Skip to content

Assignment-su/Next.js

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

6 Commits
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿฆ  Next.js

About Next.js

๐ŸŸข ๋ฆฌ์•กํŠธ๋ฅผ ํ’€์Šคํƒ์œผ๋กœ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ

* ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ : ํŠน์ • ๊ธฐ๋Šฅ ํ•˜๋‚˜์— ์ง‘์ค‘ (lke React)
* ํ”„๋ ˆ์ž„์›Œํฌ : ํ•˜๋‚˜์˜ ๊ธฐ๋Šฅ์ด ์•„๋‹Œ ์‹œ์Šคํ…œ ์ „์ฒด์˜ ๋™์ž‘์„ ๊ณ ๋ ค (like Next.js)

๐ŸŸข Next.js๋Š” ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง (Server Side Rendering)์„ ์ง€์›ํ•œ๋‹ค.

also referred to as "SSR" or "Dynamic Rendering" ๋ฆฌ์•กํŠธ์—์„œ๋Š” ๋ณ„๋„์˜ router๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

/pages ๋””๋ ‰ํ† ๋ฆฌ ํ•˜์œ„์— ์žˆ๋Š” ๊ฒฝ๋กœ(path)๊ฐ€ ๊ทธ ์ž์ฒด๋กœ ํŽ˜์ด์ง€์˜ path๊ฐ€ ๋œ๋‹ค.

/pages/home.tsx => www.example.com/home

Routhing

The Pages Router has a file-system based router built on concepts of pages.

When a file is added to the pates directory it's automatically available as a route.

Learn more about routing in the Pages Router

๐ŸŸข Next.js๋ฅผ ํ†ตํ•ด ๋ฐฑ์—”๋“œ ์ฝ”๋“œ๋„ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

/pages/api ํ•˜์œ„์— Node.js ๋ฐฑ์—”๋“œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด API๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.




1. Next.js ํ”„๋กœ์ ํŠธ ์‹œ์ž‘ํ•˜๊ธฐ

$ npx create-next-app@latest

2. ์ƒˆ๋กœ์šด ํŽ˜์ด์ง€ ์ƒ์„ฑํ•˜๊ธฐ

  • /app ํ•˜์œ„์— ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ทธ ํ•˜์œ„์— /page.jsx ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค๋ฉด ์ค‘์ฒฉ๋œ ๊ฒฝ๋กœ๋ฅผ ๊ฐ€์ง„ ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
    • /app/AAA/page.jsx => www.example.com/AAA

(1) app > news > page.jsx ์ƒ์„ฑํ•˜๊ธฐ

//๊ธฐ๋ณธ์ ์ธ ํ…œํ”Œ๋ฆฟ
import React from "react";

const News = () => {
  return <div>Hello News</div>;
};

export default News;

localhost:3000/news

๋”ฐ๋กœ ๋ผ์šฐํŠธ ์ฒ˜๋ฆฌ ํ•ด์ค„ ํ•„์š”์—†์ด path์— ๋งž์ถฐ์„œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋ฉด ๋œ๋‹ค.


  • localhost:3000/news/articles
import React from 'react';

const Articles = () => {
    return (
    	<div>
        	Hello articles
        </div>
    );
};
export default Articles;

app > news > articles > page.jsx


[๊ณต์‹๋ฌธ์„œ] Pages and Layouts

we recommend reading the Routing Fundamentsal and Defining Routes pages before continuing.

The App Router inside Next.js 13 introduced new file conventious to easily create pages, shared layouts, and templates.

This page will guide you through how to use theses special files in your Next.js application.

  • pages์™€ layouts ์˜ ์ฐจ์ด์ 

Pages

A page is UI that is uique to a route.

You can define pages by exporting a component from a page.js file.

Use nested folders to define a route and a page.js file to make the route publicly accessible.

ํŽ˜์ด์ง€๋Š” ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์ธ๋ฐ ๋ผ์šฐํŠธ์˜ ๊ณ ์œ ํ•œ ๊ฐ’์„ ๊ฐ€์ง„ ๊ฒฝ๋กœ์ด๋‹ค. (ํ•˜๋‚˜์˜ ๋ผ์šฐํŠธ์— ํ•˜๋‚˜์”ฉ ๊ณ ์œ ํ•˜๊ฒŒ ํ• ๋‹น๋œ UI ํŽ˜์ด์ง€)

