๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

React

[ Next.js ] Next13์˜ ์ฃผ์š” ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

VercelํŒ€์ด Next.js์˜ 13๋ฒ„์ „์ด 2022๋…„ 10์›” 26์ผ Next.js ๊ณต์‹ ํŽ˜์ด์ง€์— ์†Œ๊ฐœ๋˜์—ˆ์ง€๋งŒ,

์ž์„ธํžˆ ์‚ดํŽด๋ณด์ง€๋ฅผ ์•Š์•˜๋Š”๋ฐ ์ƒˆ๋กœ ์ด์งํ•˜๊ฒŒ๋œ ํšŒ์‚ฌ์—์„œ Next13์œผ๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒˆ๋กœ ์„ธํŒ…ํ•˜๊ธฐ๋กœ ์ด์•ผ๊ธฐ๊ฐ€ ๋˜์–ด

๊ณต์‹ ๋ธ”๋กœ๊ทธ ๋‚ด์šฉ์„ ์‚ดํŽด๋ณด์•˜๋‹ค.

 

 

 

 

++Next.js 13.4(ํ˜„์žฌ ๊ธฐ์ค€ ์ตœ์‹  ๋ฒ„์ „)์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์•„๋ž˜์˜ ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด ์„ค์น˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

npm i next@latest react@latest react-dom@latest eslint-config-next@latest

 

 

 

 

์•ฑ ๋ผ์šฐํŒ… (App Directory) - Next.13.4(ํ˜„์žฌ)๊ธฐ์ค€ Stable

๊ธฐ์กด์— pages/ ๋””๋ ‰ํ† ๋ฆฌ์—์„œ ๋ผ์šฐํŒ… ๋˜๋˜ ๋ฐฉ์‹๊ณผ ๋‹ค๋ฅด๊ฒŒ, app/ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ๋ผ์šฐํŒ… ํ•˜๋Š” ๋ฐฉ์‹์ด ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.

- Tree : ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ์‹œ๊ฐํ™” ํ•˜๊ธฐ์œ„ํ•œ ๊ทœ์น™์œผ๋กœ, ์˜ˆ๋ฅผ ๋“ค์–ด ์ƒ์œ„ ๋ฐ ํ•˜์œ„ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ, ํด๋” ๊ตฌ์กฐ์ด๋‹ค.

 

- Subtree : ์ƒˆ ๋ฃจํŠธ(์ฒ˜์Œ)์—์„œ ์‹œ์ž‘ํ•˜์—ฌ ์žŽ(๋งˆ์ง€๋ง‰)์—์„œ ๋๋‚˜๋Š” ํŠธ๋ฆฌ์˜ ์ผ๋ถ€์ด๋‹ค.

 

- Root : ๋ฃจํŠธ ๋ ˆ์•„์ด์›ƒ๊ณผ ๊ฐ™์€ ํŠธ๋ฆฌ ๋˜๋Š” ํ•˜์œ„ ํŠธ๋ฆฌ์˜ ์ฒซ ๋ฒˆ์งธ ๋…ธ๋“œ์ด๋‹ค.

 

- Leaf: ํ•˜์œ„ ํŠธ๋ฆฌ์— ํ•˜์œ„ ํ•ญ๋ชฉ์ด ์—†๋Š” ๋…ธ๋“œ(์˜ˆ: URL ๊ฒฝ๋กœ์˜ ๋งˆ์ง€๋ง‰ segment.)

 

 

 

๊ธฐ์กด์˜ pages ๋ผ์šฐํ„ฐ ๋ฐฉ์‹

/ Pages Router
// pages/about.js

import React from 'react';
export default () => <h1>About us</h1>;

 

 

์ƒˆ๋กœ์šด ์•ฑ ๋ผ์šฐํ„ฐ ๋ฐฉ์‹

// New: App Router โœจ
// app/layout.js
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

// app/page.js
export default function Page() {
  return <h1>Hello, Next.js!</h1>;
}

 

 

 

 

 

 

1. Layouts

