redirects
Redirects를 사용하면 들어오는 요청 경로를 다른 목적지 경로로 리디렉션할 수 있습니다.
리디렉션을 사용하려면 next.config.js에서 redirects 키를 사용할 수 있습니다:
module.exports = {
async redirects() {
return [
{
source: '/about',
destination: '/',
permanent: true,
},
]
},
}redirects는 source, destination, 및 permanent 속성을 가진 객체를 포함하는 배열을 반환하는 비동기 함수입니다:
source는 들어오는 요청 경로 패턴입니다.destination은 라우팅하려는 경로입니다.permanenttrue또는false-true인 경우 클라이언트/검색 엔진에 리디렉션을 영구적으로 캐시하도록 지시하는 308 상태 코드를 사용하고,false인 경우 일시적이고 캐시되지 않는 307 상태 코드를 사용합니다.
왜 Next.js는 307과 308을 사용하나요? 전통적으로 302는 일시적 리디렉션에, 301은 영구적 리디렉션에 사용되었지만, 많은 브라우저가 리디렉션의 요청 메서드를 원래 메서드와 상관없이
GET으로 변경했습니다. 예를 들어, 브라우저가POST /v1/users요청을 하고 상태 코드 302와 함께 위치/v2/users를 반환하면, 이후 요청은POST /v2/users대신GET /v2/users가 될 수 있습니다. Next.js는 307 일시적 리디렉션과 308 영구적 리디렉션 상태 코드를 사용하여 사용된 요청 메서드를 명시적으로 유지합니다.
basePath:false또는undefined-false인 경우 매칭 시basePath가 포함되지 않으며, 외부 리디렉션에만 사용할 수 있습니다.locale:false또는undefined- 매칭 시 로케일이 포함되지 않아야 하는지 여부입니다.has는type,key및value속성을 가진 has 객체의 배열입니다.missing은type,key및value속성을 가진 missing 객체의 배열입니다.
리디렉션은 파일 시스템(페이지 및 /public 파일 포함) 전에 확인됩니다.
Pages Router를 사용할 때, Middleware가 경로와 일치하지 않으면 리디렉션이 클라이언트 측 라우팅(Link, router.push)에 적용되지 않습니다.
리디렉션이 적용되면 요청에 제공된 모든 쿼리 값이 리디렉션 대상에 전달됩니다. 예를 들어, 다음 리디렉션 구성을 참조하세요:
{
source: '/old-blog/:path*',
destination: '/blog/:path*',
permanent: false
}/old-blog/post-1?hello=world가 요청되면, 클라이언트는 /blog/post-1?hello=world로 리디렉션됩니다.
Path Matching
경로 매칭이 허용됩니다. 예를 들어 /old-blog/:slug는 /old-blog/hello-world와 일치합니다(중첩 경로 없음):
module.exports = {
async redirects() {
return [
{
source: '/old-blog/:slug',
destination: '/news/:slug', // 매칭된 매개변수는 대상에서 사용할 수 있습니다
permanent: true,
},
]
},
}Wildcard Path Matching
와일드카드 경로를 매칭하려면 매개변수 뒤에 *를 사용할 수 있습니다. 예를 들어 /blog/:slug*는 /blog/a/b/c/d/hello-world와 일치합니다:
module.exports = {
async redirects() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // 매칭된 매개변수는 대상에서 사용할 수 있습니다
permanent: true,
},
]
},
}Regex Path Matching
정규식 경로를 매칭하려면 매개변수 뒤에 괄호로 정규식을 감쌀 수 있습니다. 예를 들어 /post/:slug(\\d{1,})는 /post/123과 일치하지만 /post/abc와는 일치하지 않습니다:
module.exports = {
async redirects() {
return [
{
source: '/post/:slug(\\d{1,})',
destination: '/news/:slug', // 매칭된 매개변수는 대상에서 사용할 수 있습니다
permanent: false,
},
]
},
}다음 문자는 정규식 경로 매칭에 사용되므로, source에서 비특수 값으로 사용될 때는 앞에 \\를 추가하여 이스케이프해야 합니다: (, ), {, }, :, *, +, ?
module.exports = {
async redirects() {
return [
{
// `/english(default)/something`이 요청될 때 일치합니다
source: '/english\\(default\\)/:slug',
destination: '/en-us/:slug',
permanent: false,
},
]
},
}Header, Cookie, and Query Matching
헤더, 쿠키 또는 쿼리 값이 has 필드와 일치하거나 missing 필드와 일치하지 않을 때만 리디렉션을 매칭하려면, has 필드 또는 missing 필드를 사용할 수 있습니다. source와 모든 has 항목이 일치하고 모든 missing 항목이 일치하지 않아야 리디렉션이 적용됩니다.
has 및 missing 항목에는 다음 필드가 있을 수 있습니다:
type:String-header,cookie,host또는query중 하나여야 합니다.key:String- 일치시킬 선택된 유형의 키입니다.value:String또는undefined- 확인할 값입니다. undefined인 경우, 모든 값이 일치합니다. 정규식과 같은 문자열을 사용하여 값의 특정 부분을 캡처할 수 있습니다. 예: 값이first-(?<paramName>.*)인 경우,first-second는second가 되어 목적지에서:paramName으로 사용할 수 있습니다.
module.exports = {
async redirects() {
return [
// 헤더 `x-redirect-me`가 있는 경우,
// 이 리디렉션이 적용됩니다
{
source: '/:path((?!another-page$).*)',
has: [
{
type: 'header',
key: 'x-redirect-me',
},
],
permanent: false,
destination: '/another-page',
},
// 헤더 `x-dont-redirect`가 있는 경우,
// 이 리디렉션이 적용되지 않습니다
{
source: '/:path((?!another-page$).*)',
missing: [
{
type: 'header',
key: 'x-do-not-redirect',
},
],
permanent: false,
destination: '/another-page',
},
// 소스, 쿼리 및 쿠키가 일치하는 경우,
// 이 리디렉션이 적용됩니다
{
source: '/specific/:path*',
has: [
{
type: 'query',
key: 'page',
// 페이지 값은 제공된 값이 있고
// 명명된 캡처 그룹을 사용하지 않으므로
// 목적지에서 사용할 수 없습니다. 예: (?<page>home)
value: 'home',
},
{
type: 'cookie',
key: 'authorized',
value: 'true',
},
],
permanent: false,
destination: '/another/:path*',
},
// 헤더 `x-authorized`가 존재하고
// 일치하는 값을 포함하는 경우, 이 리디렉션이 적용됩니다
{
source: '/',
has: [
{
type: 'header',
key: 'x-authorized',
value: '(?<authorized>yes|true)',
},
],
permanent: false,
destination: '/home?authorized=:authorized',
},
// 호스트가 `example.com`인 경우,
// 이 리디렉션이 적용됩니다
{
source: '/:path((?!another-page$).*)',
has: [
{
type: 'host',
value: 'example.com',
},
],
permanent: false,
destination: '/another-page',
},
]
},
}Redirects with basePath support
리디렉션과 함께 basePath 지원을 활용할 때, 각 source 및 destination은 next.config.js에 basePath: false를 추가하지 않는 한 자동으로 basePath로 접두사가 추가됩니다:
module.exports = {
basePath: '/docs',
async redirects() {
return [
{
source: '/with-basePath', // 자동으로 /docs/with-basePath가 됩니다
destination: '/another', // 자동으로 /docs/another가 됩니다
permanent: false,
},
{
// basePath: false가 설정되어 있으므로 /docs가 추가되지 않습니다
source: '/without-basePath',
destination: 'https://example.com',
basePath: false,
permanent: false,
},
]
},
}Redirects with i18n support
리디렉션과 함께 i18n 지원을 활용할 때, 각 source 및 destination은 구성된 locales를 처리하도록 자동으로 접두사가 추가되며, 리디렉션에 locale: false를 추가하지 않는 한 자동으로 처리됩니다. locale: false를 사용하는 경우, source 및 destination에 로케일을 접두사로 추가해야 올바르게 매칭됩니다.
module.exports = {
i18n: {
locales: ['en', 'fr', 'de'],
defaultLocale: 'en',
},
async redirects() {
return [
{
source: '/with-locale', // 모든 로케일을 자동으로 처리합니다
destination: '/another', // 로케일을 자동으로 전달합니다
permanent: false,
},
{
// locale: false가 설정되어 있으므로 로케일을 자동으로 처리하지 않습니다
source: '/nl/with-locale-manual',
destination: '/nl/another',
locale: false,
permanent: false,
},
{
// `en`이 defaultLocale이므로 '/'와 일치합니다
source: '/en',
destination: '/en/another',
locale: false,
permanent: false,
},
// locale: false가 설정된 경우에도 모든 로케일을 매칭할 수 있습니다
{
source: '/:locale/page',
destination: '/en/newpage',
permanent: false,
locale: false,
},
{
// 이것은 /(en|fr|de)/(.*)로 변환되므로 최상위 수준의
// `/` 또는 `/fr` 경로와 일치하지 않습니다
source: '/(.*)',
destination: '/another',
permanent: false,
},
]
},
}드물게는, 이전 HTTP 클라이언트가 적절히 리디렉션되도록 사용자 정의 상태 코드를 지정해야 할 수 있습니다. 이러한 경우, permanent 속성 대신 statusCode 속성을 사용할 수 있지만, 두 속성을 모두 사용할 수는 없습니다. IE11 호환성을 보장하기 위해 308 상태 코드에는 자동으로 Refresh 헤더가 추가됩니다.
Other Redirects
- API Routes 및 Route Handlers 내부에서 들어오는 요청에 따라 리디렉션할 수 있습니다.
getStaticProps및getServerSideProps내부에서 요청 시 특정 페이지를 리디렉션할 수 있습니다.
Version History
| Version | Changes |
|---|---|
v13.3.0 | missing added. |
v10.2.0 | has added. |
v9.5.0 | redirects added. |