Next.js 개발 가이드/06. Learn Next.js 공식 가이드
[Next.js] Redirecting - 리다이렉팅
Tech쏜
2024. 12. 31. 08:50
useRouter() Hook을 사용한 클라이언트 사이드 리디렉션
사용자가 버튼을 눌렀을 때 특정 페이지로 이동하도록 하고 싶을 때 사용한다.
import { useRouter } from 'next/router';
export default function Page() {
const router = useRouter();
return (
<button type="button" onClick={() => router.push('/dashboard')}>
Dashboard
</button>
);
}
- router.push('/dashboard')를 호출하면 /dashboard 페이지로 클라이언트 사이드에서 이동한다.
- 장점: 사용자가 현재 보고 있는 페이지를 리로드하지 않고 이동 가능.
- 활용 사례: 로그인 후 대시보드로 이동, 특정 버튼 클릭 시 이동 등.
next.config.js를 사용한 서버 사이드 리디렉션
URL 구조를 변경하거나, 특정 경로를 다른 경로로 영구적으로 리디렉션할 때 유용하다.
미리 정해진 고정된 리디렉션을 처리.
module.exports = {
async redirects() {
return [
// '/about'을 '/'로 리디렉션
{
source: '/about',
destination: '/',
permanent: true, // 308 상태 코드
},
// '/blog/:slug'를 '/news/:slug'로 리디렉션
{
source: '/blog/:slug',
destination: '/news/:slug',
permanent: true, // 308 상태 코드
},
];
},
};
- source: 리디렉션의 시작 경로.
- destination: 이동할 경로.
- permanent: true면 308 상태 코드(영구 리디렉션), false면 307 상태 코드(임시 리디렉션).
- 활용 사례: 페이지 경로 변경, SEO 최적화, 오래된 URL 리디렉션 등.
Middleware를 사용한 조건부 리디렉션
사용자의 로그인 여부에 따라 접근을 제한하거나 특정 조건에 따라 경로를 리디렉션할 때 사용한다.
실시간 데이터 처리 및 조건 기반 리디렉션에 유용.
// middleware.ts
import { NextResponse, NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const isAuthenticated = checkUserAuthentication(request);
// 인증된 사용자만 접근 가능
if (!isAuthenticated) {
return NextResponse.redirect(new URL('/login', request.url));
}
// 계속 요청 처리
return NextResponse.next();
}
function checkUserAuthentication(request: NextRequest) {
const token = request.cookies.get('auth_token');
return !!token; // 토큰이 있으면 인증된 사용자로 간주
}
export const config = {
matcher: '/dashboard/:path*', // '/dashboard'와 하위 경로에만 적용
};
- 인증되지 않은 사용자는 /login으로 리디렉션됩니다.
- 활용 사례: 인증/인가 처리, 지역별 리디렉션, AB 테스트 등.
대규모 리디렉션 처리 (Middleware + 데이터베이스 연동)
리디렉션 경로가 1,000개 이상일 때, next.config.js에 모두 등록하면 관리가 어렵다.
이를 데이터베이스 또는 JSON 파일로 관리해 효율적으로 처리.
1. Redirect Map 생성
// redirects.json
{
"/old": {
"destination": "/new",
"permanent": true
},
"/blog/old-post": {
"destination": "/blog/new-post",
"permanent": false
}
}
2. Middleware에서 리디렉션 처리
// middleware.ts
import { NextResponse, NextRequest } from 'next/server';
import redirects from './redirects.json';
export function middleware(request: NextRequest) {
const pathname = request.nextUrl.pathname;
const redirectEntry = redirects[pathname];
if (redirectEntry) {
const statusCode = redirectEntry.permanent ? 308 : 307;
return NextResponse.redirect(redirectEntry.destination, statusCode);
}
// 리디렉션 경로가 없는 경우
return NextResponse.next();
}
대규모 리디렉션 성능 최적화 (Bloom Filter 활용)
Bloom Filter는 대규모 데이터에서 빠르게 특정 값의 존재 여부를 확인할 수 있는 데이터 구조이다.
// bloom-filter.json
{
"size": 1000,
"filter": [/* 필터 데이터 */]
}
// middleware.ts
import { ScalableBloomFilter } from 'bloom-filters';
import bloomFilterData from './bloom-filter.json';
const bloomFilter = ScalableBloomFilter.fromJSON(bloomFilterData);
export function middleware(request: NextRequest) {
const pathname = request.nextUrl.pathname;
if (bloomFilter.has(pathname)) {
// API 호출로 리디렉션 경로 가져오기
return fetch(`/api/redirects?pathname=${pathname}`)
.then(res => res.json())
.then(redirectEntry => {
if (redirectEntry) {
const statusCode = redirectEntry.permanent ? 308 : 307;
return NextResponse.redirect(redirectEntry.destination, statusCode);
}
return NextResponse.next();
});
}
return NextResponse.next();
}
요약 비교
방법사용 위치주요 사용 사례처리 속도
useRouter() | 클라이언트 | 버튼 클릭, 특정 동작 후 이동 처리 | 빠름 |
next.config.js | 서버 빌드 타임 | 고정된 리디렉션 처리, SEO 최적화 | 빠름 |
Middleware | 서버 런타임 | 인증/인가, 조건부 리디렉션 | 다소 느림 |
대규모 리디렉션 | 데이터베이스 연동 | 대규모 경로 관리, 실시간 처리 | 최적화 필요 |
Bloom Filter | 데이터 최적화 | 대규모 경로 관리 성능 최적화 | 매우 빠름 |