본문 바로가기
웹 프로그래밍/Next.js

[Next.js 공식문서 정리] Routing : 07. Dynamic Routes.md

by 청량리 물냉면 2025. 3. 29.
반응형

정확한 세그먼트 이름을 미리 알 수 없고 요청 시점 또는 빌드 시점에 동적으로 생성해야 할 경우, 동적 세그먼트(Dynamic Segments)를 사용한다.

1. 동적 세그먼트 (Dynamic Segments)

폴더 이름을 대괄호 [ ] 로 감싸면 동적 세그먼트를 만들 수 있다. (예시: [id], [slug])

동적 세그먼트는 layout, page, route, generateMetadata 함수의 prop으로 전달된다.

예제

다음과 같은 블로그 페이지가 있다고 가정하면,

app/blog/[slug]/page.js

여기서 [slug] 는 블로그 게시물의 동적 세그먼트이다.

export default async function Page({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  const { slug } = await params;
  return <div>My Post: {slug}</div>
}
Route Example URL params
app/blog/[slug]/page.js /blog/a { slug: 'a' }
app/blog/[slug]/page.js /blog/b { slug: 'b' }
app/blog/[slug]/page.js /blog/c { slug: 'c' }

⚠ 세그먼트에 대한 매개변수를 생성하는 방법은 generateStaticParams 페이지를 참조

참고

  • params 속성은 Promise이다. 따라서 값을 가져오려면 async/await 또는 React의 use 함수를 사용해야 한다.
    • 버전 14와 그 이전 버전에서 params는 동기적(synchronous)으로 동작했다. 이전 버전과의 호환성을 위해 Next.js 15에서 역시 동기적으로 접근할 수 있지만, 이 기능은 향후 제거될 예정
  • 동적 세그먼트(Dynamic Segments)는 pages 디렉터리의 동적 라우트(Dynamic Routes)와 동일한 개념이다.

 

2. 정적 매개변수 생성 (Generating Static Params)

generateStaticParams 함수는 동적 경로 세그먼트와 함께 사용하여 요청 시(on-demand)가 아닌, 빌드 시(build time)에 정적으로 경로를 생성할 수 있다.

export async function generateStaticParams() {
  const posts = await fetch('https://.../posts').then((res) => res.json())

  return posts.map((post) => ({
    slug: post.slug,
  }))
}

generateStaticParams 함수의 주요 이점

  • 효율적인 data fetching: generateStaticParams 내부에서 데이터를 가져올 때 fetch를 사용하면, Next.js가 자동으로 해당 요청을 캐싱(메모이제이션) 한다.
  • 중복 요청 방지: 같은 fetch 요청이 여러 번 호출되더라도 Next.js는 동일한 요청을 한 번만 실행하고, 이후에는 캐시된 결과를 재사용한다.
  • 빌드 시간 단축: Layout, Page, 여러 개의 generateStaticParams에서 같은 데이터를 요청할 경우, 각각 매번 서버에 요청하는 것이 아니라 한 번만 가져오고 재사용하므로 빌드 시간이 줄어든다.

3. 캐치올 세그먼트 (Catch-all Segments)

동적 세그먼트는 특정 부분만 동적으로 처리할 수도 있지만, 하위 모든 경로를 포함해 동적 처리 할 수도 있다.

(1) 기본 캐치올 세그먼트

대괄호 [ ] 안에 ... 을 추가하면 이후 모든 경로를 포함할 수 있다.

예제:

app/shop/[...slug]/page.js

위 경로 표현은 /shop/clothes, /shop/clothes/tops, /shop/clothes/tops/t-shirts 등의 모든 하위 경로를 포함한다.

Route Example URL params
app/shop/[...slug]/page.js /shop/a { slug: ['a'] }
app/shop/[...slug]/page.js /shop/a/b { slug: ['a', 'b'] }
app/shop/[...slug]/page.js /shop/a/b/c { slug: ['a', 'b', 'c'] }

(2) 선택적 캐치올 세그먼트 (Optional Catch-all Segments)

경로를 선택적으로 포함하려면, [ ] 안에 [[...]]를 사용한다.

예제:

app/shop/[[...slug]]/page.js

이렇게 하면 /shop도 유효한 경로로 처리된다.

Route Example URL params 값
app/shop/[[...slug]]/page.js /shop { slug: undefined }
app/shop/[[...slug]]/page.js /shop/a { slug: ['a'] }
app/shop/[[...slug]]/page.js /shop/a/b { slug: ['a', 'b'] }
app/shop/[[...slug]]/page.js /shop/a/b/c { slug: ['a', 'b', 'c'] }

기본 캐치올 세그먼트 (Catch-all Segments)선택적 캐치올 세그먼트 (Optional Catch-all Segments) 의 차이점: 선택적 캐치올 세그먼트를 사용하면 매개 변수가 없는 경로도 라우트와 매칭된다. (위의 예에서 /shop).

 

4. TypeScript 적용

TypeScript를 사용할 시, params 객체의 타입을 명시적으로 지정할 수 있다.

export default async function Page({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  return <h1>My Page</h1>;
}
Route params 타입
app/blog/[slug]/page.js { slug: string }
app/shop/[...slug]/page.js { slug: string[] }
app/shop/[[...slug]]/page.js { slug?: string[] }
app/[categoryId]/[itemId]/page.js { categoryId: string, itemId: string }

참고:
타입 정의는 향후 Next.js TypeScript 플러그인에 의해 자동으로 처리될 수 있다.

📌 요약

  • 동적 세그먼트 ([slug]): 요청 시점 또는 빌드 시점에 동적으로 생성
  • 정적 매개변수 생성 (generateStaticParams): 빌드 시 정적 데이터로 생성하여 성능 최적화
  • 캐치올 세그먼트 ([...slug]): 특정 경로뿐만 아니라 모든 하위 경로를 포함
  • 선택적 캐치올 세그먼트 ([[...slug]]): 기본 경로(/shop)도 허용하면서 동적 경로 지원
  • TypeScript 지원: params 객체에 대한 명확한 타입 정의 가능

🚀 Next.js 15 이후 params 가 비동기 프로퍼티가 되었으므로 await 또는 React의 use 함수를 사용해야 한다는 점도 기억하기

 

 


https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes

 

Routing: Dynamic Routes | Next.js

Dynamic Routes can be used to programmatically generate route segments from dynamic data.

nextjs.org

 

반응형