https://nextjs.org/blog/next-13#layouts

 

์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๊ณ , ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•˜๋ฉด์„œ ๊ฒฝ๋กœ ๊ฐ„์— UI๋ฅผ ์‰ฝ๊ฒŒ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์•„๋ž˜์˜ ํŒŒ์ผ ์‹œ์Šคํ…œ์„ ํ†ตํ•ด ๋ ˆ์ด์•„์›ƒ์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ ˆ์ด์•„์›ƒ์€ ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€ ๊ฐ„์˜ UI ๋ฅผ ๊ณต์œ ํ•œ๋‹ค.

๋„ค๋น„๊ฒŒ์ด์…˜ ์ƒ์—์„œ, ๋ ˆ์ด์•„์›ƒ์€ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๊ณ , ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ฆฌ๋ Œ๋”๋ง ํ•˜์ง€ ์•Š๋Š”๋‹ค.

// app/page.js
// This file maps to the index route (/)
export default function Page() {
  return <h1>Hello, Next.js!</h1>;
}
// app/blog/layout.js
export default function BlogLayout({ children }) {
  return <section>{children}</section>;
}

 

 

 

 

2. React Server Components

๊ฐ€์žฅ ๋™์ ์ธ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์— ๋Œ€ํ•ด ์„œ๋ฒ„ ์šฐ์„ (server-first)์„ ๊ธฐ๋ณธ๊ฐ’(default)์œผ๋กœ ์„ค์ •ํ•œ๋‹ค.

app/ ๋””๋ ‰ํ† ๋ฆฌ๋Š” React์˜ ์ƒˆ๋กœ์šด Server Components ์•„ํ‚คํ…์ณ๋ฅผ ์ง€์›ํ•œ๋””. ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์™€ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋Š” ๊ฐ๊ฐ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ฐ€์žฅ ์ ํ•ฉํ•œ ์ผ์— ์‚ฌ์šฉ๋˜๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜์„ ํ–ฅ์ƒ์‹œํ‚ค๊ณ  ๋น ๋ฅด๊ณ  ๋งค์šฐ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒํ•œ ์•ฑ์„ ๋‹จ์ผ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ชจ๋ธ๋กœ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์„œ๋ฒ„ ๊ตฌ์„ฑ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ๋ณต์žกํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋™์‹œ์— ํด๋ผ์ด์–ธํŠธ๋กœ ์ „์†ก๋˜๋Š” JavaScript์˜ ์–‘์„ ์ค„์—ฌ, ์ดˆ๊ธฐ ํŽ˜์ด์ง€ ๋กœ๋“œ ์†๋„๋ฅผ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค.

 

๊ฒฝ๋กœ(route)๊ฐ€ ๋กœ๋“œ๋  ๋•Œ, Next.js ๋ฐ React ๋Ÿฐํƒ€์ž„์ด ๋กœ๋“œ๋˜์–ด ์บ์‹œ๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ณ  ํฌ๊ธฐ๋ฅผ ์˜ˆ์ธกํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ๋Ÿฐํƒ€์ž„์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ปค์ ธ๋„ ํฌ๊ธฐ๊ฐ€ ์ฆ๊ฐ€ํ•˜์ง€ ์•Š๊ณ , ๋น„๋™๊ธฐ๋กœ ๋กœ๋“œ๋˜์–ด ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ HTML์ด ํด๋ผ์ด์–ธํŠธ์—์„œ ์ ์ง„์ ์œผ๋กœ ๊ฐœ์„ ๋  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

 

 

 

 

 

 

3. Streaming

๋ Œ๋”๋ง ์‹œ ์ฆ‰์‹œ ๋กœ๋“œ ์ƒํƒœ ๋ฐ ์ŠคํŠธ๋ฆผ์„ UI๋‹จ์œ„๋กœ ํ‘œ์‹œํ•œ๋‹ค. app/ ๋””๋ ‰ํ† ๋ฆฌ๋Š” UI์˜ ๋ Œ๋”๋ง ๋‹จ์œ„๋ฅผ ์ ์ง„์ ์œผ๋กœ ๋ Œ๋”๋งํ•˜๊ณ  ๋ Œ๋”๋ง๋œ ๋‹จ์œ„๋ฅผ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ถ€๋ถ„์ ์œผ๋กœ ์ŠคํŠธ๋ฆฌ๋ฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

 

