개요
Next.js는 리디렉션을 처리하는 여러 방법이 있다.
Next.js에서 지원하는 리디렉션 api는 다음과 같다.
API | Purpose | Where | Status Code |
redirect | 사용자 동작 또는 이벤트 후 리디렉션 | Server Components, Server Actions, Route Handlers | 307 (Temporary) or 303 (Server Action) |
permanentRedirect | 사용자 동작 또는 이벤트 후 영구 리디렉션 | Server Components, Server Actions, Route Handlers | 308 (Permanent) |
useRouter | 클라이언트 측 내비게이션 수행 | 클라이언트 컴포넌트의 이벤트 핸들러 | N/A |
redirects in next.config.js | 경로 기반으로 들어오는 요청 리디렉션 | next.config.js 파일 | 307 (Temporary) or 308 (Permanent) |
NextResponse.redirect | 조건 기반으로 들어오는 요청 리디렉션 | Middleware | Any |
본 글에서는 redirect, permanentRedirect, useRouter, next.config.js에서의 리디렉션, middleware에서의 리디렉션에 대해 기술하였다.
redirect
서버 컴포넌트의 경우 redirect() 함수를 사용한다.
import { redirect } from 'next/navigation'
async function fetchTeam(id: string) {
const res = await fetch('https://...')
if (!res.ok) return undefined
return res.json()
}
export default async function Profile({ params }: { params: { id: string } }) {
const team = await fetchTeam(params.id)
if (!team) {
redirect('/login')
}
// ...
}
redirect() 함수 사용 시 주의/유의사항
- redirect 함수는 기본적으로 307 상태 코드를 반환한다.
- 하지만 서버에서 데이터를 보낸 후 redirect 함수를 사용 시 303 코드를 반환한다.
- redirect 함수는 일부러 오류처럼 동작한다.때문에 try/catch 블록 바깥에서 사용한다.
- 때문에 try/catch와 같은 오류 처리 블록에서 사용 시 반드시 오류가 발생하게 된다.
- redirect는 렌더링 프로세스 도중에만 호출이 가능하다. 이벤트 핸들러에서는 호출이 불가능하다. 이벤트 핸들러에서는 useRouter() 함수 내의 push 메소드를 사용한다.
- ex) 이사람 로그인 안했네? 로그인 페이지로 보내버려야겠다. 와 같은 상황에서 사용
- redirect는 외부 링크도 허용한다.
- ex) redirect("https://www.google.com")
- 렌더링 프로세스 전에 리디렉션하려면 next.config.js 또는 미들웨어를 사용한다.
예제 코드( next.config.js )
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
async redirects() {
return [
{
source: '/old-page', // 사용자가 이 주소로 오면
destination: '/new-page', // 여기로 보내버림
permanent: true, // 301 (영구 리디렉션)
},
]
},
}
module.exports = nextConfig;
- 예제 코드( middleware.ts )
// middleware.ts (또는 middleware.js)
import { NextRequest, NextResponse } from 'next/server'
export function middleware(request: NextRequest) {
const isLoggedIn = request.cookies.get('token')?.value; // 로그인 쿠키 검사
if (!isLoggedIn && request.nextUrl.pathname.startsWith('/mypage')) {
// 로그인 안 했는데 /mypage에 접근하면 로그인으로 보냄
return NextResponse.redirect(new URL('/login', request.url));
}
// 다른 경우엔 통과
return NextResponse.next();
}
permanentRedirect function
permanentRedirect 함수는 사용자를 다른 URL로 영구적으로 리디렉션할 수 있게 해준다.
Server Component, Route Handlers, Server Actions에서 호출할 수 있다.
permanentRedirect는 종종 엔터티의 캐노니컬 URL(표준 URL)이 변경된 후 사용된다.
예를 들어 사용자가 사용자 이름을 변경하여서 프로필 URL을 업데이트해야하는 경우가 있다.
app/actions.ts
'use server'
import { permanentRedirect } from 'next/navigation'
import { revalidateTag } from 'next/cache'
export async function updateUsername(username: string, formData: FormData) {
try {
// Call database
} catch (error) {
// Handle errors
}
revalidateTag('username') // Update all references to the username
permanentRedirect(`/profile/${username}`) // Navigate to the new user profile
}
permanentRedirect는 기본적으로 308(영구 리디렉션) 상태 코드를 반환한다.
permanentRedirect는 절대 URL도 허용하며 외부 링크로 리디렉션하는데 사용할 수 있다.
렌더링 프로세스 전에 리디렉션하려면 next.config.js 또는 미들웨어를 사용해야 한다.
useRouter hook
useRouter() 훅을 사용하여 클라이언트 컴포넌트 방식으로 경로 변경이 가능하다.
'use client'
import { useRouter } from 'next/navigation'
export default function Page() {
const router = useRouter()
return (
<button type="button" onClick={() => router.push('/dashboard')}>
Dashboard
</button>
)
}
‘use client’를 상단에 작성하여 클라이언트 컴포넌트임을 명시한 후 사용하여야 한다.
타 클라이언트 컴포넌트에서 특정 url로 linking이 필요할 시 유용하다.
redirects in next.config.js
next.config.js 파일의 redirects 옵션을 사용하면 들어오는 요청 경로를 다른 목적지 경로로 리디렉션할 수 있다.
이는 페이지의 URL 구조를 변경하거나 미리 알려진 리디렉션 목록이 있는 경우 유용하다.
redirects는 경로, 헤더, 쿠키 및 쿼리 매칭을 지원하여 들어오는 요청을 기반으로 사용자를 리디렉션할 수 있는 유연성을 제공한다.
이를 활용하기 위해선 설계 단계에서 요청 헤더, 쿠키, 쿼리 값을 어떻게 사용할지 미리 결정해야 한다.
next.config.ts
module.exports = {
async redirects() {
return [
// Basic redirect
{
source: '/about',
destination: '/',
permanent: true,
},
// Wildcard path matching
{
source: '/blog/:slug',
destination: '/news/:slug',
permanent: true,
},
]
},
}
redirects는 permanent 옵션과 함께 307(Temporary Redirect - 임시 이동) 또는 308(Permanent Redirect - 영구 이동) 상태 코드를 반환할 수 있다.
redirects는 플랫폼에 제한이 있을 수 있다.
예를 들어 Vercel에서는 1,024개의 리디렉션 제한이 있다.
1,024개를 초과하는 대규모 리디렉션 관리를 위해서는 Middleware를 사용하여 사용자 지정 솔루션을 만들어야 한다.
제한이 있는 이유는 CDN 용량 제한이 있기 때문이다.
redirects는 Middleware 이전에 실행된다.
NextResponse.redirect in Middleware
Middleware는 요청이 완료되기 전에 코드를 실행할 수 있게 한다.
그 후 들어오는 요청을 기반으로 다른 URL로 리디렉션할 수 있다.
즉 중간에 요청을 가로챈다.
흐름은 다음과 같다.
[사용자 요청]
↓
[Middleware 실행] ← 여기서 검사, 리디렉션 등 처리
↓
[해당 라우트로 요청 전달 or 중단/리디렉션]
아래와 같은 상황에서 사용한다.
🔐 인증 처리 | 로그인 안 한 사용자를 /login으로 리디렉션 |
🌍 지역/언어 리디렉션 | Accept-Language 헤더에 따라 /ko, /en 페이지로 자동 이동 |
🧪 실험/분기 테스트 | 특정 쿠키 값으로 AB 테스트 페이지 분기 |
🚧 대규모 리디렉션 | 1000개 이상 리디렉션 조건을 코드로 처리 |
사용자가 인증되지 않은 경우 /login 페이지로 리디렉션 하는 코드는 다음과 같다.
middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const loggedIn = request.cookies.get('logged_in')?.value;
if (!loggedIn && request.nextUrl.pathname.startsWith('/dashboard')) {
// 로그인 안 됐으면 /dashboard 접근 막고 /login으로 리디렉션
return NextResponse.redirect(new URL('/login', request.url));
}
// 아무 문제 없으면 그냥 통과
return NextResponse.next();
}
위와 같이 작성할 수도 있고 auth-provider와 같은 모듈을 lib/, utils/, services/와 같은 위치에 추가하여 다음과 같이 작성할 수도 있다.
middleware.ts
import { NextResponse, NextRequest } from 'next/server'
import { authenticate } from 'auth-provider'
export function middleware(request: NextRequest) {
const isAuthenticated = authenticate(request)
// If the user is authenticated, continue as normal
if (isAuthenticated) {
return NextResponse.next()
}
// Redirect to login page if not authenticated
return NextResponse.redirect(new URL('/login', request.url))
}
export const config = {
matcher: '/dashboard/:path*',
}
auth-provider.ts
// auth-provider.ts
import { NextRequest } from 'next/server'
export function authenticate(request: NextRequest): boolean {
const token = request.cookies.get('auth_token')?.value
// 예: 토큰이 존재하면 로그인된 사용자로 간주
return Boolean(token)
}
'Next.js' 카테고리의 다른 글
[Next.js] Spring boot 서버로부터 Session 토큰 받은 후 자동 저장하기 (2) | 2025.05.02 |
---|---|
[Next.js] Next.js에서의 에러 경계 설정과 스트리밍 기반의 로딩 UI 구현 전략 (0) | 2025.04.20 |
[Next.js] 네비게이션 작동 원리 (0) | 2025.04.19 |
[Next.js] Next.js 라우팅과 렌더링 원리 (0) | 2025.04.15 |