// `app/page.tsx` is the UI for the `/` URL
export default function Page() {
return <h1>Hello, Home page!</h1>
}
// `app/dashboard/page.tsx` is the UI for the `/dashboard` URL
export default function Page() {
return <h1>Hello, Dashboard Page!</h1>
}

Layouts

A layout is UI that is shared between multiple routes. On navigation, layouts preserve state, remain interactive, and do not re-render. Layouts can also be nested.

You can define a layout by default exporting a React component from a layout.js file. The component should accept a children prop that will be populated with a child layout (if it exists) or a page during rendering.

์—ฌ๋ŸฌํŽ˜์ด์ง€์—์„œ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋Š” UI๋ผ๋Š” ์˜๋ฏธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๊ณตํ†ต์ ์œผ๋กœ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” NAVBAR ๋ฅผ ํŽ˜์ด์ง€ ๋ณด๋‹ค๋Š” ๋ ˆ์ด์•„์›ƒ์˜ ๊ฐœ๋…์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

export default function DashboardLayout({
children, // will be a page or nested layout
}: {
children: React.ReactNode
}) {
return (
 <section>
   {/* Include shared UI here e.g. a header or sidebar */}
   <nav></nav>

   {children}
 </section>
)
}	

3. ๋™์ ์ธ ํŽ˜์ด์ง€ ๋งŒ๋“ค๊ธฐ

  • ํŒŒ์ผ ๋ช…์„ [id].jsx ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด ์ฃผ๊ฒŒ ๋˜๋ฉด, id ๊ฐ’(ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’)์„ ๋ฐ›์•„ ๋™์ ์ธ ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค์–ด ์ค„ ์ˆ˜ ์žˆ๋‹ค.
    • /app.news/[id]/page.jsx => www.example.com/news/123
    • ์ปดํฌ๋„ŒํŠธ props๋กœ params, searchParams ์ „๋‹ฌ๋ฐ›๊ธฐ
//app\new\[id]\page.jsx
import React from "react";

const NewsIdPage = ({ params }) => {
  console.log("news id", params.id);
  return <div> hello new {params.id}</div>;
};

export default NewsIdPage;

hello new 123 => http://localhost:3000/new/123

hello new 12356 => http://localhost:3000/new/12356

  • ์ง€๊ธˆ ๋งŒ๋“ค๊ณ  ์žˆ๋Š” ํŽ˜์ด์ง€๋Š” ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง์„ ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋ธŒ๋ผ์šฐ์ € ์ฝ˜์†”์ฐฝ์€ ํด๋ผ์ด์–ธํŠธ ๋ Œ๋”๋ง์„ ํ•  ๋•Œ ๋ณด์—ฌ์ง€๋Š” ์ฝ˜์†” ์ฐฝ์ด๋‹ค.
import React from "react";

const NewsIdPage = ({ params, searchParams }) => {
  console.log("news id", params.id);
  console.log("searchParams", searchParams);
  return <div> hello new {params.id}</div>;
};

export default NewsIdPage;

http://localhost:3000/new/12356?test=abc

news id 12356
searchParams {}
 GET /new/12356 200 in 93ms
news id 12356
searchParams { test: 'abc' }
 GET /new/12356?test=abc 200 in 82ms

