(준)공식 문서/Next.js

[ Next.js 15 공식 문서 ] Route Handlers and Middleware (라우트 핸들러와 미들웨어)

Je-chan 2025. 7. 20. 22:24

Route Handlers와 Middleware

Route Handlers

Route Handlers를 사용하면 Web RequestResponse API를 사용하여 특정 라우트에 대한 커스텀 요청 핸들러를 생성할 수 있습니다.

🔍 알아두면 좋은 점

Route Handlers는 app 디렉토리 내에서만 사용할 수 있습니다. 이들은 pages 디렉토리 내의 API Routes와 동등한 기능을 제공하므로 API Routes와 Route Handlers를 함께 사용할 필요가 없습니다.

규칙

Route Handlers는 app 디렉토리 내의 route.js|ts 파일에서 정의됩니다:

export async function GET(request: Request) {}

Route Handlers는 page.jslayout.js와 유사하게 app 디렉토리 내 어디에든 중첩될 수 있습니다. 하지만 page.js와 같은 라우트 세그먼트 레벨에는 route.js 파일이 있을 수 없습니다.

💡 실무 팁

Route Handlers는 다음과 같은 상황에서 특히 유용합니다:

  • API 엔드포인트 생성: 외부 API와 연동하거나 데이터베이스 조작
  • 파일 업로드 처리: 이미지나 문서 업로드 로직
  • Webhook 수신: 결제 서비스나 외부 서비스의 콜백 처리
  • 폼 데이터 처리: 복잡한 폼 제출 로직

지원되는 HTTP 메서드

다음 HTTP 메서드들이 지원됩니다: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS. 지원되지 않는 메서드가 호출되면 Next.js는 405 Method Not Allowed 응답을 반환합니다.

확장된 NextRequest와 NextResponse API

Next.js는 네이티브 RequestResponse API 지원에 더해, 고급 사용 사례를 위한 편리한 헬퍼를 제공하는 NextRequestNextResponse로 이를 확장합니다.

캐싱

Route Handlers는 기본적으로 캐시되지 않습니다. 하지만 GET 메서드에 대해서는 캐싱을 선택할 수 있습니다. 다른 지원되는 HTTP 메서드는 캐시되지 않습니다. GET 메서드를 캐시하려면 Route Handler 파일에서 export const dynamic = 'force-static'과 같은 라우트 설정 옵션을 사용합니다.

export const dynamic = 'force-static'

export async function GET() {
  const res = await fetch('https://data.mongodb-api.com/...', {
    headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY,
    },
  })
  const data = await res.json()

  return Response.json({ data })
}
🔍 알아두면 좋은 점

다른 지원되는 HTTP 메서드들은 같은 파일에서 캐시된 GET 메서드와 함께 배치되더라도 캐시되지 않습니다.

💡 실무 팁 - 캐싱 전략
  • 정적 데이터: 자주 변경되지 않는 데이터(설정, 상수 등)는 force-static 사용
  • 사용자별 데이터: 인증이 필요한 API는 캐싱 비활성화
  • 시간 기반 캐싱: revalidate 옵션으로 일정 시간 후 재검증
  • 태그 기반 캐싱: 특정 이벤트 발생 시 캐시 무효화가 필요한 경우

특별한 Route Handlers

sitemap.ts, opengraph-image.tsx, icon.tsx와 같은 특별한 Route Handlers와 기타 메타데이터 파일들은 Dynamic API나 동적 설정 옵션을 사용하지 않는 한 기본적으로 정적으로 유지됩니다.

라우트 해결

route를 가장 낮은 수준의 라우팅 기본 요소로 생각할 수 있습니다.

  • page처럼 레이아웃이나 클라이언트 사이드 네비게이션에 참여하지 않습니다.
  • page.js와 같은 라우트에는 route.js 파일이 있을 수 없습니다.
페이지 라우트 결과
app/page.js app/route.js ❌ 충돌
app/page.js app/api/route.js ✅ 유효
app/[user]/page.js app/api/route.js ✅ 유효

route.js 또는 page.js 파일은 해당 라우트의 모든 HTTP 동사를 담당합니다.

export default function Page() {
  return <h1>Hello, Next.js!</h1>
}

// ❌ 충돌
// `app/route.ts`
export async function POST(request: Request) {}

