Next.js Proxy 정리

Next.js Docs – Getting Started: Proxy 페이지를 기반으로, App Router 환경에서의 Proxy(구 Middleware) 사용 방법을 정리한 문서입니다.


1. Proxy 개요

  • Next.js 16부터 Middleware → Proxy로 이름이 변경되었습니다. (역할은 동일합니다.)
  • Proxy는 요청이 완료되기 전에 실행되는 코드입니다.
  • 들어오는 요청을 기준으로 다음과 같은 작업을 수행할 수 있습니다.
    • 다른 경로로 rewrite
    • 다른 URL로 redirect
    • 요청/응답 헤더 수정
    • 직접 응답 반환

즉, 요청이 실제 페이지나 API에 도달하기 전에 공통의 전처리 레이어를 넣는 기능이라고 볼 수 있습니다.


2. Proxy 사용 사례 (Use cases)

Proxy가 유용하게 쓰이는 대표적인 예시는 다음과 같습니다.

  1. 헤더 공통 처리

    • 모든 페이지 또는 일부 페이지에 대해 공통적으로 헤더를 추가/수정해야 할 때
    • 예: 보안 헤더, 실험 플래그 헤더 등
  2. A/B 테스트 또는 실험을 위한 라우팅

    • 유입 경로나 쿠키, 실험 그룹에 따라 서로 다른 페이지로 rewrite
    • 예: /pricing 방문자를 그룹 A/B에 따라 다른 컴포넌트로 보내기
  3. 프로그램적인 리다이렉트

    • 요청 정보(쿠키, 헤더, GeoIP 등)를 기반으로 분기하여 redirect
    • 예: 로그인 여부에 따라 /login 또는 /dashboard로 이동

2.1 언제 Proxy 대신 다른 기능을 사용해야 하는가

  • 단순한 리다이렉트만 필요하다면

    • 먼저 next.config.ts의 [redirects 설정](예: /old/new)을 고려하는 것이 좋습니다.
    • Proxy는 요청 정보에 접근하거나 복잡한 로직이 필요한 경우에 사용하는 것을 권장합니다.
  • 완전한 세션 관리·인증 솔루션으로 Proxy를 사용하는 것은 권장되지 않습니다.

    • Proxy는 빠른 권한 체크(optimistic checks) 같은 곳에 적합합니다.
    • 느린 데이터 패칭이나 복잡한 인증 플로우 전체를 Proxy에서 처리하는 용도로는 적합하지 않습니다.
  • Proxy 내부에서 fetch를 사용할 때

    • options.cache, options.next.revalidate, options.next.tags 옵션은 효과가 없습니다.
    • 즉, Proxy에서는 fetch 기반의 Next.js 캐싱/리밸리데이션 기능이 동작하지 않습니다.

3. Proxy 파일 컨벤션 (Convention)

Proxy는 프로젝트 루트 또는 src 루트에 proxy.ts(또는 proxy.js) 파일을 만들어 사용합니다.

my-app/
  app/
  pages/
  proxy.ts     // 또는 proxy.js

또는 src 구조를 사용할 경우:

my-app/
  src/
    app/
    pages/
    proxy.ts
  • 프로젝트당 하나의 proxy.ts 파일만 지원됩니다.
  • 대신, 실제 로직은 다른 모듈로 분리한 뒤 proxy.ts에서 import 하여 사용할 수 있습니다.
    • 예: authProxy.ts, abTestProxy.ts 등으로 분리 후 proxy.ts에서 조합
  • 단일 proxy 파일만 허용하는 이유
    • 설정 및 동작이 단순해지고,
    • 여러 Proxy 레이어가 겹치며 발생할 수 있는 충돌을 방지하며,
    • 성능 최적화에도 유리합니다.

4. 기본 예제 (Example)

Proxy 함수는 named export proxy 또는 default export로 내보낼 수 있습니다.

// proxy.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

// 필요 시 async 함수로 선언 가능
export function proxy(request: NextRequest) {
  // 예: /about/* 경로에 접근하면 /home으로 리다이렉트
  return NextResponse.redirect(new URL('/home', request.url))
}

// 또는 default export 사용도 가능
// export default function proxy(request: NextRequest) { ... }

// 어떤 경로에 Proxy를 적용할지 설정
export const config = {
  matcher: '/about/:path*',
}

4.1 matcher 설정

  • config.matcherProxy가 적용될 경로 패턴을 정의합니다.
    • 예: '/about/:path*'/about, /about/team, /about/company 등 모든 하위 경로에 적용
  • matcher는 Route Handlers, Middleware 등에서 사용하던 패턴과 동일합니다.
    • 와일드카드(*), 동적 세그먼트(:path*) 등을 사용할 수 있습니다.

4.2 동작 흐름 정리

  1. 사용자가 /about/company 요청
  2. matcher: '/about/:path*'에 의해 Proxy가 실행
  3. Proxy 내부 로직에서 /home으로 redirect
  4. 클라이언트는 /home 응답을 받게 됨

5. Proxy 사용 시 주의 사항 정리

  • Proxy는 요청 전처리 레이어로 이해하는 것이 좋습니다.
    • 공통 헤더 처리, 간단한 권한 체크, A/B 테스트 분기를 구현하는 데 적합합니다.
  • 느린 데이터 조회나 완전한 인증·세션 관리는 Route Handlers, 서버 액션, 전용 인증 솔루션(예: NextAuth, 자체 인증 서버) 등에서 처리하는 것이 더 좋습니다.
  • Proxy 내부 fetch에서 Next.js 캐시 관련 옵션(cache, next.revalidate, next.tags)은 작동하지 않습니다.
  • 프로젝트 전체에서 Proxy 파일은 **오직 하나 (proxy.ts 또는 proxy.js)**만 사용할 수 있습니다.
    • 대신 여러 파일로 나누어 import하여 Proxy 로직을 모듈화하도록 구성할 수 있습니다.