icon안동민 개발노트

Catch-all 세그먼트 사용


 Next.js의 App Router에서 Catch-all 세그먼트는 여러 경로 세그먼트를 동적으로 처리할 수 있는 강력한 기능입니다. 이 절에서는 Catch-all 및 Optional catch-all 세그먼트의 개념, 사용 사례, 그리고 일반 동적 라우트와의 차이점에 대해 알아보겠습니다.

Catch-all 세그먼트 ([...slug])

 Catch-all 세그먼트는 [...slug] 문법을 사용하여 정의됩니다. 이 세그먼트는 하나 이상의 경로 세그먼트를 포함하는 모든 URL과 매칭됩니다.

 사용 예

// app/blog/[...slug]/page.js
export default function BlogPost({ params }) {
  return <div>Slug: {params.slug.join('/')}</div>
}

 *이 예제에서

  • /blog/a{ slug: ['a'] }
  • /blog/a/b{ slug: ['a', 'b'] }
  • /blog/a/b/c{ slug: ['a', 'b', 'c'] }

 Catch-all 세그먼트는 최소한 하나의 세그먼트가 필요합니다.

 /blog와 같이 세그먼트가 없는 경우 404 에러가 발생합니다.

Optional catch-all 세그먼트 ([[...slug]])

 Optional catch-all 세그먼트는 [[...slug]] 문법을 사용합니다. 이는 Catch-all 세그먼트와 유사하지만, 세그먼트가 없는 경우도 매칭됩니다.

 사용 예

// app/blog/[[...slug]]/page.js
export default function BlogPost({ params }) {
  const slug = params.slug || ['home']
  return <div>Slug: {slug.join('/')}</div>
}

 이 예제에서

  • /blog{ slug: undefined }
  • /blog/a{ slug: ['a'] }
  • /blog/a/b{ slug: ['a', 'b'] }

 Optional catch-all 세그먼트는 세그먼트가 없는 경우도 처리할 수 있어, 더 유연한 라우팅이 가능합니다.

일반 동적 라우트와의 차이점

  1.  세그먼트 수 : 일반 동적 라우트 ([id])는 단일 세그먼트만 처리하지만, Catch-all 세그먼트는 여러 세그먼트를 처리할 수 있습니다.

  2.  유연성 : Catch-all 세그먼트는 가변적인 수의 세그먼트를 처리할 수 있어 더 유연합니다.

  3.  params 객체 : 일반 동적 라우트에서는 params.id와 같이 단일 값을 받지만, Catch-all 세그먼트에서는 params.slug가 배열이 됩니다.

  4.  URL 구조 : Catch-all 세그먼트를 사용하면 더 복잡하고 중첩된 URL 구조를 쉽게 처리할 수 있습니다.

사용 사례

  1. 문서 시스템 : /docs/getting-started/installation/windows와 같은 중첩된 문서 구조
  2. 다국어 지원 : /en/products/electronics/smartphones와 같은 다국어 URL
  3. 블로그 카테고리 : /blog/tech/programming/javascript와 같은 다단계 카테고리 구조

실습 : 유연한 블로그 포스트 URL 구조 만들기

 다음 요구사항을 만족하는 블로그 포스트 URL 구조를 구현해보세요.

  1. 기본 블로그 페이지 /blog
  2. 카테고리별 블로그 목록 /blog/[category]
  3. 연도별 블로그 목록 /blog/[year]
  4. 카테고리와 연도를 조합한 블로그 목록 /blog/[category]/[year]
  5. 개별 블로그 포스트 /blog/[category]/[year]/[slug]

 구현 단계

  1. app/blog/[[...slug]]/page.js 파일을 생성합니다.
  2. params.slug를 사용하여 다양한 URL 패턴을 처리합니다.
  3. 각 패턴에 따라 적절한 콘텐츠를 렌더링합니다.

 예시 코드

// app/blog/[[...slug]]/page.js
export default function BlogPage({ params }) {
  const slug = params.slug || []
 
  if (slug.length === 0) {
    return <h1>Blog Home</h1>
  }
 
  if (slug.length === 1) {
    if (isNaN(slug[0])) {
      return <h1>Category: {slug[0]}</h1>
    } else {
      return <h1>Year: {slug[0]}</h1>
    }
  }
 
  if (slug.length === 2) {
    return <h1>Category: {slug[0]}, Year: {slug[1]}</h1>
  }
 
  if (slug.length === 3) {
    return <h1>Post: {slug[2]} in {slug[0]} category, {slug[1]}</h1>
  }
 
  return <h1>404 - Not Found</h1>
}

 이 실습을 통해 Catch-all 세그먼트를 사용하여 복잡하고 유연한 URL 구조를 구현하는 방법을 경험할 수 있습니다.

 이는 실제 블로그 플랫폼이나 콘텐츠 관리 시스템을 개발할 때 유용한 기술입니다.