Middleware

Middleware를 사용하면 요청이 완료되기 전에 코드를 실행할 수 있습니다. 그런 다음 들어오는 요청을 기반으로 재작성, 리디렉션, 요청 또는 응답 헤더 수정, 또는 직접 응답하여 응답을 수정할 수 있습니다.

사용 사례

Middleware가 효과적인 몇 가지 일반적인 시나리오는 다음과 같습니다:

  • 들어오는 요청의 일부를 읽은 후 빠른 리디렉션
  • A/B 테스트나 실험을 기반으로 다른 페이지로 재작성
  • 모든 페이지 또는 페이지의 하위 집합에 대한 헤더 수정

Middleware는 다음과 같은 경우에는 적합하지 않습니다:

  • 느린 데이터 가져오기
  • 세션 관리
💡 실무 팁 - Middleware 활용 사례
  • 인증 체크: 로그인이 필요한 페이지 접근 제어
  • 지역화(i18n): 사용자 위치에 따른 언어/지역 설정
  • 봇 차단: User-Agent 기반 봇 트래픽 필터링
  • A/B 테스트: 특정 비율로 사용자를 다른 페이지로 분기
  • 성능 모니터링: 요청 시간 측정 및 로깅
  • 보안 헤더: CSP, CORS 등 보안 관련 헤더 추가

options.cache, options.next.revalidate, 또는 options.next.tags와 함께 fetch를 사용하는 것은 Middleware에서 효과가 없습니다.

규칙

Middleware를 정의하려면 프로젝트의 루트에 middleware.ts (또는 .js) 파일을 사용합니다. 예를 들어, pagesapp과 같은 레벨에, 또는 해당하는 경우 src 내부에 위치시킵니다.

🔍 알아두면 좋은 점

프로젝트당 하나의 middleware.ts 파일만 지원되지만, 여전히 미들웨어 로직을 모듈로 구성할 수 있습니다. 미들웨어 기능을 별도의 .ts 또는 .js 파일로 분리하고 메인 middleware.ts 파일로 import할 수 있습니다. 이를 통해 라우트별 미들웨어를 더 깔끔하게 관리하고, 중앙 집중식 제어를 위해 middleware.ts에서 통합할 수 있습니다. 단일 미들웨어 파일을 강제함으로써 설정을 단순화하고, 잠재적인 충돌을 방지하며, 여러 미들웨어 레이어를 피함으로써 성능을 최적화합니다.

예시

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

// `await`를 내부에서 사용하는 경우 이 함수를 `async`로 표시할 수 있습니다
export function middleware(request: NextRequest) {
  return NextResponse.redirect(new URL('/home', request.url))
}

// 경로 매칭에 대해 자세히 알아보려면 아래 "경로 매칭"을 참조하세요
export const config = {
  matcher: '/about/:path*',
}
💡 실무 팁 - Middleware 성능 최적화
  • 조건부 실행: matcher 설정으로 필요한 경로에서만 실행
  • 빠른 종료: 조건 체크를 최상단에 배치하여 불필요한 처리 방지
  • 비동기 작업 최소화: 무거운 연산은 Route Handler로 이동
  • 에러 핸들링: 예외 발생 시 기본 페이지로 fallback 처리
  • 로깅 신중하게: 모든 요청에서 실행되므로 로그 레벨 조절 필요

API 참조

Route Handlers와 Middleware에 대해 자세히 알아보세요:

  • route.js - route.js 특별 파일에 대한 API 참조.
  • middleware.js - middleware.js 파일에 대한 API 참조.
  • Backend for Frontend - Next.js를 백엔드 프레임워크로 사용하는 방법을 알아보세요.
💡 실무 팁 - 보안 고려사항
  • CORS 설정: Route Handler에서 적절한 CORS 헤더 설정
  • 요청 검증: 입력 데이터 유효성 검사 필수
  • 레이트 리미팅: API 남용 방지를 위한 요청 제한
  • 인증 토큰: JWT나 세션 기반 인증 구현
  • 환경 변수: 민감한 정보는 환경 변수로 관리
  • HTTPS 강제: Middleware에서 HTTP to HTTPS 리디렉션
📖 원문 링크

이 문서의 원문은 Next.js 공식 문서에서 확인하실 수 있습니다.