대괄호가 주소의 변수를 잡아
파일 시스템 라우팅에서도 고정할 수 없는 주소 조각이 있어. 폴더 이름을 대괄호로 감싸면 실제 URL 값을 params로 받을 수 있어. 한 조각, 한 조각 이상, 아무 조각도 없을 수 있는 경우에 따라 표기가 달라져.
| 폴더 형태 | 주소 예 | params 모양 |
|---|---|---|
[slug] | /blog/hello | { slug: 'hello' } |
[...slug] | /docs/a/b/c | { slug: ['a','b','c'] } |
[[...slug]] | /docs 또는 /docs/a/b | { slug: undefined } 또는 { slug: ['a','b'] } |
여러 동적 구간도 한 객체로 모여
app/shop/[category]/[item]/page.tsx처럼 한 경로에 변수가 여러 개 있어도 돼. 페이지가 받는 params에는 category와 item이 한 객체로 합쳐져 들어와. Next.js 15 이상에서는 그 객체를 Promise에서 꺼낸다는 점도 잊지 마.
미리 만들지 않은 값의 운명을 정해
generateStaticParams가 빌드 때 일부 값만 만들었더라도, 기본 설정에서는 목록에 없던 값이 요청되면 그 자리에서 렌더링해. 알려지지 않은 slug를 반드시 404로 막고 싶다면 export const dynamicParams = false를 선언해. 정적 목록을 만들었다는 사실만으로 허용 목록이 되는 건 아니야.
동적 구간을 만들 때 허용 가능한 값의 집합과 미리 만들 값의 집합을 따로 적어. 인기 글 100개만 빌드하되 나머지 글도 첫 요청에 만들 수 있고, 문서 버전처럼 정해진 값만 허용한다면 dynamicParams = false가 맞아. 두 결정을 하나로 섞으면 예상 밖 404나 무한한 페이지 생성이 생겨.
catch-all이 폴더 수를 줄여 준다고 모든 계층에 맞는 건 아니야. 한 배열로 받은 경로를 다시 해석하는 코드가 제품의 URL 규칙을 숨길 수 있어. 계층마다 의미와 화면이 다르면 명시적 동적 구간을 나누는 편이 타입·메타데이터·오류 경계를 더 분명하게 해. 단일·catch-all·선택 catch-all 경로에 빈 값과 여러 조각을 보내 params 모양을 기록해. generateStaticParams 목록 안팎을 각각 요청하고 dynamicParams를 바꿨을 때 첫 요청 렌더링과 404가 어떻게 달라지는지 production build에서 확인해.