[번역] Next.js13 App Router - Routing - Dynamic Routes

최영호·2023년 7월 28일
1

On this page

미리 세그먼트의 정확한 이름을 알지 못하거나 다이나믹 데이터를 바탕으로 라우트를 만들고 싶다면 리퀘스트 타임이나 빌드 타임 때 프리렌더링 과정에서 생성 되는 다이나믹 세그먼트를 사용하면 좋다.

Convention

다이나믹 세그먼트는 폴더 이름을 대괄호로 감싸 구현할 수 있다. [폴더 이름]
예를 들어 [id] 혹은 [slug]

다이나믹 세그먼트는 layout, page, route 그리고 generateMetadata 함수에 params 프롭으로 전달 된다.

Example

예를 들어 블로그 어플리케이션에 app/blog/[slug]/page.js 라우트가 있고 [slug] 값이 블로그 포스트를 위한 다이나믹 세그먼트라고 생각해보자.

export default function Page({ params }: { params: { slug: string } }) {
  return <div>My Post: {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" }

generateStaticParams() 페이지에서 세그먼트를 위한 params를 어떻게 생성할 수 있는지 알아보세요.

추천 사항:
다이나믹 세그먼트는 pages 디렉토리의 Dynamic Routes와 동일한 개념이다.

Generating Static Params

generateStaticParams 함수는 다이나믹 라우트 세그먼트라우트 정적 생성 기능을 합친 것으로 리퀘스트 타임에 온디맨드로 실행되지 않고 빌드 타임에 실행 된다.

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 Segments

다이나믹 세그먼트는 대괄호 내부에 줄임표를 붙여([...폴더 이름]) 후속 세그먼트를 모두 잡아낼 수 있도록 확장할 수 있다.

예를 들어 app/shop/[...slug]/page.js/shop/clothes 와 매치되고 /shop/clothes/tops, /shop/clothes/tops/t-shirts 와도 매치 된다.

라우트예시 URLparams
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'] }

Optional Catch-all Segments

Catch-all 세그먼트는 대괄호를 중첩하여([[...폴더 이름]]) 선택적으로 파라미터를 포함시킬 수 있도록 할 수 있다.

예를 들어 app/shop/[[...slug]]/page.js/shop, /shop/clothes, /shop/clothes/tops, /shop/clothes/tops/t-shirts 모두와 매치 된다

catch-all 과 선택적 catch-all 세그먼트의 차이점은 선택적 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'] }

TypeScript

타입스크립트와 함께 사용할 때, 라우트 세그먼트에 따라 params 의 타입을 지정할 수 있다.

export default function Page({ params }: { params: { slug: string } }) {
  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 }

참고 사항:
미래엔 타입스크립트 플러그인을 통해 자동으로 이루어질 예정입니다.

profile
무친 프론트엔드 개발자를 꿈꾸며...

0개의 댓글