ReactNextCentral

동적 라우트

Published on
동적 라우트를 사용하여 동적 데이터로부터 프로그래밍 방식으로 라우트 세그먼트를 생성할 수 있습니다.
Table of Contents

사전에 정확한 세그먼트 이름을 모르고 동적 데이터로 라우트를 생성하려면 요청 시간에 채워지거나 빌드 시간에 프리렌더링 될 동적 세그먼트를 사용할 수 있습니다.


규칙

동적 세그먼트는 폴더 이름을 대괄호로 감싸서 생성할 수 있습니다: [folderName]. 예를 들면, [id] 또는 [slug].

동적 세그먼트는 layout, page, route, 및 generateMetadata 함수에 params prop으로 전달됩니다.


예시

예를 들면, 블로그는 다음과 같은 라우트를 포함할 수 있습니다: app/blog/[slug]/page.js, 여기서 [slug]는 블로그 게시물의 동적 세그먼트입니다.

app/blog/[slug]/page.tsx
export default function Page({ params }: { params: { slug: string } }) {
  return <div>내 게시물: {params.slug}</div>
}
JavaScript
app/blog/[slug]/page.js
export default function Page({ params }) {
  return <div>내 게시물: {params.slug}</div>
}
라우트예제 URLparams
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' }

세그먼트에 대한 params를 생성하는 방법을 알아보려면 generateStaticParams() 페이지를 참조하세요.

동적 세그먼트는 pages 디렉토리의 동적 라우트와 동일합니다.


정적 Params 생성

generateStaticParams 함수는 동적 라우트 세그먼트와 함께 사용되어 요청 시간에 대신 빌드 시간에 라우트를 정적으로 생성하는 데 사용할 수 있습니다.

app/blog/[slug]/page.tsx
export async function generateStaticParams() {
  const posts = await fetch('https://.../posts').then((res) 
    => res.json())

  return posts.map((post) => ({
    slug: post.slug,
  }))
}
JavaScript
app/blog/[slug]/page.js
export async function generateStaticParams() {
  const posts = await fetch('https://.../posts').then((res) 
    => res.json())

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

generateStaticParams() 함수의 주요 이점은 데이터를 스마트하게 검색하는 것입니다. generateStaticParams 함수 내에서 fetch 요청을 사용하여 컨텐츠가 가져와지면 요청은 자동으로 메모이제이션됩니다. 이는 여러 generateStaticParams, 레이아웃, 페이지에서 동일한 인수로 fetch 요청이 한 번만 이루어짐을 의미하며, 빌드 시간을 줄입니다.

pages 디렉토리에서 마이그레이션하는 경우 마이그레이션 가이드를 사용하세요.

더 많은 정보와 고급 사용 사례를 위해 generateStaticParams 서버 함수 문서를 참조하세요.


Catch-all 세그먼트

동적 세그먼트는 이후의 세그먼트를 [Catch-all 대괄호] 안에 생략표를 추가함으로써 확장될 수 있습니다: [...folderName].

예를 들면, app/shop/[...slug]/page.js/shop/clothes와 일치하지만 /shop/clothes/tops, /shop/clothes/tops/t-shirts 등도 일치합니다.

라우트예제 URLparams
app/shop/[...slug]/page.js/shop/clothes{ slug: ['clothes'] }
app/shop/[...slug]/page.js/shop/clothes/tops{ slug: ['clothes', 'tops'] }
app/shop/[...slug]/page.js/shop/clothes/tops/t-shirts{ slug: ['clothes', 'tops', 't-shirts'] }

Catch-all 세그먼트는 항상 라우트의 마지막 세그먼트로 있어야 합니다. 그렇지 않으면 오류가 발생합니다.


Optional Catch-all 세그먼트

Catch-all 세그먼트는 매개변수를 [[이중 대괄호]]로 포함하여 선택적으로 만들 수 있습니다: [[...folderName]].

예를 들어, app/shop/[[...slug]]/page.js/shop/clothes, /shop/clothes/tops, /shop/clothes/tops/t-shirts 외에 또한 /shop과도 일치합니다.

Catch-allOptional Catch-all 세그먼트의 차이점은 Optional Catch-all은 매개변수 없는 라우트도 일치한다는 것입니다(위 예에서 /shop).

라우트예시 URLparams
app/shop/[[...slug]]/page.js/shop{}
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'] }

타입스크립트

타입스크립트를 사용할 때 구성된 라우트 세그먼트에 따라 params에 대한 타입을 추가할 수 있습니다.

app/blog/[slug]/page.tsx
export default function Page({ params }: { params: { slug: string } }) {
  return <h1>My Page</h1>
}
JavaScript
app/blog/[slug]/page.js
export default function Page({ params }) {
  return <h1>My Page</h1>
}
라우트params 타입 정의
app/blog/[slug]/page.js{ slug: string }
app/shop/[...slug]/page.js{ slug: string[] }
app/[categoryId]/[itemId]/page.js{ categoryId: string, itemId: string }

이것은 앞으로 타입스크립트 플러그인에 의해 자동으로 수행될 수 있습니다.