동적 페이지를 미리 만드는 이유
상품 상세 페이지나 블로그처럼 URL의 일부가 데이터에 따라 달라지는 페이지가 있습니다.
/products/1
/products/2
/products/3
Next.js에서는 [id]를 사용해 하나의 Page에서 이런 URL을 모두 처리할 수 있습니다.
app/
└─ products/
└─ [id]/
└─ page.tsx
그런데 여기서 한 가지 문제가 생깁니다.
상품 페이지를 사용자가 요청할 때마다 서버에서 새로 만들어야 할까요?
이미 어떤 상품이 존재하는지 알고 있고, 그 페이지를 미리 만들 수 있다면 굳이 사용자가 접속할 때까지 기다릴 필요가 없습니다.
이때 사용하는 것이 generateStaticParams입니다.
사용자가 요청하기 전에 페이지를 미리 만듭니다
예를 들어 상품이 다음과 같이 있다고 해보겠습니다.
상품
1. iPhone
2. MacBook
3. AirPods
generateStaticParams에서 미리 만들 상품을 알려줄 수 있습니다.
export async function generateStaticParams() {
return [
{ id: '1' },
{ id: '2' },
{ id: '3' },
]
}
Next.js는 빌드할 때 generateStaticParams를 실행하고, 반환된 id를 이용해 각 페이지를 미리 렌더링합니다. (nextjs.org)
빌드
generateStaticParams()
↓
id = 1, 2, 3
↓
각 id로 Page 렌더링
↓
상품 페이지 미리 준비
그래서 사용자가 /products/1에 접속했을 때 처음부터 페이지를 만드는 것이 아니라, 빌드 과정에서 준비해 둔 결과를 사용할 수 있습니다.
그렇다면 페이지 내용은 어떻게 달라질까요?
상품마다 페이지 내용은 당연히 다릅니다.
/products/1 → iPhone
/products/2 → MacBook
/products/3 → AirPods
generateStaticParams는 상품 정보를 만드는 함수가 아닙니다.
어떤 id의 페이지를 미리 만들지 알려주는 역할만 합니다.
실제 데이터는 page.tsx에서 가져옵니다.
export async function generateStaticParams() {
return [
{ id: '1' },
{ id: '2' },
{ id: '3' },
]
}
export default async function Page({ params }) {
const { id } = await params
const product = await getProduct(id)
return <h1>{product.name}</h1>
}
개념적으로 보면:
generateStaticParams()
↓
"1, 2, 3 페이지를 만들어줘"
↓
┌──────────────┐
│ page.tsx │
└──────────────┘
↓ ↓ ↓
id=1 id=2 id=3
↓ ↓ ↓
상품1 상품2 상품3
즉,
generateStaticParams
→ 어떤 페이지를 미리 만들까?
page.tsx
→ 그 페이지에 무엇을 보여줄까?
로 역할이 나뉩니다.
왜 미리 만들어 두는 것이 좋을까요?
사용자가 페이지를 요청할 때마다 서버에서 처음부터 렌더링한다고 생각해봅시다.
사용자 요청
↓
서버에서 데이터 조회
↓
Server Component 실행
↓
페이지 렌더링
↓
사용자에게 전달
페이지를 만드는 데 시간이 걸린다면 사용자는 그만큼 기다려야 합니다.
반면 빌드 시점에 미리 만들어 두면:
빌드
↓
페이지 미리 렌더링
↓
사용자 요청
↓
준비된 페이지 사용
이렇게 사용자가 페이지를 요청한 뒤 해야 할 작업을 줄일 수 있습니다.
즉 generateStaticParams를 사용하는 가장 큰 이유는
미리 알 수 있는 Dynamic Route를 사용자가 방문하기 전에 prerender하기 위해서입니다.
모든 동적 페이지를 미리 만들 필요는 없습니다
그렇다고 모든 상품을 빌드할 때 전부 만드는 것이 항상 좋은 것은 아닙니다.
상품이 100개라면 괜찮을 수 있지만,
상품 1,000,000개
라면 모든 상품 페이지를 빌드할 때 만드는 것은 부담이 될 수 있습니다.
그래서 generateStaticParams에는 미리 만들고 싶은 params만 반환할 수 있습니다.
export async function generateStaticParams() {
return [
{ id: '1' },
{ id: '2' },
{ id: '3' },
]
}
예를 들어 조회수가 높은 상품이나 자주 방문하는 페이지처럼 미리 만들어 둘 가치가 있는 페이지를 선택할 수 있습니다.
Dynamic Route와 함께 이해해야 합니다
여기서 중요한 점은 generateStaticParams가 Dynamic Route를 없애는 것이 아니라는 것입니다.
app/
└─ products/
└─ [id]/
└─ page.tsx
여전히 /products/[id]라는 Dynamic Route입니다.
다만 그중 일부 params를:
/products/1
/products/2
/products/3
빌드 시점에 미리 렌더링하는 것입니다.
따라서:
Dynamic Route
→ 여러 URL을 하나의 Page로 처리
generateStaticParams
→ 그중 어떤 URL을 미리 만들어 둘지 결정
이라고 이해하면 됩니다.
전체 흐름
결국 generateStaticParams는 다음과 같은 흐름을 만듭니다.
Dynamic Route
/products/[id]
↓
generateStaticParams()
↓
{id: "1"}
{id: "2"}
{id: "3"}
↓
빌드 시 Page 렌더링
↓
미리 준비된 페이지
↓
사용자가 요청
↓
빠르게 페이지 제공
정리하면 generateStaticParams는 동적인 URL을 사용하는 페이지라도, 이미 알고 있는 params에 대해서는 사용자가 방문하기 전에 미리 만들어 두기 위한 기능입니다.
동적인 URL
↓
미리 알 수 있는 params
↓
generateStaticParams
↓
빌드 시 prerender
↓
사용자 요청 시 기다릴 작업 감소
따라서 generateStaticParams의 핵심은 "동적 페이지를 어떻게 만드는가"가 아니라 "동적 페이지 중 무엇을 미리 만들어 둘 것인가"에 있습니다.