Next.js์˜ Server Components์™€ ์ค‘์ฒฉ๋œ ๋ ˆ์ด์•„์›ƒ์„ ์‚ฌ์šฉํ•˜๋ฉด, ๋ฐ์ดํ„ฐ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ํ•„์š”๋กœํ•˜์ง€ ์•Š๋Š” ํŽ˜์ด์ง€ ๋ถ€๋ถ„์„ ์ฆ‰์‹œ ๋ Œ๋”๋งํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ํŽ˜์ด์ง€ ๋ถ€๋ถ„์—๋Š” ๋กœ๋”ฉ ์ƒํƒœ๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ฐฉ์‹์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž๋Š” ์ „์ฒด ํŽ˜์ด์ง€๊ฐ€ ๋กœ๋“œ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆด ํ•„์š” ์—†์ด, ์ฆ‰์‹œ ์ƒํ˜ธ ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

https://nextjs.org/blog/next-13#streaming

 

 

Vercel์— ๋ฐฐํฌ๋œ Next.js 13 ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ app/ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ๊ธฐ๋ณธ์ ์œผ๋กœ ์‘๋‹ต์„ ์ŠคํŠธ๋ฆฌ๋ฐํ•˜์—ฌ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚จ๋‹ค. ์ด ์ŠคํŠธ๋ฆฌ๋ฐ์€ Node.js ๋ฐ Edge ๋Ÿฐํƒ€์ž„์—์„œ ๋ชจ๋‘ ์ ์šฉ๋œ๋‹ค.

 

 

 

 

 

 

 

 

 

 

 

Turbopack (Beta - Next.js 13.4 ํ˜„์žฌ ๊ธฐ์ค€)

์ตœ๋Œ€ 700๋ฐฐ ๋น ๋ฅธ Rust๊ธฐ๋ฐ˜ Webpack ๋Œ€์ฒด.

Vite๋ณด๋‹ค 10๋ฐฐ ๋น ๋ฅด๋‹ค.

https://nextjs.org/blog/next-13#introducing-turbopack-alpha

 

 

 

New next/image

native ๋ธŒ๋ผ์šฐ์ €์˜ ๋Š๋ฆฐ ๋กœ๋”ฉ์œผ๋กœ ๋”์šฑ ๋นจ๋ผ์ง.

Next.js 13 ์—์„œ๋Š” ๊ฐ•๋ ฅํ•œ ์ƒˆ๋กœ์šด Image ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋„์ž…ํ•˜์—ฌ ๋ ˆ์ด์•„์›ƒ ๋ณ€๋™ ์—†์ด ์ด๋ฏธ์ง€๋ฅผ ์‰ฝ๊ฒŒ ํ‘œ์‹œํ•˜๊ณ , ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ํŒŒ์ผ์„ ์š”์ฒญ์— ๋”ฐ๋ผ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

import Image from 'next/image';
import avatar from './lee.png';

function Home() {
  // "alt" is now required for improved accessibility
  // optional: image files can be colocated inside the app/ directory
  return <Image alt="leeerob" src={avatar} placeholder="blur" />;
}

 

 

 

์ฃผ์š”ํŠน์ง• 

  • ํด๋ผ์ด์–ธํŠธ ์ธก JavaScript๊ฐ€ ๋” ์ ๊ฒŒ ํฌํ•จ๋˜์—ˆ๋‹ค.
  • ์Šคํƒ€์ผ๋ง๊ณผ ๊ตฌ์„ฑ์ด ๋” ์‰ฝ๋‹ค.
  • ๊ธฐ๋ณธ์ ์œผ๋กœ altํƒœ๊ทธ๊ฐ€ ํ•„์š”ํ•˜์—ฌ ์ ‘๊ทผ์„ฑ์ด ๊ฐœ์„ ๋œ๋‹ค.
  • ์›น ํ”Œ๋žซํผ๊ณผ ์ผ์น˜ํ•œ๋‹ค.
  • ๋„ค์ดํ‹ฐ๋ธŒ ๋ ˆ์ด์ง€ ๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ์ด ๋นจ๋ผ ์ˆ˜๋ถ„ํ™”(hydration)๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค.

 

 

 

 

 

 

 

 

 

