generateStaticParams
generateStaticParams
함수는 동적 라우트 세그먼트와 함께 사용하여 요청에 따라 동적으로 처리되는 방식이 아닌 빌드 시 라우트를 정적으로 생성할 수 있습니다.
// [slug] 동적 세그먼트를 채울 `params` 목록을 반환합니다
export async function generateStaticParams() {
const posts = await fetch("https://.../posts").then((res) => res.json());
return posts.map((post) => ({
slug: post.slug,
}));
}
// 이 페이지의 여러 버전이 `generateStaticParams`가 반환한
// `params`를 사용하여 정적으로 생성됩니다
export default function Page({ params }) {
const { slug } = params;
// ...
}
알아두면 좋은 점
dynamicParams
세그먼트 구성 옵션을 사용하여generateStaticParams
로 생성되지 않은 동적 세그먼트를 방문할 때 어떤 일이 발생하는지 제어할 수 있습니다.- 런타임에 경로를 재검증하기 위해서는
generateStaticParams
에서 빈 배열을 반환하거나export const dynamic = 'force-static'
을 사용해야 합니다.next dev
중에는 라우트로 이동할 때generateStaticParams
가 호출됩니다.next build
중에는 해당 레이아웃이나 페이지가 생성되기 전에generateStaticParams
가 실행됩니다.- 재검증(ISR) 중에는
generateStaticParams
가 다시 호출되지 않습니다.generateStaticParams
는 Pages Router의getStaticPaths
함수를 대체합니다.
매개변수
options.params
(선택사항)
라우트의 여러 동적 세그먼트가 generateStaticParams
를 사용하는 경우, 하위 generateStaticParams
함수는 상위가 생성하는 각 params
세트에 대해 한 번씩 실행됩니다.
params
객체에는 상위 generateStaticParams
에서 채워진 params
가 포함되어 있으며, 이를 사용하여 하위 세그먼트에서 params
를 생성할 수 있습니다.
반환값
generateStaticParams
는 객체 배열을 반환해야 하며, 각 객체는 단일 라우트의 채워진 동적 세그먼트를 나타냅니다.
- 객체의 각 속성은 라우트에 대해 채워질 동적 세그먼트입니다.
- 속성의 이름은 세그먼트의 이름이고, 속성의 값은 해당 세그먼트가 채워져야 할 내용입니다.
예시 라우트 | generateStaticParams 반환 타입 |
---|---|
/product/[id] | { id: string }[] |
/products/[category]/[product] | { category: string, product: string }[] |
/products/[...slug] | { slug: string[] }[] |
단일 동적 세그먼트
export function generateStaticParams() {
return [{ id: "1" }, { id: "2" }, { id: "3" }];
}
// 이 페이지의 세 가지 버전이 `generateStaticParams`가 반환한
// `params`를 사용하여 정적으로 생성됩니다
// - /product/1
// - /product/2
// - /product/3
export default function Page({ params }: { params: { id: string } }) {
const { id } = params;
// ...
}
export function generateStaticParams() {
return [{ id: "1" }, { id: "2" }, { id: "3" }];
}
// 이 페이지의 세 가지 버전이 `generateStaticParams`가 반환한
// `params`를 사용하여 정적으로 생성됩니다
// - /product/1
// - /product/2
// - /product/3
export default function Page({ params }) {
const { id } = params;
// ...
}
여러 동적 세그먼트
export function generateStaticParams() {
return [
{ category: "a", product: "1" },
{ category: "b", product: "2" },
{ category: "c", product: "3" },
];
}
// 이 페이지의 세 가지 버전이 `generateStaticParams`가 반환한
// `params`를 사용하여 정적으로 생성됩니다
// - /products/a/1
// - /products/b/2
// - /products/c/3
export default function Page({
params,
}: {
params: { category: string; product: string };
}) {
const { category, product } = params;
// ...
}
export function generateStaticParams() {
return [
{ category: "a", product: "1" },
{ category: "b", product: "2" },
{ category: "c", product: "3" },
];
}
// 이 페이지의 세 가지 버전이 `generateStaticParams`가 반환한
// `params`를 사용하여 정적으로 생성됩니다
// - /products/a/1
// - /products/b/2
// - /products/c/3
export default function Page({ params }) {
const { category, product } = params;
// ...
}
전체 경로 처리 세그먼트 (Catch-all Segments)
export function generateStaticParams() {
return [{ slug: ["a", "1"] }, { slug: ["b", "2"] }, { slug: ["c", "3"] }];
}
// 이 페이지의 세 가지 버전이 `generateStaticParams`가 반환한
// `params`를 사용하여 정적으로 생성됩니다
// - /product/a/1
// - /product/b/2
// - /product/c/3
export default function Page({ params }: { params: { slug: string[] } }) {
const { slug } = params;
// ...
}
export function generateStaticParams() {
return [{ slug: ["a", "1"] }, { slug: ["b", "2"] }, { slug: ["c", "3"] }];
}
// 이 페이지의 세 가지 버전이 `generateStaticParams`가 반환한
// `params`를 사용하여 정적으로 생성됩니다
// - /product/a/1
// - /product/b/2
// - /product/c/3
export default function Page({ params }) {
const { slug } = params;
// ...
}
예시
정적 렌더링
빌드 시 모든 경로
빌드 시 모든 경로를 정적으로 렌더링하려면 generateStaticParams
에 전체 경로 목록을 제공하세요:
export async function generateStaticParams() {
const posts = await fetch("https://.../posts").then((res) => res.json());
return posts.map((post) => ({
slug: post.slug,
}));
}
빌드 시 일부 경로
빌드 시 일부 경로를 정적으로 렌더링하고 나머지는 런타임에 처음 방문할 때 렌더링하려면 부분적인 경로 목록을 반환하세요:
export async function generateStaticParams() {
const posts = await fetch("https://.../posts").then((res) => res.json());
// 빌드 시 처음 10개의 게시물을 렌더링합니다
return posts.slice(0, 10).map((post) => ({
slug: post.slug,
}));
}
그런 다음 dynamicParams
세그먼트 구성 옵션을 사용하여 generateStaticParams
로 생성되지 않은 동적 세그먼트를 방문할 때 어떤 일이 발생하는지 제어할 수 있습니다.
// 상위 10개 게시물 외의 모든 게시물은 404가 됩니다
export const dynamicParams = false;
export async function generateStaticParams() {
const posts = await fetch("https://.../posts").then((res) => res.json());
const topPosts = posts.slice(0, 10);
return topPosts.map((post) => ({
slug: post.slug,
}));
}
런타임에 모든 경로
처음 방문할 때 모든 경로를 정적으로 렌더링하려면 빈 배열을 반환하거나 (빌드 시 경로가 렌더링되지 않음) export const dynamic = 'force-static'
을 사용하세요:
export async function generateStaticParams() {
return [];
}
알아두면 좋은 점:
generateStaticParams
에서는 항상 배열을 반환해야 합니다. 비어 있더라도 마찬가지입니다. 그렇지 않으면 라우트가 동적으로 렌더링됩니다.
export const dynamic = "force-static";
지정되지 않은 경로에 대한 렌더링 비활성화
지정되지 않은 경로가 런타임에 정적으로 렌더링되는 것을 방지하려면 라우트 세그먼트에 export const dynamicParams = false
옵션을 추가하세요. 이 구성 옵션을 사용하면 generateStaticParams
에서 제공한 경로만 제공되고, 지정되지 않은 라우트는 404가 되거나 (캐치올 라우트의 경우) 일치합니다.
라우트의 여러 동적 세그먼트
현재 레이아웃이나 페이지 위의 동적 세그먼트에 대한 매개변수를 생성할 수 있지만, 아래는 불가능합니다. 예를 들어, app/products/[category]/[product]
라우트의 경우:
app/products/[category]/[product]/page.js
는[category]
와[product]
둘 다에 대한 매개변수를 생성할 수 있습니다.app/products/[category]/layout.js
는[category]
에 대한 매개변수만 생성할 수 있습니다.
여러 동적 세그먼트가 있는 라우트에 대한 매개변수를 생성하는 두 가지 접근 방식이 있습니다:
아래에서 위로 매개변수 생성
하위 라우트 세그먼트에서 여러 동적 세그먼트를 생성합니다.
// [category]와 [product] 모두에 대한 세그먼트 생성
export async function generateStaticParams() {
const products = await fetch("https://.../products").then((res) =>
res.json()
);
return products.map((product) => ({
category: product.category.slug,
product: product.id,
}));
}
export default function Page({
params,
}: {
params: { category: string; product: string };
}) {
// ...
}
// [category]와 [product] 모두에 대한 세그먼트 생성
export async function generateStaticParams() {
const products = await fetch("https://.../products").then((res) =>
res.json()
);
return products.map((product) => ({
category: product.category.slug,
product: product.id,
}));
}
export default function Page({ params }) {
// ...
}
위에서 아래로 매개변수 생성
먼저 상위 세그먼트를 생성하고 그 결과를 사용하여 하위 세그먼트를 생성합니다.
// [category]에 대한 세그먼트 생성
export async function generateStaticParams() {
const products = await fetch("https://.../products").then((res) =>
res.json()
);
return products.map((product) => ({
category: product.category.slug,
}));
}
export default function Layout({ params }: { params: { category: string } }) {
// ...
}
// [category]에 대한 세그먼트 생성
export async function generateStaticParams() {
const products = await fetch("https://.../products").then((res) =>
res.json()
);
return products.map((product) => ({
category: product.category.slug,
}));
}
export default function Layout({ params }) {
// ...
}
하위 라우트 세그먼트의 generateStaticParams
함수는 상위 generateStaticParams
가 생성하는 각 세그먼트에 대해 한 번씩 실행됩니다.
하위 generateStaticParams
함수는 상위 generateStaticParams
함수에서 반환된 params
를 사용하여 동적으로 자체 세그먼트를 생성할 수 있습니다.
// 상위 세그먼트의 `generateStaticParams` 함수에서 전달된
// `params`를 사용하여 [product]에 대한 세그먼트 생성
export async function generateStaticParams({
params: { category },
}: {
params: { category: string };
}) {
const products = await fetch(
`https://.../products?category=${category}`
).then((res) => res.json());
return products.map((product) => ({
product: product.id,
}));
}
export default function Page({
params,
}: {
params: { category: string; product: string };
}) {
// ...
}
// 상위 세그먼트의 `generateStaticParams` 함수에서 전달된
// `params`를 사용하여 [product]에 대한 세그먼트 생성
export async function generateStaticParams({ params: { category } }) {
const products = await fetch(
`https://.../products?category=${category}`
).then((res) => res.json());
return products.map((product) => ({
product: product.id,
}));
}
export default function Page({ params }) {
// ...
}
알아두면 좋은 점:
fetch
요청은 모든generate
접두사가 붙은 함수, 레이아웃, 페이지 및 서버 컴포넌트에서 동일한 데이터에 대해 자동으로 메모이제이션됩니다.fetch
를 사용할 수 없는 경우 Reactcache
를 사용할 수 있습니다.
버전 기록
버전 | 변경 사항 |
---|---|
v13.0.0 | generateStaticParams 도입됨. |