{ test: 'abc' ์€ ? ๋‹ค์Œ์— ๋งŒ๋“  ์ฟผ๋ฆฌ ์ŠคํŠธ๋ง ์ด๋‹ค.

key, value ํ˜•ํƒœ๋กœ ์–ด๋–ค ๊ฐ’๋“ค์„ URL์„ ํ†ตํ•ด์„œ ์ „๋‹ฌํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ ์ฟผ๋ฆฌ ์ŠคํŠธ๋ง์ด๋‹ค.

์ฟผ๋ฆฌ ์ŠคํŠธ๋ง ๊ฐ’์„ ์ปดํฌ๋„ŒํŠธ์—์„œ searchParams ์„ ํ†ตํ•ด์„œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

import React from "react";

const NewsIdPage = ({ params, searchParams }) => {
  console.log("news id", params.id);
  console.log("searchParams", searchParams);
  return (
    <div>
      hello new {params.id}
      hello new {searchParams.test}
    </div>
  );
};

export default NewsIdPage;

ํ™”๋ฉด์— ๋ณด์—ฌ์ง€๋Š” ๊ฒฐ๊ณผ๊ฐ’ : hello new 12356hello new abc

โœ“ Compiled in 75ms (277 modules)
news id 12356
searchParams { test: 'abc' }
  • params, searchParams ์„ ํ†ตํ•ด์„œ URL ์žˆ๋Š” ์ •๋ณด๋“ค์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

4. ํŽ˜์ด์ง€ ๊ฐ„ ๋งํฌ๋กœ ์—ฐ๊ฒฐํ•˜๊ธฐ

  • import Link form next/link
    • <Link href="/path">
//Next.js_project\my-app\app\page.js
import Image from "next/image";
import styles from "./page.module.css";
import Link from "next/link";

export default function Home() {
  return (
    <>
      <h1>Hello Next.js</h1>
      <Link href="/news">Go to News</Link>
    </>
  );
}
  • useRouter๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?



1. ์„œ๋ฒ„ ๋ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์…‹์—…

$ npm i prisma -save-dev
$ npx prisma init --datasource-provider sqlite
model Todo {
  id String @id @default(uuid())
  title String
}
$ npx prisma migrate dev --name init
migrations/
  โ””โ”€ 20240509010404_init/
    โ””โ”€ migration.sql
//app\db.js
//db.js ํŒŒ์ผ ์ƒ์„ฑํ•˜๊ธฐ

import { PrismaClient } from "@prisma/client";

const globalForPrisma = globalThis;

export const prisma = globalForPrisma.prisma ?? new PrismaClient();

if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;

2. ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ ๋ฐ์ดํ„ฐ ํŒจ์นญํ•˜๊ธฐ

  • ๋กœ์ปฌ DB์—์„œ ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
  • ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด๋ณด๊ธฐ
  • ์ฝ˜์†”์— ์ฐ์–ด๋ณด๊ธฐ
  • UI๋กœ ๊ทธ๋ ค๋ณด๊ธฐ
import Link from "next/link";
import { prisma } from "./db";

export default async function Home() {
  //๊ฐ„๋‹จํ•˜๊ฒŒ ๋ฐ์ดํ„ฐ ๋„ฃ์–ด์ฃผ๊ธฐ
  await prisma.todo.create({ data: { title: "ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ" } });
  const todos = await prisma.todo.findMany();
  console.log("todos", todos);
  return (
    <>
      <h1>Hello Next.js</h1>
      <Link href="/news">Go to News</Link>
    </>
  );
}
 โœ“ Compiled in 253ms (312 modules)
todos [
  { id: 'f9aa9947-5de2-4ed9-9529-0475b4d232b7', title: 'ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ' },
  { id: 'd49dd681-83f5-4560-82ce-c1628a30e28b', title: 'ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ' },
  { id: 'c22f11ab-6df1-45a0-862d-6f8398a0c82a', title: 'ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ' },
  { id: '8466642b-acd4-4ddf-ba12-d753cfe7bc3e', title: 'ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ' }
]
 GET / 200 in 210ms
  • ์—ฌ๋Ÿฌ๊ฐœ๊ฐ€ ๋“ค์–ด๊ฐ€๋Š” ์ด์œ  : ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋กœ๋”ฉํ•  ๋•Œ๋งˆ๋‹ค create ๋กœ์ง์ด ์‹คํ–‰์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋•Œ๋งˆ๋‹ค ํ•˜๋‚˜์”ฉ ๊ณ„์† ์Œ“์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
import Link from "next/link";
import { prisma } from "./db";

export default async function Home() {
  //๊ฐ„๋‹จํ•˜๊ฒŒ ๋ฐ์ดํ„ฐ ๋„ฃ์–ด์ฃผ๊ธฐ
  //await prisma.todo.create({ data: { title: "ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ" } });
  const todos = await prisma.todo.findMany();
  console.log("todos", todos);
  return (
    <>
      <h1>Hello Next.js</h1>
      <Link href="/news">Go to News</Link>
      {/* ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์—์„œ ๋ถˆ๋Ÿฌ์˜จ ๋ฐ์ดํ„ฐ๋“ค์„ map์„ ํ†ตํ•ด ๋กœ์ง์„ ๊ทธ๋ ค๋‚˜๊ฐˆ ์ˆ˜ ์žˆ๋‹ค. */}
      {todos.map((todo) => (
        <h1>{todo.title}</h1>
      ))}
    </>
  );
}
//ํ™”๋ฉด์— ๋ณด์ด๋Š” ๊ฒฐ๊ณผ๊ฐ’ 

Hello Next.js
Go to News
ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ
ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ
ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ
ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ

state๊ฐ€ ์•„๋‹ˆ๋ผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ฐ’์„ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กœ๊ณ ์นจ์„ ํ•ด๋„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ’์ด ๊ทธ๋Œ€๋กœ ๋‚จ์•„์žˆ๊ฒŒ ๋œ๋‹ค.

๋งŒ์•ฝ await prisma.todo.create({ data: { title: "ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ" } }); create ๋กœ์ง์„ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ๋  ๋•Œ๋งˆ๋‹ค ํ•˜๋‚˜์”ฉ ์ถ”๊ฐ€๊ฐ€ ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

โญ ์„œ๋ฒ„์‚ฌ์ด๋“œ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ์ดํ„ฐ ํŒจ์นญ์„ ์–ด๋–ป๊ฒŒ ํ•˜๋Š”์ง€ ํ๋ฆ„ ๊ธฐ์–ตํ•˜๊ธฐ


Rendering ๋ Œ๋”๋ง

๋ Œ๋”๋ง์€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๊ฐ€ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ „ํ™˜์‹œ์ผœ์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

๋ Œ๋”๋ง์˜ ํ™˜๊ฒฝ์€ ํฌ๊ฒŒ Client์™€ Server ๋‘ ํƒ€์ž…์œผ๋กœ ๋‚˜๋ˆ ์ ธ์„œ ์„ค๋ช…์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

  • Client ๋ Œ๋”๋ง : ๋””๋ฐ”์ด์Šค์— ์žˆ๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์„œ๋ฒ„ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ๋ฐ›์•„์„œ UI๋ฅผ ๊ทธ๋ ค์ฃผ๋Š” ๋ฐฉ์‹
  • Server ๋ Œ๋”๋ง : ์ปดํ“จํ„ฐ๊ฐ€ ์šฐ๋ฆฌ๋“ค์˜ ์ฝ”๋“œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅ์„ ํ•˜๊ณ  ์žˆ๊ณ  ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ์š”์ฒญ์„ ๋ฐ›์•˜์„ ๋•Œ ๊ทธ ์—ฐ์‚ฐ์„ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‚ด์—์„œ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ ์‘๋‹ต์„ ์ฃผ๋Š” ๋ฐฉ์‹
    • ํ•ด๋‹น ์„œ๋ฒ„์•ˆ์—์„œ ์ด๋ฏธ ๋ฐ์ดํ„ฐ ์‘๋‹ต ์š”์ฒญ์„ ๋‹ค ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

Data Fetching ๋ฐ์ดํ„ฐ ํŒจ์นญ

์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ†ตํ•ด์„œ ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ ํŒจ์นญ์„ ํ•œ๋‹ค. ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋“ค์„ ๋™์‹œ์— ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ๋ฐ์ดํ„ฐ ํŒจ์นญ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํญํฌ์ˆ˜ ์ฒ˜๋Ÿผ ์—ฐ์‡„์ ์œผ๋กœ ์ผ์–ด๋‚˜๋ฉด์„œ ๋กœ๋”ฉํƒ€์ž„์ด ๊ธธ์–ด์ง€๋Š” ์ผ๋“ค์„ ์ตœ์†Œํ™”ํ•œ๋‹ค.

์š”์ฒญ์„ ํŠธ๋ฆฌ ํ˜•ํƒœ๋กœ ๋ณต์ œ๋ฅผ ํ•œ๋‹ค. ํ™”๋ฉด์„ ๋กœ๋”ฉํ•˜๋Š” ๊ณผ์ •์—์„œ Streaming and Susepense๋ฅผ ํ†ตํ•ด์„œ ํŽ˜์ด์ง€๋ฅผ ๋ Œ๋”๋ง์„ ํ•œ๋‹ค. (์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ๋น ๋ฅด๊ฒŒ ํ™”๋ฉด์„ ๋ณด์—ฌ์งˆ ์ˆ˜ ์žˆ๋„๋ก )

Releases

No releases published

Packages

No packages published