next.config.js: 리라이트
next.config.js: 리라이트 | Next.js
섹션 제목: “next.config.js: 리라이트 | Next.js”원본 URL: https://nextjs.org/docs/app/api-reference/config/next-config-js/rewrites
리라이트
섹션 제목: “리라이트”최종 업데이트 2026년 2월 20일
리라이트를 사용하면 들어오는 요청 경로를 다른 대상 경로에 매핑할 수 있습니다.
리라이트는 URL 프록시처럼 동작하여 대상 경로를 가려 주고, 사용자가 사이트에서 위치를 이동하지 않은 것처럼 보이게 합니다. 반면 리다이렉트는 새 페이지로 다시 라우팅하며 URL 변경 사항을 보여 줍니다.
리라이트를 사용하려면 next.config.js에서 rewrites 키를 사용할 수 있습니다:
next.config.js
module.exports = { async rewrites() { return [ { source: '/about', destination: '/', }, ] }, }리라이트는 클라이언트 측 라우팅에 적용됩니다. 위 예시에서 <Link href="/about">로 이동하면 /about URL을 유지한 채 /의 콘텐츠를 제공합니다.
rewrites는 source와 destination 속성을 가진 객체들을 담은 배열 또는 (아래에서 설명하는) 배열 객체를 반환해야 하는 async 함수입니다:
source:String- 들어오는 요청 경로 패턴입니다.destination:String- 라우팅하려는 경로입니다.basePath:false또는undefined- false일 경우 basePath는 매칭 시 포함되지 않으며, 외부 리라이트에만 사용할 수 있습니다.locale:false또는undefined- 매칭 시 로케일을 포함하지 않을지 여부입니다.has는type,key,value속성을 가진 has 객체 배열입니다.missing은type,key,value속성을 가진 missing 객체 배열입니다.
rewrites 함수가 배열을 반환하면, 리라이트는 파일 시스템(페이지와 /public 파일) 확인 후 동적 라우트 전에 적용됩니다. rewrites 함수가 특정 형태의 배열 객체를 반환하면 Next.js v10.1부터 이 동작을 변경하고 더 정밀하게 제어할 수 있습니다:
next.config.js
module.exports = { async rewrites() { return { beforeFiles: [ // These rewrites are checked after headers/redirects // and before all files including _next/public files which // allows overriding page files { source: '/some-page', destination: '/somewhere-else', has: [{ type: 'query', key: 'overrideMe' }], }, ], afterFiles: [ // These rewrites are checked after pages/public files // are checked but before dynamic routes { source: '/non-existent', destination: '/somewhere-else', }, ], fallback: [ // These rewrites are checked after both pages/public files // and dynamic routes are checked { source: '/:path*', destination: `https://my-old-site.com/:path*`, }, ], } }, }알아두면 좋아요 :
beforeFiles의 리라이트는 source를 매칭한 직후 파일 시스템/동적 라우트를 확인하지 않고, 모든beforeFiles가 확인될 때까지 계속됩니다.
Next.js에서 라우트를 확인하는 순서는 다음과 같습니다:
- headers를 확인/적용
- redirects를 확인/적용
- proxy
beforeFiles리라이트를 확인/적용- public 디렉터리의 정적 파일,
_next/static파일, 비동적 페이지를 확인/제공 afterFiles리라이트를 확인/적용하며, 이 중 하나가 매칭되면 매칭마다 동적 라우트/정적 파일을 확인fallback리라이트를 확인/적용하며, 이는 404 페이지 렌더링 전에, 그리고 동적 라우트/모든 정적 자산을 확인한 뒤 적용됩니다.getStaticPaths에서 fallback: true/‘blocking’을 사용하면,next.config.js에 정의된 fallbackrewrites는 실행되지 않습니다.
리라이트 매개변수
섹션 제목: “리라이트 매개변수”리라이트에서 매개변수를 사용할 때, 해당 매개변수가 destination에 사용되지 않으면 기본적으로 쿼리에 전달됩니다.
next.config.js
module.exports = { async rewrites() { return [ { source: '/old-about/:path*', destination: '/about', // The :path parameter isn't used here so will be automatically passed in the query }, ] }, }매개변수가 destination에서 사용되면 어떤 매개변수도 자동으로 쿼리에 전달되지 않습니다.
next.config.js
module.exports = { async rewrites() { return [ { source: '/docs/:path*', destination: '/:path*', // The :path parameter is used here so will not be automatically passed in the query }, ] }, }이미 destination에서 하나의 매개변수를 사용하고 있더라도, destination에서 쿼리를 지정하여 매개변수를 수동으로 전달할 수 있습니다.
next.config.js
module.exports = { async rewrites() { return [ { source: '/:first/:second', destination: '/:first?second=:second', // Since the :first parameter is used in the destination the :second parameter // will not automatically be added in the query although we can manually add it // as shown above }, ] }, }알아두면 좋아요 : Automatic Static Optimization의 정적 페이지나 프리렌더링에서 리라이트로 전달된 매개변수는 하이드레이션 이후 클라이언트에서 파싱되어 쿼리로 제공됩니다.
경로 매칭
섹션 제목: “경로 매칭”경로 매칭이 허용되며, 예를 들어 /blog/:slug는 /blog/first-post와 매칭됩니다(중첩 경로 없음).
next.config.js
module.exports = { async rewrites() { return [ { source: '/blog/:slug', destination: '/news/:slug', // Matched parameters can be used in the destination }, ] }, }/blog/:slug 패턴은 /blog/first-post, /blog/post-1과 매칭되지만 /blog/a/b와는 매칭되지 않습니다(중첩 경로 없음). 패턴은 시작 지점에 고정되므로 /blog/:slug는 /archive/blog/first-post와 매칭되지 않습니다.
매개변수에 *(0개 이상), +(1개 이상), ?(0개 또는 1개)와 같은 수식어를 사용할 수 있습니다. 예를 들어 /blog/:slug*는 /blog, /blog/a, /blog/a/b/c와 매칭됩니다.
자세한 내용은 path-to-regexp 문서를 참고하세요.
와일드카드 경로 매칭
섹션 제목: “와일드카드 경로 매칭”와일드카드 경로를 매칭하려면 매개변수 뒤에 *를 사용할 수 있습니다. 예를 들어 /blog/:slug*는 /blog/a/b/c/d/hello-world와 매칭됩니다:
next.config.js
module.exports = { async rewrites() { return [ { source: '/blog/:slug*', destination: '/news/:slug*', // Matched parameters can be used in the destination }, ] }, }정규식 경로 매칭
섹션 제목: “정규식 경로 매칭”정규식 경로를 매칭하려면 매개변수 뒤에 괄호로 정규식을 감싸면 됩니다. 예를 들어 /blog/:slug(\\d{1,})는 /blog/123와 매칭되지만 /blog/abc와는 매칭되지 않습니다:
next.config.js
module.exports = { async rewrites() { return [ { source: '/old-blog/:post(\\d{1,})', destination: '/blog/:post', // Matched parameters can be used in the destination }, ] }, }정규식 경로 매칭에 사용되는 문자는 (, ), {, }, [, ], |, \, ^, ., :, *, +, -, ?, $이며, source에서 특수 용도가 아닌 값으로 사용하려면 앞에 \\를 추가해 이스케이프해야 합니다:
next.config.js
module.exports = { async rewrites() { return [ { // this will match `/english(default)/something` being requested source: '/english\\(default\\)/:slug', destination: '/en-us/:slug', }, ] }, }헤더, 쿠키, 쿼리 매칭
섹션 제목: “헤더, 쿠키, 쿼리 매칭”헤더, 쿠키, 쿼리 값이 has 필드와 일치하거나 missing 필드와 일치하지 않을 때만 리라이트를 매칭하도록 제한할 수 있습니다. 리라이트가 적용되려면 source와 모든 has 항목이 일치해야 하고, 모든 missing 항목은 일치하지 않아야 합니다.
has와 missing 항목에는 다음 필드를 사용할 수 있습니다:
type:String-header,cookie,host,query중 하나여야 합니다.key:String- 선택한 타입에서 매칭하려는 키입니다.value:String또는undefined- 확인할 값이며, undefined면 아무 값이나 매칭됩니다.value에first-(?<paramName>.*)와 같은 정규식 문자열을 사용하면,first-second값에서second를 추출해:paramName으로 destination에서 사용할 수 있습니다.
next.config.js
module.exports = { async rewrites() { return [ // if the header `x-rewrite-me` is present, // this rewrite will be applied { source: '/:path*', has: [ { type: 'header', key: 'x-rewrite-me', }, ], destination: '/another-page', }, // if the header `x-rewrite-me` is not present, // this rewrite will be applied { source: '/:path*', missing: [ { type: 'header', key: 'x-rewrite-me', }, ], destination: '/another-page', }, // if the source, query, and cookie are matched, // this rewrite will be applied { source: '/specific/:path*', has: [ { type: 'query', key: 'page', // the page value will not be available in the // destination since value is provided and doesn't // use a named capture group e.g. (?<page>home) value: 'home', }, { type: 'cookie', key: 'authorized', value: 'true', }, ], destination: '/:path*/home', }, // if the header `x-authorized` is present and // contains a matching value, this rewrite will be applied { source: '/:path*', has: [ { type: 'header', key: 'x-authorized', value: '(?<authorized>yes|true)', },],
destination: ‘/home?authorized=:authorized’,
},
// if the host is example.com,
// this rewrite will be applied
{
source: ’/:path*’,
has: [
{
type: ‘host’,
value: ‘example.com’,
},
],
destination: ‘/another-page’,
},
]
},
}
외부 URL로 재작성
섹션 제목: “외부 URL로 재작성”예시
리라이트를 사용하면 외부 URL로 라우트를 재작성할 수 있으므로 Next.js를 점진적으로 도입할 때 특히 유용합니다. 아래 예시는 메인 앱의 /blog 라우트를 외부 사이트로 리디렉션하기 위한 리라이트입니다.
next.config.js
module.exports = { async rewrites() { return [ { source: '/blog', destination: 'https://example.com/blog', }, { source: '/blog/:slug', destination: 'https://example.com/blog/:slug', // Matched parameters can be used in the destination }, ] }, }trailingSlash: true를 사용하는 경우 source 파라미터에도 슬래시를 추가해야 합니다. 대상 서버가 트레일링 슬래시를 기대한다면 destination 파라미터에도 포함해야 합니다.
next.config.js
module.exports = { trailingSlash: true, async rewrites() { return [ { source: '/blog/', destination: 'https://example.com/blog/', }, { source: '/blog/:path*/', destination: 'https://example.com/blog/:path*/', }, ] }, }Next.js 점진적 도입
섹션 제목: “Next.js 점진적 도입”모든 Next.js 라우트를 확인한 뒤 기존 웹사이트로 프록시하도록 Next.js를 폴백시킬 수도 있습니다.
이렇게 하면 더 많은 페이지를 Next.js로 마이그레이션할 때마다 리라이트 구성을 변경할 필요가 없습니다.
next.config.js
module.exports = { async rewrites() { return { fallback: [ { source: '/:path*', destination: `https://custom-routes-proxying-endpoint.vercel.app/:path*`, }, ], } }, }basePath 지원과 함께하는 리라이트
섹션 제목: “basePath 지원과 함께하는 리라이트”리라이트와 함께 basePath 지원을 활용하면 basePath: false를 리라이트에 추가하지 않는 한 각 source와 destination이 자동으로 basePath로 접두사 처리됩니다.
next.config.js
module.exports = { basePath: '/docs',
async rewrites() { return [ { source: '/with-basePath', // automatically becomes /docs/with-basePath destination: '/another', // automatically becomes /docs/another }, { // does not add /docs to /without-basePath since basePath: false is set // Note: this cannot be used for internal rewrites e.g. `destination: '/another'` source: '/without-basePath', destination: 'https://example.com', basePath: false, }, ] }, }버전 기록
섹션 제목: “버전 기록”| 버전 | 변경 사항 |
|---|---|
v13.3.0 | missing이 추가되었습니다. |
v10.2.0 | has가 추가되었습니다. |
v9.5.0 | Headers가 추가되었습니다. |
보내기