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 데이터 최적화 대규모 경로 관리 성능 최적화 매우 빠름