반응형

TL;DR


  • [slug] : 단일 경로 세그먼트 포착
  • [...slug] : 다중 경로 세그먼트 포착(Catch-All)
  • [[...slug]] : 루트 경로를 포함한 모든 경로를 선택적으로 포착(Optional Catch-All)

 

 

Dynamic Segments


정확한 세그먼트 이름을 미리 알 수 없을 때 폴더 이름을 대괄호로 감싸면 다이나믹 세그먼트로 작동. 세그먼트 이름은 layout, page 또는 route 파일에서 params 프롭으로 값 조회 가능.

 

Route URL Example Params
app/blog/[slug]/page.js /blog/a { slug: 'a' }
app/blog/[slug]/page.js /blog/b { slug: 'b' }
루트 경로(blog/)에 페이지 없으면 접근 불가.

 

 

Catch-all Segments


다이나믹 세그먼트를 확장하여 경로의 여러 세그먼트를 포착하려면 폴더 이름 앞에 점 3개(…)를 추가하여 Catch-All 세그먼트로 설정 가능. 이를 통해 여러 경로를 하나의 세그먼트로 처리할 수 있으며 params는 배열 형태로 전달됨.

 

Route URL Example Params
app/blog/[...slug]/page.js /blog/a { slug: ['a'] }
app/blog/[...slug]/page.js /blog/a/b { slug: ['a', 'b'] }
루트 경로(blog/)에 페이지 없으면 접근 불가.

 

 

Optional Catch-all Segments


Catch-All 세그먼트를 선택적으로 적용할 땐 대괄호 2개를 사용하여 Optional Catch-All 세그먼트로 설정 가능. 루트 경로와 하위 경로를 모두 처리할 수 있으며, 루트 경로에선 params.slug 값이 undefined로 전달됨.

 

Route URL Example Params
app/blog/[[...slug]]/page.js /blog { slug: undefined }
app/blog/[[...slug]]/page.js /blog/a { slug: ['a'] }
app/blog/[[...slug]]/page.js /blog/a/b { slug: ['a', 'b'] }
루트 경로(blog/)로 접근하면 app/blog/[[...slug]]/page.js 로 매핑됨.
⚠️ Optional Catch-All 세그먼트 사용시 동일 루트 폴더에 별도의 페이지 파일은 추가 못함

📦 app/
└─ blug/
   ├─ [[...slug]]/
   │  └─ page.tsx
   └─ page.tsx (❌ 불가)

 

 

Generating Static Params


generateStaticParams를 사용하면 동적 경로 기반의 정적 페이지를 빌드 타임에 미리 생성할 수 있으며, 이 함수 안에서 fetch로 가져온 데이터는 자동으로 메모이징된다. 이후 다른 페이지나 레이아웃 등에서 동일한 arguments를 사용하여 보낸 요청은 추가적인 네트워크 요청 없이 값을 재사용한다. 이를 통해 빌드 시간을 효율적으로 단축할 수 있다.

export async function generateStaticParams() {
  // API 호출 또는 데이터베이스 쿼리 등으로 동적 경로 목록을 가져옴
  const posts = await fetch('https://api.example.com/posts').then((res) => res.json());

  return posts.map((post) => ({
    slug: post.slug, // slug는 동적 경로 파라미터에 해당
  }));
}

export default function Page({ params }) {
  return <div>Post: {params.slug}</div>;
}

 


글 수정사항은 노션 페이지에 가장 빠르게 반영됩니다. 링크를 참고해 주세요
반응형