New @next/font

๋ ˆ์ด์•„์›ƒ ์ด๋™์ด ํ•„์š” ์—†๋Š” ์ž๋™ ์ž์ฒด ํ˜ธ์ŠคํŒ… ํฐํŠธ.

import { Inter } from '@next/font/google';

const inter = Inter();

<html className={inter.className}>
import localFont from '@next/font/local';

const myFont = localFont({ src: './my-font.woff2' });

<html className={myFont.className}>

Next.js 13์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒˆ๋กœ์šด ํฐํŠธ ์‹œ์Šคํ…œ์„ ๋„์ž…ํ–ˆ๋‹ค.

  • ์‚ฌ์šฉ์ž ์ •์˜ ํฐํŠธ๋ฅผ ํฌํ•จํ•œ ํฐํŠธ๋ฅผ ์ž๋™์œผ๋กœ ์ตœ์ ํ™”ํ•œ๋‹ค.
  • ๊ฐœ์ธ ์ •๋ณด ๋ณดํ˜ธ์™€ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ์™ธ๋ถ€ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ์ œ๊ฑฐํ•œ๋‹ค.
  • ํฐํŠธ ํŒŒ์ผ์— ๋Œ€ํ•œ ๋‚ด์žฅ ์ž๋™ ์…€ํ”„ ํ˜ธ์ŠคํŒ… ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.
  • CSS์˜ size-adjust ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž๋™์œผ๋กœ ๋ ˆ์ด์•„์›ƒ ๋ณ€๋™์„ ์ œ๊ฑฐํ•œ๋‹ค.

 

์ด๋Ÿฐ ์ƒˆ๋กœ์šด ํฐํŠธ ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ๊ณผ ๊ฐœ์ธ ์ •๋ณด ๋ณดํ˜ธ๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ๋ชจ๋“  Google Font๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. CSS์™€ ํฐํŠธ ํŒŒ์ผ์€ ๋นŒ๋“œ ์‹œ๊ฐ„์— ๋‹ค์šด๋กœ๋“œ ๋˜๋ฉฐ, static assets๊ณผ ํ•จ๊ป˜ ์ž์ฒด ํ˜ธ์ŠคํŒ… ๋œ๋‹ค. ๋ธŒ๋ผ์šฐ์ €์—์„œ Google๋กœ ์š”์ฒญ์ด ์ „์†ก๋˜์ง€ ์•Š๋Š”๋‹ค.

 

 

 

 

 

 

Improved next/link

 

์ž๋™ <a>๋ฅผ ๊ฐ์‹ธ๋Š” ๋‹จ์ˆœํ™”๋œ API

next/link๋Š” ๋” ์ด์ƒ ์ˆ˜๋™์œผ๋กœ <a>ํƒœ๊ทธ๋ฅผ ํ•˜์œ„๋กœ ์ถ”๊ฐ€ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. Next.js 13์—์„œ <Link>๋Š” ํ•ญ์ƒ <a>๋ฅผ ๋ Œ๋”๋งํ•œ๋‹ค.

 

import Link from 'next/link'

// Next.js 12: `<a>` has to be nested otherwise it's excluded
<Link href="/about">
  <a>About</a>
</Link>

// Next.js 13: `<Link>` always renders `<a>`
<Link href="/about">
  About
</Link>

 

 

 

 

 

 


 

๐ŸŒธ ์ถœ์ฒ˜ ๐ŸŒธ

 

nextjs.org-Blog

nextjs.org-Using App Router Docs