리라이트(rewrites)란?
리라이트는 들어오는 요청 경로를 다른 목적지 경로로 바꿔주는 기능이에요.
이걸 간단히 말하면, 사용자가 웹사이트에서 이동한 것처럼 보이지만 실제로는 다른 경로에서 데이터를 가져오는 거예요. URL 자체는 바뀌지 않아서 '나는 여전히 같은 페이지에 있어!'라고 느껴지게 만드는 거죠. 이 점에서 리다이렉트와 큰 차이가 있어요. 리다이렉트는 말 그대로 URL이 바뀌면서 새 페이지로 이동하게 되거든요.
Next.js에서 리라이트를 사용하고 싶다면, next.config.js
파일 안에 rewrites
키를 활용하면 돼요.
예를 들어 이렇게 설정할 수 있어요:
module.exports = {
async rewrites() {
return [
{
source: '/old-path/:slug*',
destination: '/new-path/:slug*',
},
];
},
};
이렇게 하면 사용자가 /old-path/anything
으로 요청해도 실제 서버에선 /new-path/anything
을 처리하지만, 브라우저 주소창은 그대로 /old-path/anything
으로 유지돼요.
추가 팁!
- 리라이트는 특히 API 경로나 내부 구조를 바꾸고 싶을 때 유용해요. 예를 들어, API 버전을 변경할 때 외부에는 이전 API 경로를 그대로 노출하면서 내부에서는 새 버전을 쓸 수 있죠.
- 다만 리라이트가 작동하려면 Next.js가 해당 목적지 URL을 처리할 수 있어야 해요. 외부 도메인으로는 리라이트가 불가능하니 참고하세요.
- 만약 URL이 바뀌는 걸 원한다면, 리다이렉트를 사용해야 하는 점 기억하세요!
리라이트를 잘 활용하면 사용자 경험을 훨씬 깔끔하게 유지하면서 서버 구조를 유연하게 바꿀 수 있답니다. 고민되는 부분 있으면 언제든 질문해 주세요!
Next.js에서 rewrites
설정을 쓰면 클라이언트 사이드 라우팅 시 URL 경로를 원하는 대로 바꿔서 보여줄 수 있어요. 예를 들어, 위 코드처럼 /about
경로를 /
(홈 페이지)로 다시 매핑할 수 있죠.
module.exports = {
async rewrites() {
return [
{
source: '/about',
destination: '/',
},
]
},
}
이렇게 하면 코드 안에서 <Link href="/about">
을 사용해도 실제로는 /
경로로 라우팅 됩니다.
rewrites 함수
- async 함수로, 반환값은 객체 혹은 배열 형태입니다.
- 반환 값 안에는
{ source, destination }
객체들이 들어가죠.
속성명 | 설명 |
---|---|
source | 들어오는 요청의 경로 패턴 (예: /about ) |
destination | 실제로 라우팅할 경로 |
basePath | false 혹은 undefined - false 면 기본 basePath 를 경로에서 제외 (외부 URL rewrite에 쓰임) |
locale | false 혹은 undefined - 지역화(locale) 경로 포함 여부 설정 |
has | 조건 배열 - 특정 헤더, 쿠키, 쿼리 값 등이 있을 때만 rewrite 적용 가능 |
missing | 조건 배열 - 특정 헤더, 쿠키, 쿼리 값이 없을 때만 rewrite 적용 가능 |
추가 팁!
rewrites
는 URL을 '숨긴다'고 생각하면 쉬워요. 사용자가about
페이지로 접속한 것 같지만 실제론 루트 페이지를 보여주니까요.- SEO에 영향을 안 주고 프론트엔드에서 URL만 바꾸고 싶을 때 유용해요.
- 복잡한 조건문으로 특정 쿠키가 있거나 쿼리 파라미터에 따라 경로를 다르게 바꾸고 싶다면
has
나missing
옵션을 이용해보세요.
예를 들어:
rewrites: async () => [
{
source: '/dashboard',
has: [
{ type: 'cookie', key: 'token' }, // 로그인 되어 있는 사람만 접근 가능하게
],
destination: '/dashboard',
},
{
source: '/dashboard',
missing: [
{ type: 'cookie', key: 'token' }, // 로그인 안 되어 있으면 로그인 페이지로
],
destination: '/login',
},
],
이렇게 하면 사용자가 로그인이 되어 있는지 쿠키로 검사해 조건부 리다이렉트도 구현할 수 있어요.
Next.js 공식 문서에서는 rewrites
외에도 redirects
, headers
같은 유용한 설정들을 제공하니, 사이트 라우팅 컨트롤이 필요할 때 꼭 한 번 정독해보세요!
Next.js에서 rewrites 설정을 다룰 때, rewrites
함수가 배열을 반환하면, 이 리라이트(재작성) 규칙들은 파일 시스템(페이지와 /public 파일) 확인 후, 동적 라우트 검사 전에 적용돼요. 그런데 Next.js 10.1 버전부터는 rewrites
함수가 특정 구조의 객체 안에 배열들을 반환할 수 있는데요, 이 방식은 리라이트가 적용되는 타이밍을 좀 더 세밀하게 조정할 수 있게 해 줍니다.
아래 코드를 보면 각 배열이 어떤 역할을 하는지 쉽게 이해할 수 있어요:
module.exports = {
async rewrites() {
return {
beforeFiles: [
// headers/redirects 확인 후, 모든 파일 (예: _next/public 포함) 확인 전
// 여기에 선언한 리라이트들은 페이지 파일들을 덮어쓸 수도 있어요
{
source: '/some-page',
destination: '/somewhere-else',
has: [{ type: 'query', key: 'overrideMe' }],
},
],
afterFiles: [
// 페이지와 public 파일 확인 후, 동적 라우트 검사 전
{
source: '/non-existent',
destination: '/somewhere-else',
},
],
fallback: [
// 페이지/public 파일과 동적 라우트 모두 확인 후
{
source: '/:path*',
destination: `https://my-old-site.com/:path*`,
},
],
}
},
}
테이블로 정리하면 이렇게 볼 수 있어요
구분 | 적용 시점 | 특징 및 설명 |
---|---|---|
beforeFiles | headers/redirects 검사 후, 파일 시스템 검사(페이지, public) 전 | 페이지 파일 덮어쓰기 가능, 모든 beforeFiles 가 확인될 때까지 계속 검사 |
afterFiles | 페이지 및 public 파일 확인 후, 동적 라우트 확인 전 | 일반 파일은 없고 동적 라우트는 남아있을 때 사용 |
fallback | 페이지/public 파일과 동적 라우트 검사 모두 완료 후 | 모든 검사 끝난 후 리라이트를 적용, 외부 사이트로 프록시 등 활용 가능 |
좀 더 알려볼게요!
-
beforeFiles
내 리라이트는 매칭되더라도 모든beforeFiles
배열의 규칙들을 다 검사해요. 즉, 첫번째 매치에서 멈추지 않고, 다음 규칙도 계속 확인하는 거죠. 이는 오버라이드나 여러 조건에 유리해요. -
여러분이 리라이트를 통해 어떤 페이지를 완전히 다른 페이지로 교체하거나(예: A → B), 혹은 외부 URL로 프록시하려면
fallback
위치에 정의하는 게 적합해요. -
동적 라우트(
/:id
같은 경로)를 조작하고 싶다면afterFiles
위치를 활용하면 되는데요, 이 영역은 기본 페이지, public 파일 검사를 마친 후에 처리됩니다. -
파일 시스템 검사(실제로 그 경로에 맞는 파일이나 페이지가 있는지 확인)는 성능에도 영향을 끼치기 때문에, 필요한 경우에만 세밀하게 조절하는 게 중요해요.
마무리
Next.js의 rewrites 기능, 특히 v10.1 이후 객체 모양의 rewrites
반환은 라우팅 제어를 정말 유연하게 만들어줍니다. 상황에 맞게 beforeFiles
, afterFiles
, fallback
을 잘 조합해서, 내가 원하는 대로 페이지 흐름을 완벽하게 관리해 보세요! 개발자의 상상력과 요구에 유연하게 대응할 수 있다는 점이 Next.js의 큰 장점 중 하나랍니다.
필요하면 다음에 redirects
와 headers
설정에 대해서도 재미있고 쉽게 설명해 드릴게요! 😊
Next.js에서 라우팅과 리다이렉트, 그리고 리라이트(rewrite)가 어떻게 작동하는지 한번 정리해볼게요. 개발할 때 이 흐름을 이해하고 있으면 문제 생겼을 때 원인 찾기가 훨씬 수월해져요.
Next.js 요청 처리 순서
순서 | 처리 내용 |
---|---|
1 | 헤더(headers) 체크 및 적용 |
2 | 리다이렉트(redirects) 체크 및 적용 |
3 | beforeFiles 리라이트(rewrites) 체크 및 적용 |
4 | 정적 파일(public 디렉토리, _next/static 파일)과 비동적(non-dynamic) 페이지를 체크 및 서빙 |
5 | afterFiles 리라이트 체크 및 적용 — 여기서 매칭되면 다이나믹 라우트나 정적 파일을 다시 체크 |
6 | fallback 리라이트 체크 및 적용 — 404 페이지를 렌더링하기 전에, 다이나믹 라우트와 정적 자산 모두 체크한 뒤 수행. getStaticPaths에서 fallback: true 나 blocking 을 사용했다면 이 fallback 리라이트는 실행되지 않습니다. |
리라이트(rewrite)에서 파라미터 사용 시 참고
리라이트 할 때 destination URL에 파라미터를 직접 사용하지 않으면, 자동으로 쿼리(query)로 전달돼요.
예를 들어,
module.exports = {
async rewrites() {
return [
{
source: '/old-about/:path*',
destination: '/about', // 여기서는 :path를 직접 쓰지 않았으니 쿼리로 전달됨
},
]
},
}
위처럼 작성하면 /old-about/some/page
로 접속했을 때, /about?path=some/page
로 처리되는 셈이에요.
만약 파라미터를 destination에 포함시키고 싶다면 이렇게 써야 해요:
destination: '/about/:path*',
그러면 /old-about/whatever
가 /about/whatever
로 바로 바뀌죠.
이런 내용이 왜 중요하냐면?
- 리다이렉트는 URL을 완전히 바꿔서 클라이언트가 새 주소로 이동하도록 하는 반면
- 리라이트는 내부적으로 경로를 변경해서 유저는 주소가 변하지 않는 것처럼 유지하면서 다른 페이지나 리소스를 보여줄 수 있어요.
그래서 이미지 요청이나 API 프록시, 특정 조건에서 페이지 렌더링 방식을 유연하게 제어할 때 리라이트를 많이 씁니다.
혹시 Next.js 라우팅, 리다이렉트, 리라이트 중 어디에 더 궁금한 점 있으면 언제든 질문 주세요! 직접 써보고 경험한 팁도 더 알려드릴게요.
Next.js에서 rewrites
설정을 할 때, 이 부분이 살짝 헷갈릴 수 있는데요. 오늘은 rewrites
에서 파라미터가 목적지(destination
)에 어떻게 전달되는지, 그리고 자동으로 쿼리로 넘어가지 않는 경우를 함께 살펴볼게요.
파라미터가 목적지에 사용될 경우, 다른 파라미터는 쿼리에 자동으로 전달되지 않아요
다음 코드를 보시면,
module.exports = {
async rewrites() {
return [
{
source: '/docs/:path*',
destination: '/:path*', // :path 파라미터를 destination에서 이미 사용하고 있어요.
},
]
},
}
source
에 /docs/:path*
가 있는데, destination
에서도 똑같이 /:path*
를 사용 중이에요. 중요한 점은 이렇게 destination
에서 이미 파라미터를 사용하면, 나머지 파라미터는 자동으로 쿼리 스트링에 전달되지 않는다는 것!
즉, 만약 다른 파라미터가 있었다면 자동으로 ?파라미터=값
형태로 넘겨주지 않으니 주의해야 해요.
쿼리 파라미터를 직접 지정하면 수동으로 전달할 수 있어요
필요해서 쿼리에도 파라미터를 넘기고 싶다면 이렇게 직접 명시해주면 됩니다.
module.exports = {
async rewrites() {
return [
{
source: '/:first/:second',
destination: '/:first?second=:second',
// :first는 destination 경로에서 이미 사용중이라,
// :second는 자동 쿼리 전달이 안 되는데 직접 쿼리에 넣어줬어요.
},
]
},
}
/:first/:second
경로에서 destination
이 /:first?second=:second
이니, first
는 경로에, second
는 쿼리스트링에 직접 넣어주면서 목적지 URL을 생성합니다.
어떻게 활용하면 좋을까?
- 복잡한 URL 매핑 할 때 각 파라미터를 어떻게 쓸지 정리하기 편해요.
- 특정 파라미터를 경로에 반드시 넣어야 할 때, 나머지는 쿼리로 주고 싶다면 위처럼 수동 지정해야 합니다.
- 자동 쿼리 전달이 원치 않는 경우에도 활용할 수 있죠.
참고: Next.js rewrites
공식 문서
Next.js Rewrites 공식 문서에서 더 다양한 예시와 옵션을 확인할 수 있으니, 실제 프로젝트에 바로 적용하기 전에 한 번쯤 훑어보시길 추천드려요!
재미있는 점은, 이런 기본 동작을 이해하면 라우팅을 더 유연하게 다룰 수 있다는 거예요. 다음에도 이런 실용적인 팁으로 찾아올게요. 궁금한 점 있으면 언제든 질문 환영입니다! 😄
참고할 점: Automatic Static Optimization이나 rewrites에서 사용하는 prerendering 파라미터를 통해 생성된 정적 페이지들은 hydration 이후 클라이언트에서 파싱되고, 이 정보가 쿼리로 제공됩니다.
경로 매칭(Path Matching)
Next.js에서 경로 매칭은 매우 유연하게 사용할 수 있는데요. 예를 들어 /blog/:slug
같은 패턴은 /blog/hello-world
같은 경로와 매칭됩니다. 여기서 :slug
는 동적으로 변할 수 있는 부분입니다. 단, 중첩된 경로(예: /blog/2023/03
같은)는 매칭하지 않으니 참고하세요.
다음은 rewrites
설정 예시입니다:
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug',
destination: '/news/:slug', // 매칭된 파라미터를 destination 경로에서도 사용할 수 있습니다.
},
]
},
}
좀 더 알아보기
rewrites
는 클라이언트가 요청한 URL을 내부적으로 다른 경로로 매핑해 주는 기능이라, 실제로 URL은 바뀌지 않으면서 다른 페이지의 콘텐츠를 보여줄 수 있습니다.- 매개변수
:slug
같은 동적 세그먼트를 활용하면 더욱 깔끔하고 유연한 URL 구조를 만들 수 있죠. - 중첩 경로나 와일드카드 사용이 필요하다면 Next.js의 다른 기능들(ex. catch-all routes)을 활용하는 것도 좋은 방법입니다.
이 기능을 잘 활용하면 URL 디자인을 자유롭게 변경하면서도, 기존에 만들어 둔 페이지 컴포넌트 재사용이 가능해집니다!
와일드카드 경로 매칭 (Wildcard Path Matching)
Next.js에서 와일드카드 경로를 매칭하고 싶다면, 경로 매개변수 뒤에 *
를 붙여주면 돼요. 예를 들어 /blog/:slug*
라고 쓰면 /blog/a/b/c/d/hello-world
같은 경로도 한 번에 매칭이 된답니다.
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // 매칭된 파라미터를 목적지 경로에서도 사용할 수 있어요
},
]
},
}
여기서 중요한 점!
:slug*
에서 *
는 이 뒤에 어떤 경로가 와도 다 잡아준다는 의미에요. 즉, /blog/a
도 되고, /blog/a/b/c
도 다 같은 규칙으로 잡히는 거죠.
이걸 이용하면 블로그 포스트나 여러 단계로 깊은 경로를 리다이렉트할 때 아주 유용합니다.
정규식(Regex) 경로 매칭
Next.js rewrites
설정에서 복잡한 경로 지정이 필요할 때는 정규식을 써서 더욱 세밀한 매칭도 가능해요.
정규식은 보통 문자열 패턴 매칭에 강력한 무기인 만큼, 유연한 라우팅 구현에 큰 도움이 됩니다.
예를 들어, /post/:id(\\d+)
라는 경로는 숫자(id)가 들어가는 경로만 정확히 잡고 싶을 때 쓸 수 있어요.
즉 /post/123
는 매칭되고 /post/abc
는 매칭 안되도록 하는 거죠.
여기까지 와일드카드와 정규식 경로 매칭에 대해서 간단히 살펴봤는데요,
다음에는 정규식을 써서 실제로 어떻게 경로를 재작성하는지 예제를 들어서 더 쉽게 알려드릴게요!
궁금한 점 있으면 댓글로 남겨주세요.
정규식(Regex)로 경로를 매칭하고 싶다면, 파라미터 뒤에 괄호() 안에 정규식을 감싸서 사용할 수 있어요. 예를 들어, /blog/:slug(\\d{1,})
라고 하면 /blog/123
처럼 숫자로만 된 경로는 매칭되고 /blog/abc
같은 문자는 매칭되지 않아요.
아래 예시를 볼게요:
module.exports = {
async rewrites() {
return [
{
source: '/old-blog/:post(\\d{1,})',
destination: '/blog/:post', // 매칭된 파라미터를 목적지 경로에서 사용할 수 있어요
},
]
},
}
위 코드에서 :post(\\d{1,})
는 1자리 이상 숫자가 와야 매칭돼요. 그래서 /old-blog/123
으로 요청하면 /blog/123
으로 리다이렉트되는 거죠.
추가로, 정규식에서 특수문자들인 (
, )
, '
,
, [
, ]
, |
, \
, ^
, .
, :
, *
, +
, -
, ?
, $
같은 문자는 그냥 쓰면 안 되고, 그냥 문자열로 매칭하고 싶으면 반드시 앞에 역슬래시(\
)를 붙여서 이스케이프 해야 해요.
예를 들어, 경로에 괄호가 포함된 pattern을 매칭하고 싶을 때는 이렇게 작성하시면 됩니다:
module.exports = {
async rewrites() {
return [
{
// `/english(default)/something` 처럼 괄호가 포함된 경로를 매칭합니다
source: '/english\\(default\\)/:slug',
destination: '/en-us/:slug',
},
]
},
}
이 경우 /english(default)/page1
로 들어오는 요청은 /en-us/page1
으로 리다이렉트되죠.
정리하면, Next.js rewrites 등에서 경로 매칭 시 정규식을 사용할 때는
- 파라미터 뒤에 괄호로 정규식을 감싸서 세부 매칭 조건을 줄 수 있고
- 특수문자는
\\
로 꼭 이스케이프해서 사용하세요.
그래야 원하는 경로를 정확히 매칭할 수 있고 의도치 않은 오류를 예방할 수 있습니다.
이 방식으로 유연하게 URL 경로 패턴을 조절해보세요! 개발할 때 알아두면 꽤 유용합니다.
헤더, 쿠키, 쿼리 매칭하기
리라이트(rewrite)를 특정 조건에 맞출 때 헤더, 쿠키, 쿼리 값이 특정 값과 맞아야 하거나, 특정 값이 없어야 할 때도 있죠? 이럴 때 사용하는 게 바로 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
부분만 뽑아서 나중에 리라이트 목적지(destination)에서 :paramName
라는 이름으로 활용할 수 있다는 점도 참신하죠?
조금 더 풀어보자면
has
는 “이것들이 있어야 한다”는 의미예요.missing
은 “이것들이 없어야 한다”는 조건이죠.
예를 들어,
has
에{ type: 'header', key: 'x-user', value: 'admin' }
가 있으면,x-user
헤더가admin
이어야 리라이트됩니다.missing
에{ type: 'cookie', key: 'session', value: undefined }
가 있으면,session
이라는 쿠키가 없어야 리라이트가 적용됩니다.
이런 조건들을 조합하면 꽤 상세하고 구체적인 요청 매칭을 할 수 있답니다!
이 기능을 활용하면 더 똑똑하고 유연한 리라이트를 구현할 수 있어서, 특정 조건에 따라 페이지를 다르게 보여주거나 API 요청처리를 달리 할 때 정말 유용해요. 다음에 직접 예제도 만들어서 보여드릴게요!
Next.js의 rewrites
기능을 사용하면 특정 요청에 대해 URL 경로를 내부 또는 외부 URL로 "재작성(rewrite)"할 수 있어요. 이 기능은 특히 점진적으로 Next.js를 도입하거나, 내부 URL을 사용자에게 숨기고 싶을 때 유용하게 쓰입니다.
헤더, 쿼리, 쿠키, 호스트에 따른 rewrites 예시
module.exports = {
async rewrites() {
return [
// 1. 요청 헤더에 'x-rewrite-me'가 있으면 '/another-page'로 보낸다
{
source: '/:path*',
has: [
{ type: 'header', key: 'x-rewrite-me' },
],
destination: '/another-page',
},
// 2. 요청 헤더에 'x-rewrite-me'가 없으면 '/another-page'로 보낸다
{
source: '/:path*',
missing: [
{ type: 'header', key: 'x-rewrite-me' },
],
destination: '/another-page',
},
// 3. 쿼리 'page=home'이고 쿠키 'authorized=true'일 때 '/specific/:path*/home'으로 보낸다
{
source: '/specific/:path*',
has: [
{ type: 'query', key: 'page', value: 'home' },
{ type: 'cookie', key: 'authorized', value: 'true' },
],
destination: '/:path*/home',
},
// 4. 헤더 'x-authorized'에 'yes' 또는 'true'가 포함되어 있으면 '/home'에 쿼리로 authorized 값 붙이기
{
source: '/:path*',
has: [
{ type: 'header', key: 'x-authorized', value: '(?<authorized>yes|true)' },
],
destination: '/home?authorized=:authorized',
},
// 5. 호스트가 'example.com'이면 '/another-page'로 보낸다
{
source: '/:path*',
has: [
{ type: 'host', value: 'example.com' },
],
destination: '/another-page',
},
]
},
}
위 예시에서 볼 수 있듯이, 단순히 경로만 보고 리다이렉트하는 게 아니라 헤더, 쿠키, 쿼리 파라미터, 심지어 호스트까지 고려해서 경로를 바꿀 수 있습니다. 만약 조건에 맞는 헤더가 있으면 rewrite를 다르게 적용하는 식으로 세밀한 컨트롤이 가능해요.
외부 URL로도 리라이트가 가능합니다!
재밌는 점은 내부 페이지뿐 아니라 외부 URL로도 갈 수 있다는거예요. 예를 들어, 기존 웹사이트의 특정 경로를 Next.js 안에서 재작성해서 외부 사이트로 연결하고 싶을 때 아주 유용하죠.
module.exports = {
async rewrites() {
return [
// '/blog' 경로는 https://example.com/blog 로 이동
{
source: '/blog',
destination: 'https://example.com/blog',
},
// '/blog/:slug' 경로도 https://example.com/blog/:slug 로 매칭되는 대로 이동
{
source: '/blog/:slug',
destination: 'https://example.com/blog/:slug',
},
]
},
}
이처럼 외부 URL도 destination
에 바로 적으면 그쪽으로 요청을 보낼 수 있답니다. 특히 마이그레이션 기간에 기존 서비스와 신 서비스를 자연스럽게 연결할 때 매우 유용해요.
추가 팁!
- rewrites vs redirects: rewrites는 URL을 바꿔서 서버에서 다른 페이지를 보여주지만, 실제 사용자에게는 원래 URL이 유지돼요. 반면 redirects는 사용자를 다른 URL로 실제로 이동시키고 브라우저 주소창도 바뀝니다.
- 조건이 많을 때는 꼭 주의: 너무 복잡한 조건을 걸면 관리하기 어려우니, 가독성을 고려해서 몇 개의 룰을 잘 분리해서 쓰는 게 좋아요.
- value를 안쓰거나 캡처 그룹을 쓰면 경로 파라미터 활용 가능: 위 예시처럼
(??<authorized>yes|true)
처럼 정규표현식 캡처 그룹을 쓰면 재작성 대상 경로에 캡처된 값을 쉽게 쓸 수 있어요.
이제 필요에 따라 세밀하게 페이지 경로를 조작해보세요! Next.js rewrites 기능은 생각보다 강력해서 몇 가지 응용만 알면 정말 다양한 케이스에 적용할 수 있답니다. 🙂
next.js에서 trailingSlash: true
설정을 사용할 때 꼭 알아둬야 할 점이 있어요. 바로 리다이렉트(rewrites) 설정할 때 source
경로 끝에도 꼭 슬래시(/)를 붙여줘야 한다는 거죠. 목적지(destination) URL도 마찬가지예요. 만약 원격 서버가 슬래시를 기대한다면 destination 경로 끝에도 슬래시를 붙여줘야 정상적으로 동작합니다.
예를 들어, 아래와 같이 설정하면 /blog/
또는 /blog/
하위 경로로 들어오는 요청을 정확히 리다이렉트할 수 있어요.
module.exports = {
trailingSlash: true,
async rewrites() {
return [
{
source: '/blog/',
destination: 'https://example.com/blog/',
},
{
source: '/blog/:path*/',
destination: 'https://example.com/blog/:path*/',
},
]
},
}
여기서 :path*
는 와일드카드처럼 동작해서 /blog/anything/here/
같은 하위 경로도 전부 포괄해줍니다.
Next.js 점진적 도입 (Incremental adoption)
또 하나 재미있는 점은, 기존에 운영 중인 웹사이트가 있을 때 Next.js로 점진적으로 옮겨갈 수 있다는 거예요. Next.js가 먼저 자신의 라우트들을 검사한 후에 해당 경로가 없다면 기존 서버 쪽으로 프록시(proxy) 요청을 넘기는 방법이죠.
이 방식을 사용하면 한 번에 모든 페이지를 Next.js로 옮기지 않아도 되고, 조금씩 옮기면서 안정적으로 서비스를 개선할 수 있답니다.
추가 팁!
trailingSlash
옵션을 켜면 빌드된 정적 파일들도 자동으로 폴더 형식으로 생성됩니다. 예를 들어/about
은/about/index.html
로 만들어지고, 브라우저에서는/about/
URL로 접근하게 되죠.- 리다이렉트 설정에서 슬래시는 사소해 보여도, 이 부분이 틀리면 404 에러가 날 수 있으니 꼭 신경 써 주세요.
- 점진적 도입을 고려한다면, Next.js의
rewrites
와fallback
기능을 적극 활용해보세요. 개발할 때 훨씬 유연해질 거예요!
다음에도 Next.js 관련해서 재미있고 쓸모 있는 팁 있으면 계속 공유할게요!
Next.js로 더 많은 페이지를 마이그레이션할 때, 리라이트(rewrites) 설정을 매번 바꿀 필요가 없도록 하는 방법을 알려 드릴게요.
module.exports = {
async rewrites() {
return {
fallback: [
{
source: '/:path*',
destination: `https://custom-routes-proxying-endpoint.vercel.app/:path*`,
},
],
}
},
}
이렇게 하면 어떤 경로로 들어오든 https://custom-routes-proxying-endpoint.vercel.app
쪽으로 다 연결해주는 역할을 해요. 그래서 점진적으로 Next.js로 옮겨가는 중에도 기존 경로를 일일이 바꿀 필요 없이 한 번에 처리할 수 있죠.
basePath 지원하는 리라이트
Next.js에서 basePath
를 사용하면서 리라이트를 할 때는 source
와 destination
양쪽 경로 모두 자동으로 basePath
가 앞에 붙어요. 만약 어떤 리라이트에서 basePath
를 붙이고 싶지 않으면, 아래처럼 basePath: false
를 추가하면 됩니다.
module.exports = {
async rewrites() {
return {
fallback: [
{
source: '/custom-path/:path*',
destination: 'https://external-site.com/:path*',
basePath: false, // basePath 자동 접두사 안붙임
},
],
}
},
}
이렇게 쓰면 basePath
가 없는 그대로 외부 도메인 주소로 리다이렉션하게 돼요.
추가 팁!
rewrites
는 URL 경로를 클라이언트에게 그대로 보여주면서 내부적으로 다른 경로로 연결해주는 기능이에요. SEO나 UX에 민감한 상황에서 유용하죠.fallback
속성은 일치하는 리라이트 규칙이 없을 때 마지막으로 적용되는 규칙이라, 넓은 범위의 라우팅을 처리할 때 깔끔하게 쓸 수 있어요.- 만약 API 요청 경로나 이미지 리퀘스트에 리라이트를 복잡하게 적용해야 한다면, 별도의 규칙으로 꼼꼼히 테스트해보세요.
Next.js에서 라우팅을 다루는 게 어렵게 느껴질 수 있지만, 이런 설정들을 잘 활용하면 한결 유연하고 깔끔하게 관리할 수 있으니 꼭 한번 시도해보세요!
module.exports = {
basePath: '/docs',
async rewrites() {
return [
{
source: '/with-basePath', // /docs/with-basePath로 자동 변환됨
destination: '/another', // /docs/another로 자동 변환됨
},
{
// basePath: false가 설정되어 있어 /docs가 붙지 않음
// 참고: 내부 리다이렉트(예: destination: '/another')에는 사용할 수 없음
source: '/without-basePath',
destination: 'https://example.com',
basePath: false,
},
]
},
}
버전 히스토리
Version | Changes |
---|---|
v13.3.0 | missing 추가됨 |
v10.2.0 | has 추가됨 |
v9.5.0 | Headers 추가됨 |
살짝 더 알려드려요!
- basePath는 Next.js에서 모든 경로 앞에 특정 기본 경로를 붙이고 싶을 때 사용해요. 예를 들어, 위 예제처럼
basePath: '/docs'
를 설정하면, 모든 페이지와 API가/docs
하위에 위치해요. rewrites
는 요청 경로를 다른 경로나 외부 URL로 내부적으로 바꿔주는 역할을 하죠. 위 코드에서는/with-basePath
요청이/docs/with-basePath
로,/another
경로로도 매핑되는 걸 볼 수 있어요.- 그런데
basePath: false
옵션이 들어간 리라이트는 좀 특별해요. 이 옵션을 주면 기본 경로가 붙지 않고, 외부 URL(예:https://example.com
)로 바로 연결할 수 있어요. 다만, 내부 경로 리라이트에선 사용할 수 없으니 주의하세요. - 버전 히스토리를 보면 점차 기능이 추가되고 확장된 걸 알 수 있는데, 개발 중인 프로젝트에 필요한 기능이 어느 버전부터 생겼는지 참고하면 좋아요!
다음에 또 재미있는 개발 팁 들고 올게요! 궁금한 점 있으면 언제든 물어봐 주세요~