동적 라우트는 대괄호로 감싼 폴더 이름으로 가변 URL 세그먼트를 매칭하고, **generateStaticParams**는 그중 어떤 페이지를 빌드 시점에 미리 렌더링할지(SSG/ISR용) Next.js에 알려 줍니다.
동적 세그먼트
tsx
() {
post = (params.);
;
}
// 정적으로 빌드할 slug 목록을 Next.js에 알려 줌
export async function generateStaticParams() {
const posts = await getAllPosts();
return posts.map(post => ({ slug: post.slug }));
// → 빌드 시점에 /blog/post-1, /blog/post-2, ... 를 정적 HTML로 빌드
}
이것이 없으면 동적 라우트는 온디맨드(SSR)로 렌더링됩니다. 이것이 있으면 Next.js가 반환된 각 param에 대해 빌드 시점에 정적 페이지를 미리 생성합니다. 알려진 동적 페이지 집합(모든 블로그 글, 모든 상품)에 SSG의 속도를 제공합니다.
// generateStaticParams가 반환하지 않은 slug는 어떻게 될까?
export const dynamicParams = true; // (기본값) 알려지지 않은 slug를 온디맨드로 렌더링 (ISR 유사)
// export const dynamicParams = false; // 미리 빌드되지 않은 slug는 404 반환
이를 통해 상위/가장 흔한 페이지는 미리 빌드하고 롱테일은 여전히 제공(또는 404)할 수 있습니다.
app/shop/[...categories]/page.tsx → /shop/a/b/c (params.categories = ['a','b','c'])
app/[lang]/[slug]/page.tsx → 다중 param: { lang, slug }
export async function generateStaticParams() {
return [{ lang: "en", slug: "about" }, { lang: "vi", slug: "about" }];
}
이 한 쌍은 대규모 동적 페이지 집합(블로그, 이커머스 카탈로그, 문서)을 최고의 성능과 SEO를 위해 정적으로 생성하는 방법이며, dynamicParams는 미리 빌드되지 않은 페이지에 대한 폴백을 제어합니다.
generateStaticParams(어떤 페이지를 미리 빌드할지)와 캐싱/revalidate 옵션을 이해하는 것이 App Router에서 동적 콘텐츠에 SSG/ISR을 적용하는 핵심입니다.