Next 13
Next 13
๋ฒ์ ์
์ด ๋๋ฉด์ ๊ธฐ์กด ํ๋ก์ ํธ๋ฅผ ๋ง์ด๊ทธ๋ ์ด์
ํ๋ ๊ฒฝ์ฐ Breaking Changes
๋ก ์ธํด ์ ๋ฐ์ ์ผ๋ก ๋ณ๊ฒฝ์ฌํญ์ ๋ง์ถฐ ์
๊ทธ๋ ์ด๋๋ฅผ ํด์ค์ผ ํ๋ค.
Next๋ ์ด๊ฒ์ ๋ฐฉ์งํ๊ณ ์ ์๋ก ์ถ๊ฐ๋ ๊ธฐ๋ฅ๊ณผ ๊ท์น๋ค์ app/
์ ์ ์ฉํ์ฌ ๊ธฐ์กด page/
๊ตฌ์กฐ์ ์ฑ์ด ๋ง๊ฐ์ง์ง ์๊ณ ์ ์ง์ ์ผ๋ก ๋ง์ด๊ทธ๋ ์ด์
ํ ์ ์๋๋ก ์ ๊ณตํ๋ค.
Routing
app
โโโ api
โ โโโ hello
โ โโโ route.ts
โโโ layout.tsx
โโโ page.tsx
โโโ product
โโโ [slug]
โ โโโ page.tsx
โโโ layout.tsx
โโโ page.tsx
๋งค์นญํ ๊ฒฝ๋ก๋ฅผ ํด๋ ์ด๋ฆ์ผ๋ก ๋๊ณ ํ์์ page
์ปดํฌ๋ํธ ํ์ผ์ ๋๋ฉด ์๋์ผ๋ก ๋ผ์ฐํ
๋๋ค.
ํด๋(๊ฒฝ๋ก)๋ณ๋ก ๋ฒ์๋ฅผ ์ขํ ์ฌ์ฌ์ฉ๋๋ ๋ ์ด์์
, ์๋ฌ ์ํ
, ๋ก๋ฉ UI
๋ฑ์ ๊ณต์ ํ์ฌ ํด๋น ๋ผ์ฐํธ ์์์ ์ฒ๋ฆฌํด์ฃผ๊ธฐ ์ํจ
page/
โapp/
Folder & File based routing
Dynamic Routing
// app/[slug]/page.tsx
interface DynamicPageProps {
params: {
slug: string;
}
}
export default function DynamicPage({ params }: DynamicPageProps) {
return `slug: ${params.slug}`;
}
generateStaticParams()
generateStaticParams()
์ด์ ๋ฒ์ ์ getStaticPaths()
๋ฅผ ๋์ฒดํ๋ ํจ์
๋ฏธ๋ฆฌ ์์ฑํ ํ์ด์ง์ ๋์ ๊ฒฝ๋ก(slug)๋ฅผ ์ง์ ํ๊ณ { slug: value } ๊ตฌ์กฐ์ ๋ฐฐ์ด์ ๋ฐํํ๊ธฐ๋ง ํ๋ฉด ๋๋ค.
export function generateStaticParams() {
const slugs = ['a', 'b'];
return slugs.map((slug) => {
slug,
})
}
Layout
๋ ์ด์์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์๋ฒ ์ปดํฌ๋ํธ(๋ณ๊ฒฝ ๊ฐ๋ฅ)
๊ฐ์ ๊ฒฝ๋ก ๋ฐ ํ์ ๊ฒฝ๋ก์ ํ์ด์ง์ ๊ณต์ ๋๋ฉฐ ๋ํ๋๋ค. โ ๋ ์ด์์(์ปดํฌ๋ํธ)
๊ฒฝ๋ก ๋ณ๋ก ๋ ์ด์์์ ์ง์ ๊ฐ๋ฅํ๋ฉฐ ์์์ ์๋ ๋ ์ด์์์ ์ค์ฒฉ๋์ด ์ ์ฉ๋๋ค.
๋ฐ์ดํฐ ํจ์นญ์ด ๊ฐ๋ฅํ๋ฉฐ ๋ ์ด์์๊ฐ ์ ๋ฌ์ด ๋ถ๊ฐ๋ฅํ์ง๋ง ๊ฒฝ๋ก๊ฐ ๊ฐ์ ๊ฒฝ์ฐ ๊ฐ ๋ ์ด์์์ด ์ค๋ณต์ผ๋ก ๋ฐ์ดํฐ ํจ์นญ์ React๊ฐ ์์์ ์ค๋ณต๋ ์์ฒญ์ ์ ๊ฑฐํ๋ค.
Root Layout (ํ์)
app/
๋ด์์ ๊ฐ์ฅ ์์์ ์๋ layout.tsx
๋ฅผ ๋ฃจํธ ๋ ์ด์์์ด๋ผ ์นญํ๋ฉฐ ๋ชจ๋ ํ์ด์ง์ ๋ํ๋๋ค.
์ด์ ๋ฒ์ ์
_app.tsx
,_document.ts ๋ฅผ ๋์ฒดํ๋ค.
์๋ฒ์์ ๋ฐํ๋ ์ด๊ธฐ HTML์ ์์ ํ ์ ์๋ค
Next.js๊ฐ ์๋์ผ๋ก
<html>
,<body>
๋ฅผ ์์ฑํ์ง ์์ผ๋ฏ๋ก ๋ฃจํธ ๋ ์ด์์์ ํด๋น ํ๊ทธ๋ฅผ ์ ์ํด์ผ ํ๋ค.
Not Found Page
์ปค์คํ
404 page๋ฅผ ๋ง๋๋ ค๋ฉด ํ์ผ์ด๋ฆ์ not-found
๋ก ์ง์ ํด์ผ ํ๋ค.
ํด๋(๊ฒฝ๋ก)๋ด์ ๊ฐ์ฅ ๊ฐ๊น์ด not-found
ํ์ผ์ด ์ฌ์ฉ๋์ด ํ์ด์ง ๋ณ๋ก ์๋ฌ ํ์ด์ง๋ฅผ ์ค์ ๊ฐ๋ฅ
ํ์ฌ ์์ ์๋ notFound()
ํธ์ถ์ ์ํด ํธ๋ฆฌ๊ฑฐ๋ ๋๋ง ๋ ๋๋ง๋๋ค.
Global Not Found Page
ํ ์์ 13.2.4
๋ฒ์ ์์๋ Global Not Found Page ๊ธฐ๋ฅ์ด app/
๋ผ์ฐํ
์์๋ ์์ง ์ ๊ณต๋์ง ์๊ณ ์๋ค.
Global Not Found Page๋ฅผ ๊ตฌํํ๋ ค๋ฉด?
๊ธฐ์กด ๋ฐฉ์๋๋ก
page/
ํ์์404.tsx
์ปดํฌ๋ํธ๋ฅผ ์ถ๊ฐํด ์ฌ์ฉapp/ ๋ด์์
๋์ ๋ผ์ฐํ ์ ํ์ฉํ์ฌ ๊ตฌํ
์ฐํํด์ app/
๋ผ์ฐํ
์ผ๋ก Global Not Found Page ๊ตฌํํ๊ธฐ
์ฐํํด์ app/
๋ผ์ฐํ
์ผ๋ก Global Not Found Page ๊ตฌํํ๊ธฐโโโ [...not-found]
โ โโโ page.tsx
โโโ not-found.tsx
// app/[...not-found]/page.tsx
import {notFound} from 'next/navigation';
export default function NotFoundCatchAll() {
notFound();
}
Metadata
์ด๋ค ํ์ด์ง(or ๋ ์ด์์)์์๋ ๊ฐ์ฒด ํํ๋ก ๋ metadata
๋ณ์๋ฅผ export
ํด์ฃผ๊ธฐ๋ง ํ๋ฉด ๋๋ค.
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'ํ์ดํ',
}
Dynamic Metadata
generateMetadata()
ํจ์๋ฅผ ํตํด ๋น๋๊ธฐ ๋ฐ์ดํฐ๋ฅผ ํจ์นญ ํ ๋ฉํ๋ฐ์ดํฐ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
generateMetadata()
ํจ์๋ฅผ ํตํด ๋น๋๊ธฐ ๋ฐ์ดํฐ๋ฅผ ํจ์นญ ํ ๋ฉํ๋ฐ์ดํฐ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.์ฌ์ฉ์์๊ฒ ํ์ด์ง๋ฅผ ์ฃผ๊ธฐ ์ generateMetadata()
ํธ์ถ๋๊ณ ๋ฉํ๋ฐ์ดํฐ ์ ๋ณด๊ฐ ์์ฑ ๋์ด์ผ์ง๋ง ํ์ด์ง๋ฅผ ์ ์กํ๋ค.
export async function generateMetadata({ params, searchParams }) {
const data = await getData(params); // ๋น๋๊ธฐ ๋ฐ์ดํฐ ํจ์นญ
return { title: data.title };
}
Default Metadata
๋ฐ๋ก ์ถ๊ฐํ์ง ์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ค์ ๋๋ ๋ฉํํ๊ทธ
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
Rendering
๋ ๋๋ง ๋ฐฉ์์ด (page/) ํ์ด์ง ๋จ์ -> (app/) ์ปดํฌ๋ํธ ๋จ์๋ก ๋ณ๊ฒฝ๋์๋ค.
๊ธฐ์กด page ๋จ์ ๋ ๋๋ง ๋ฐฉ์์ ๋ฌธ์ ์
ํ์ด์ง ๋จ์์ ๋ ๋๋ง ๋ฐฉ์์ ์ฑ์ ๊ท๋ชจ๊ฐ ์ปค์ง์๋ก ํด๋ผ์ด์ธํธ๊ฐ ๋ฐ๋ ๋ฒ๋ค ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๊ฐ ์ปค์ง๋ ๋ฌธ์ ๊ฐ ์์๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด React 18 ๋ฒ์ ์ ๋ง์ถฐ ์๋ฒ ์ปดํฌ๋ํธ, ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ๊ตฌ๋ถํ์ฌ ๋ ๋๋ง ํ๋ ๋ฐฉ์์ด ๋์ ๋์๋ค.
์ปดํฌ๋ํธ ๋จ์ ๋ ๋๋ง ๋ฐฉ์์ ์ฅ์
ํ๋์ ํ์ด์ง ์์์ ์ฌ๋ฌ ์ปดํฌ๋ํธ๋ฅผ ๊ฐ๊ธฐ ๋ค๋ฅธ ๋ ๋๋ง ๋ฐฉ์์ ๊ท์ ํด ์กฐํฉํ์ฌ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
์๋ฒ ์ปดํฌ๋ํธ๋ ์๋ฒ์์๋ง ์์ ์ด ์ด๋ฃจ์ด์ง๊ณ ์๋ฒ์์ ๋ ๋๋ง๋์ด ํด๋ผ์ด์ธํธ์๊ฒ ๋ณด๋ผ ์ฝ๋๊ฐ ์๊ธฐ ๋๋ฌธ์ ํด๋ผ์ด์ธํธ๊ฐ ๋ฐ์ ๋ฒ๋ค ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๊ฐ ํ์ ํ ์ค์ด๋ค๊ฒ ๋๋ค.
์ฆ, ์ฌ์ฉ์์ ์ธํฐ๋ ์ ์ด ํ์ํ ์ฝ๋๋ง ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌ๋์ด ์ด๊ธฐ ๋ก๋ฉ ์๋๊ฐ ๋์ฑ ๋นจ๋ผ์ง๊ฒ ๋๋ค.
React v18์์ ์๋กญ๊ฒ ์ถ๊ฐ๋ ๊ธฐ๋ฅ
์๋ฒ์์์ ๋ฆฌ์กํธ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๊ฒ ๋์๋ค.
์๋ฒ์์์๋ง ๋์ํ๋ ์ปดํฌ๋ํธ
SSR !== RSC, ์๋ก ๋์ฒด์ ๊ฐ ์๋๋ฉฐ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํค๊ธฐ ์ํด ์๋ก ๋ณด์ํ์ฌ ์ฌ์ฉ๋๋ ๊ฒ
ํ๋ฆฌ ๋ ๋๋ง(SSR) + ๋ฒ๋ค์ฌ์ด์ฆ ์ต์ํ(RSC)
app/
๋ด์ ๋ชจ๋ ์ปดํฌ๋ํธ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์๋ฒ ์ปดํฌ๋ํธ์ด๋ค.์๋ฒ์์ ๋น๋ ๋ ๋ ์คํ๋๋ ์ปดํฌ๋ํธ, ๊ธฐ๋ณธ์ ์ผ๋ก SSG
์ ์ ์ธ HTML ํํ๋ก ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌ๋๋ฉฐ ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌ๋๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ Zero
๋ธ๋ผ์ฐ์ ์์ ์ ๊ณตํ๋ API, Hooks๋ฅผ ์ฌ์ฉํ ์ ์์ง๋ง node.js(์๋ฒ)์์ ์ ๊ณตํ๋ API๋ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
์๋ฒ ์ปดํฌ๋ํธ์์ ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ ๋ ์ ์ญ ์ฑ๊ธํค๊ณผ ๊ฐ์ ๋ค์ดํฐ๋ธ ์๋ฐ์คํฌ๋ฆฝํธ ํจํด์ ํ์ฉ
์๋ฒ ์ปดํฌ๋ํธ ๊ฐ์ ์๋ฒ(DB)์์ ํจ์นญํ ๋ฐ์ดํฐ ์์์ ๊ณต์ ํ๊ณ ์ถ์ ๋๋ ๋ฐ์ดํฐ๋ฅผ ๋ถํ์ํ๊ฒ ์ ๋ฌํ ํ์ ์์ด ๊ทธ ๋ฐ์ดํฐ๋ฅผ ํ์๋ก ํ๋ ๊ณณ์์ ํจ์นญํ๋ฉด ๋๋ค. ๊ฐ์ ธ์จ ๋ฐ์ดํฐ๋ ์บ์ฑ ๋์ด ๋ฅ์คํธ์์ ์ค๋ณต ์์ฒญ์ ์ ๊ฑฐํ๋ ์์ผ๋ก ์ต์ ํ๊ฐ ์๋์ผ๋ก ์ด๋ฃจ์ด์ง๋ค.
Client Component
์ด์ ๋ฒ์ ์์ ์ฌ์ฉํ๋ ํ๋ฆฌ๋ ๋๋ง + ํ์ด๋๋ ์ด์ ๋ฐฉ์
๋ํดํธ๊ฐ ์๋ฒ์ปดํฌ๋ํธ์ด๊ธฐ ๋๋ฌธ์ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ์ฌ์ฉํ๊ธฐ ์ํด์๋ ์๋จ์
use client
๋ฅผ ๋ช ์ํด์ฃผ์ด์ผ ํ๋ค.ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ผ๊ณ ํด์ ๋ฌด์กฐ๊ฑด
csr
๋ก ๋์ํ๋ ๊ฒ์ด ์๋๋ค.์๋ฒ์์ ์ปดํฌ๋ํธ๋ฅผ ์ฝ๊ณ ์ ์ ์ธ ๋ถ๋ถ์ ๋ถ๋ฆฌํ์ฌ ํ๋ฆฌ๋ ๋๋ง์ ํฌํจ์ํค๊ณ ํ์ด๋๋ ์ด์ ๊ณผ์ ์ด ์ผ์ด๋๋ค. (๊ธฐ์กด ๋ฐฉ์๊ณผ ๋์ผ)
์ฌ์ฉ์์ ์ด๋ฒคํธ๊ฐ ์๊ฑฐ๋ ๋ธ๋ผ์ฐ์ ์์ ์คํ๋์ด์ผ ํ๋ ์ฝ๋๋ค์ด ์๋ค๋ฉด ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์ด๋ค.
์ฆ, ์ฌ์ฉ์(๋ธ๋ผ์ฐ์ )์๊ฒ ๋ณด๋ด์ ธ์ผ ํ๋ ์ฝ๋๋ค์ด ๋ด๊ธด ์ปดํฌ๋ํธ
์ํ๋ฅผ ์ฐ๊ฑฐ๋ hooks๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ์ฌ์ฉํด์ผ ํ๋ค.
์๋ฒ ์ปดํฌ๋ํธ์์ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ์ ๋ฌํ๋ props๋ serialization(์ง๋ ฌํ)๊ฐ ๊ฐ๋ฅํด์ผ ํ๋ค.
ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ์ฌ์ฉ๋๋ ๋ชจ๋, ํ์ ์ปดํฌ๋ํธ๋ค์ ๋ชจ๋ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๊ฐ ๋๋ค.
ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ์๋ฒ ์ปดํฌ๋ํธ๋ฅผ ์ํฌํธํด์ ์ฌ์ฉํ ์ ์๋ค.
๋ฐ๋ผ์ ๊ฐ๋ฅํ๋ค๋ฉด ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ ์ปดํฌ๋ํธ Tree์์ ๊ฐ์ฅ ๋๋จ์ ์์นํ๋ leaf๋ก ์ด๋์ํค๋ ๊ฒ์ด ์ข๋ค.
๋ถ๊ฐํผํ ๊ฒฝ์ฐ ๋ฅ์คํธ์์ ์ปดํฌ์ง์ ํจํด(์์ ์ปดํฌ๋ํธ๋ฅผ props๋ก ์ ๋ฌํ์ฌ ์์ ์ปดํฌ๋ํธ๋ฅผ ์กฐํฉํ๋ ํจํด)์ ํ์ฉํ ๊ฒ์ ๊ถ๊ณ ํ๋ค.
์๋ฒ ์ปดํฌ๋ํธ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ ๊ตฌ๋ถํ๊ธฐ
์ฌ์ฉ์์๊ฒ ์ ๋ฌ ๋์ด์ผ ํ๋ ์ฝ๋๊ฐ ํฌํจ๋ ๊ฒฝ์ฐ๋ง ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ๋ง๋ค์ด ์ฑ๋ฅ์ ๋์ด์.
๋ฐ์ดํฐ ํจ์นญ
โ
๋ฐ์ดํฐ ํจ์นญ์ด ๊ฐ๋ฅํ์ง๋ง ํน๋ณํ ์ด์ ๊ฐ ์๋ค๋ฉด ์๋ฒ์์ ๋ฐ์ดํฐ ํจ์นญ์ ํ๋ ๊ฒ์ด ์ข๋ค. (์ฑ๋ฅ, ์ฌ์ฉ์ฑ)
๋ฐฑ์๋ ๋ฆฌ์์ค ์ง์ ์ ๊ทผ
โ
โ
๋ ธ์ถ๋๋ฉด ์๋๋ ๋ฏผ๊ฐํ ๋ฐ์ดํฐ(์์ธ์ค ํ ํฐ, API Keys)
โ
โ
์ฌ์ฉ์์ ์ํธ์์ฉํ๋ ์ฝ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ ์ฌ์ฉ
โ
โ
React Hooks ์ฌ์ฉ (useState, useEffect ๋ฑ)
โ
โ
๋ธ๋ผ์ฐ์ API ์ฌ์ฉ
โ
โ
Data Fetching
getStaticProps()
,gstServerSideProps()
๋ฅผ ๋์ฒดํ๋ ์ฌ๋ฌ๊ฐ์ง ๋ฐฉ์์ด ์ถ๊ฐ ๋์๋ค.
์ด๋ ์์ ์ ํ์ด์ง(or ๋ ์ด์์)๋ฅผ ์ฌ์์ฑ ํ ์ง ์ง์
revalidate
๋ธ๋ผ์ฐ์ ์์ ํ์ด์ง(or ๋ ์ด์์)์ ์ฌ๊ฒ์ฆํ๋ ๊ธฐ๋ณธ ์๊ฐ์ ์ง์
export const revalidate = false; // default
// false(SSG) | 'force-cache'(SSG) | 0(SSR) | number(ISR)
fetch()
์ ์ค์ ๋ ์บ์ ์ต์
์ override ํ์ง ์๋๋ค.
-> revalidate < fetch()
fetch(url, options)
async/await
์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ ํจ์นญ
Next.js๋ Web fetch API๋ฅผ ํ์ฅํ์ฌ ์ฌ์ฉ
์บ์ ์ ๋ฌด์ ๋ฐ๋ผ SSG
, ISR
, SSR
๋ก ๋๋๊ฒ ๋๋ค.
export default async function Page() {
const data = await fetch(url, {
cache: 'force-cache'; // default (SSG)
// no-store(SSR), number(ISR)
});
}
Dynamic Rendering
๋์ ํจ์ ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ fetch()
์์ฒญ์ ์บ์ ์ต์
์ด no-store ์ผ ๋ ๋์ ๋ ๋๋ง(SSR)์ผ๋ก ์ ํ๋๋ค.
๋์ ํจ์(Dynamic fuction)
์ฌ์ฉ์์ ์์ฒญ ์์ ์ ์ ์ ์๋ ์ ๋ณด๋ฅผ ์ฌ์ฉํ ํจ์๋ฅผ ๋์ ํจ์๋ผ ํ๋ค.
ex) ์์ฒญ ์์ ์ ์ ์ ์๋ ์ ๋ณด -> ์ฟ ํค, HTTP ์์ฒญ ํค๋, URL params
API Route
Next๊ฐ Full Stack์ผ๋ก ๊ฐ๋ฐํ ์ ์๋ ์ด์
์์ฒญ ๋ณ(Get, Post)๋ก ๋๋์ด ๊ตฌ์กฐ์ ์ผ๋ก ๊ตฌํ ๊ฐ๋ฅํ๋๋ก ๋ฐ๋์๋ค.
// app/api/[endpoint]/route.ts
export async function GET(req: Request) {
const data = await ...
return NextResponse.json(data);
}
๋ผ์ฐํธ๋น ํด๋ ํ๋
๋ผ์ฐํธ๊ฐ ๋๋ ํด๋ ์ฆ, ํ์ด์ง ๋ณ๋ก ๋ค์ํ๊ณ ์ ์ฉํ ์์ดํ ๋ค์ ์ค์ ํ ์ ์๋ค.
ํด๋ ๋ณ๋ก ์ค์ ํ ์ ์๋ ํญ๋ชฉ๋ค
page.tsx: ํด๋น ํด๋๋ฅผ ๊ฒฝ๋ก๋ก ํ๋ ํ์ด์ง ์ปดํฌ๋ํธ
layout.tsx: ํ์ด์ง๋ฅผ ๊ฐ์ธ๋ ๊ณจ๊ฒฉ์ ์ค์ (์์ ๋ ์ด์์์ ์ค์ฒฉ๋จ)
template.tsx: ๋ ์ด์์๊ณผ ๋น์ทํ๋. ํ์ด์ง ์ ํ์ ์ปดํฌ๋ํธ์ ์ ์ธ์คํด์ค๊ฐ ๋ง์ดํธ๋์ด ์คํ๋๋ ์ฐจ์ด๊ฐ ์๋ค.
loading.tsx: ํด๋น ๋ผ์ฐํธ์์ ํ์ด์ง UI๊ฐ ์ค๋น๋๊ธฐ ์ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ฃผ๋ UI ์ปดํฌ๋ํธ (React.Suspense)
error.tsx: ๋ฐํ์ ์๋ฌ์ ๋์ฒด UI ์ปดํฌ๋ํธ (React.ErrorBoundary)
not-found.tsx: ํด๋น ๋ผ์ฐํธ์ 404 UI ์ปดํฌ๋ํธ
loading.tsx
ํด๋น ๋ผ์ฐํธ์ ํ์ด์ง๊ฐ ์ค๋น๋๋ ๋์ loading.tsx์ ์ ์ธํ ์ปดํฌ๋ํธ๊ฐ ๋ณด์ฌ์ง๊ฒ ๋๋ค. * layout์ ์ ์ธํ page ๋ถ๋ถ๋ง ์ ์ฉ๋จ
์ด ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ด๋ถ์ ์ผ๋ก React.Suspense ๋ฅผ ์ฌ์ฉํ๋ค.
<Layout>
<Suspense fallback={<Loading />}>
<Page />
</Suspense>
</Layout>
๋ก๋ฉ์ ๋์ ์ธ SSR์ ํ ๋ ๋น ๋ฅด๊ฒ ๋ก๋ฉ UI๋ฅผ ๋จผ์ ๋ณด์ฌ์ฃผ๊ณ ์ค์ ์ปดํฌ๋ํธ๋ฅผ ๋ณ๋ ฌ์ ์ผ๋ก ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์คํํ ์๋ฃ๋๋ฉด ์ ์กํ๋ ์์ผ๋ก ์ฌ์ฉ์์๊ฒ ํ์ด์ง๊ฐ ์๋น์ค์ด๋ผ๋ ๊ฒ์ ์๋ฆฐ๋ค.
ํ๊ณ์
ํด๋น ์ปดํฌ๋ํธ๋ ํ์ด์ง ์ ์ฒด๋ฅผ ๋ฌถ๊ธฐ ๋๋ฌธ์ ๋ณ๋ ฌ ์คํธ๋ฆฌ๋ฐ์ ์ํด์๋ ๋ด๋ถ ์์๋ค์ ์์คํ์ค๋ฅผ ๋ฐ๋ก ์ค์ ํด์ค์ผ ํ๋ค.
Suspense ์ฌ์ฉ ์ด์
UI๋ฅผ ๋ ๋๋งํ๊ธฐ ์ ์ ๋ชจ๋ ๋ฐ์ดํฐ๊ฐ ๋ก๋๋ ๋๊น์ง ๊ธฐ๋ค๋ฆด ํ์ ์์ด ํ์ด์ง์ ์ผ๋ถ๋ฅผ ๋ ๋นจ๋ฆฌ ํ์ํ ์ ์๋ค.
Streaming Server Rendering: ์คํธ๋ฆฌ๋ฐ์ ์ฌ์ฉํ๋ฉด ํ์ด์ง์ HTML์ ๋ ์์ ์ฒญํฌ๋ก ๋๋๊ณ ํด๋น ์ฒญํฌ๋ฅผ ์๋ฒ์์ ํด๋ผ์ด์ธํธ๋ก ์ ์ง์ ์ผ๋ก ์ ์กํ ์ ์์ต๋๋ค
Selective Hydration: ์ฌ์ฉ์ ์ธํฐ๋ ์ ์ ํตํด ์ด๋ค ์ปดํฌ๋ํธ๋ฅผ ๋จผ์ ์ํํ ์ง ์ ํ์ ์ผ๋ก ๊ฒฐ์
error.tsx
์๋ฌ ์ปดํฌ๋ํธ๋ ์ด๋ค ์๋ฌ๊ฐ ๋ฐ์ํ๋์ง์ ํ์ด์ง๋ฅผ ๋ฆฌ์ ํ ์ ์๋ ์ฝ๋ฐฑํจ์๋ฅผ props๋ก ์ ๊ณตํ๋ค.
๋ด๋ถ์ ์ผ๋ก ErrorBoundary
๋ฅผ ์ฌ์ฉํ๋ค.
<Layout>
<ErrorBoundary fallback={<Error />}>
<Page />
</ErrorBoundary>
</Layout>
์๋ฌ ์ปดํฌ๋ํธ๋ ๋ฐํ์์ ํ์ํ ์ฌ์ฉ์ ์ฝ๋์ useEffect
๊ฐ์ ํ
๋ค์ ์ฌ์ฉํด์ผ ํ๋ ๋ฌด์กฐ๊ฑด Client ์ปดํฌ๋ํธ๊ฐ ๋๋ค.
loading.tsx
์ ๋ง์ฐฌ๊ฐ์ง๋ก ํ์ด์ง ๋ด๋ถ ์์ ๋จ์๋ก ์๋ฌ UI๋ฅผ ๋ณด์ฌ์ฃผ๊ณ ์ถ๋ค๋ฉด ํด๋น ์ปดํฌ๋ํธ๋ฅผ ErrorBoundary
๋ก ๊ฐ์ธ๋ฉด ๋๋ค.
๊ฐ์ฅ ๊ทผ์ ํ ๋ถ๋ชจ์ error.tsx
๋ฅผ ๋ณด์ฌ์ค๋ค. (๋ฒ๋ธ๋ง ๋จ)
Last updated