본문 바로가기
개인공부

Next.js Docs (6) Dynamic Routes

by 강물둘기 2023. 6. 20.

 

Dynamic Routes

정확한 segment 이름을 모르고, 동적 데이터에서 route를 만들려고 할 때 요청시 입력되거나 빌드시 미리 렌더링되는 동적 segment를 사용할 수 있다.

 

Convention

동적 segment는 폴더 이름을 대괄호로 감싸서 만든다. [foldername]   ex. [id] , [slug] 

동적 segment는 레이아웃, 페이지, route, generateMetadata 함수에 대한 매개 변수로 전달된다.

 

 

Example

예를 들어 블로그는 app/blog/[slug]/page.js 와 같은 경로를 포함할 수 있는데 여기서 [slug]는 블로그 post의 동적 segment이다.

// app/blog/[slug]/page.tsx
export default function Page({ params }: { params: { slug: string } }) {
  return <div>My Post: {params.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' }

 

segment에 대한 매개 변수를 생성하는 방법에 대한 자세한 내용은 generateStaticParams() 페이지 참조.

 

* 알면 좋은것 : 동적 segment는 pages 디렉토리의 동적 route와 같다.

 

 

Generating Static Params

generateStaticParams 함수는 동적 route segment와 함께 사용하여 요청시 생성 되는것이 아니라 빌드시 정적으로 경로를 생성할 수 있다.

// 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,
  }))
}

 

generateStaticParams 함수의 주요 이점은 데이터의 스마트 검색이다. fetch 요청을 사용하여 generateStaticParams 함수 내에서 content를 가져오면 요청이 자동으로 중복 제거된다. 이것은 여러 generateStaticParams, 레이아웃, 페이지에서 동일한 인수를 가진 fetch 요청이 한 번만 실행되므로 빌드 시간이 단축되는 효과를 가져온다.

 

* pages 디렉토리에서 마이그레이션 할 경우 마이그레이션 guide 참조.

* 자세한 내용과 고급 적용 사례는 generateStaticParams 서버 함수 문서 참조.

 

 

Catch-all Segments

동적 segment에서 대괄호 안에 ...을 추가하여 모든 후속 segment들을 잡을 수 있다. [...foldername]

예를들어 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'] }

 

Optional Catch-all Segments

Catch-all segment는 이중 대괄호에 매개변수를 포함하여 선택적으로 설정할 수 있다. [[...foldername]]

예를 들어 app/shop/[[...slug]]/page.js는 /shop 뿐만아니라 /shop/clothes, /shop/clothes/tops, /shop/clothes/tops/t-shirts와도 일치한다.

 

catch-all segment와 optional catch-all segment의 차이는 optional에서는 매개변수가 없는 경로도 일치한다는 것이다.(위의 예시에서 /shop)

Route Example URL params
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

타입스크립트를 사용할 때 구성된 route segment에 따라 params에 type을 추가할 수 있다.

// app/blog/[slug]/page.tsx
export default function Page({ params }: { params: { slug: string } }) {
  return <h1>My Page</h1>
}

 

Route params Type Definition
app/blog/[slug]/page.js { slug : string }
app/shop/[...slug]/page.js { slug : string[] }
app/[categoryId]/[itemId]/page.js { categoryId : string, itemId : string }

 

* 알면 좋은것 : 이것은 나중에 추가될 TypeScript 플러그인이 자동으로 수행될 수 있다.

 

 

Reference

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

 

Routing: Dynamic Routes | Next.js

Using App Router Features available in /app

nextjs.org

 

댓글