본문 바로가기

TIL

Next.js 미들웨어(Middleware)

미들웨어(Middleware)

  • 요청이 처리되기 전에 실행되는 서버 측 함수
  • 요청을 가로채어 인증, 리다이렉션, 또는 사용자에 맞는 페이지를 제공하는 등의 작업을 수행할 수 있음

 

미들웨어의 역할

  • 사용자 인증 및 권한 검증 : 특정 페이지에 접근하기 전에 사용자가 인증되었는지 확인
  • 페이지 리다이렉션 : 권한이 없는 사용자를 로그인 페이지로 리다이렉션하거나, 다른 적절한 페이지로 안내할 수 있음
  • 요청 정보 변경 : 요청 객체의 내용을 동적으로 수정하고 추가 작업을 수행할 수 있음

 

Next.js 미들웨어의 주요 기능

1. NextResponse 의 주요 API

 

redirect()

// 인증되지 않은 사용자를 로그인 페이지로 리다이렉트
if (!isAuthenticated) {
  return NextResponse.redirect(new URL('/login', request.url))
}
  • 사용자를 완전히 다른 URL로 이동시킴
  • 주로 로그인, 접근 제한 등의 시나리오에서 사용

rewrite()

// 국가에 따라 다른 페이지 내용 제공
if (country === 'US') {
  return NextResponse.rewrite(new URL('/us-version', request.url))
}
  • 실제 URL을 변경하지 않고 다른 페이지의 내용을 렌더링(브라우저의 주소창 유지)
  • 백엔드에서 다른 페이지의 내용을 보여줌
  • 서버 사이드 로직이나 조건부 렌더링에 유용함

 

2. 쿠키 관리

export function middleware(request: NextRequest) {
  // 인증 토큰 확인
  const token = request.cookies.get('auth-token')
  
  if (!token) {
    // 토큰 없으면 로그인 페이지로 리다이렉트
    return NextResponse.redirect(new URL('/login', request.url))
  }

  // 새로운 쿠키 설정
  const response = NextResponse.next()
  response.cookies.set('last-visited', request.nextUrl.pathname, {
    maxAge: 60 * 60 * 24 * 7 // 7일 동안 유효
  })

  return response
}
  • 쿠키 읽기: 사용자 세션, 인증 토큰 등 확인
  • 쿠키 설정: 인증 상태, 사용자 설정 등 저장
  • 보안 및 만료 시간 설정 가능

 

3. 헤더 설정

// 요청 헤더 설정
const requestHeaders = new Headers(request.headers)
requestHeaders.set('x-custom-header', 'value')

// 응답 헤더 설정
const response = NextResponse.next()
response.headers.set('x-custom-response', 'value')
  • 요청/응답 헤더 동적 수정
  • 커스텀 헤더 추가로 추적, 로깅, 보안 강화
  • CORS, 캐시 제어, 보안 헤더 설정 등에 활용

 

4. CORS (Cross-Origin Resource Sharing) 처리

// API 라우트에 대한 CORS 설정
export function middleware(request: NextRequest) {
  const response = NextResponse.next()
  
  // 허용할 도메인 설정
  response.headers.set('Access-Control-Allow-Origin', 'https://yoursite.com')
  response.headers.set('Access-Control-Allow-Methods', 'GET, POST')
  
  return response
}
  • 보안을 유지하면서 다른 도메인의 요청 제어
  • 허용된 도메인, 메서드 명시적 지정

 

Next.js에서 미들웨어 적용해보기

 

Routing: Middleware | Next.js

Learn how to use Middleware to run code before a request is completed.

nextjs.org

 

1. 프로젝트 루트 폴더에 middleware.ts 생성하기

  • 프로젝트에 미들웨어는 하나만 생성이 가능하다.

2. 미들웨어 코드 넣기 (공식문서 예시)

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
// This function can be marked `async` if using `await` inside
export function middleware(request: NextRequest) {
  return NextResponse.redirect(new URL('/home', request.url))
}
 
// See "Matching Paths" below to learn more
export const config = {
  matcher: '/about/:path*',
}

 

middleware 함수

  • 모든 요청이 처리되기 전에 실행되는 함수
  • request.url을 기반으로 '/home'으로 리다이렉트
  • 예: 'http://example.com/about' → 'http://example.com/home'

 

middleware 적용 경로 지정 방법

1. matcher 설정

export const config = {
  matcher: [
    '/about/:path*',
    '/dashboard/:path*'
  ]
}
  • 들웨어가 실행될 경로를 지정
  • '/about'으로 시작하는 모든 경로에 적용
  • ':path*'는 모든 하위 경로를 포함 ('/about' ,  '/about/team',  '/about/contact' 등)

2. 조건문 사용

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
  if (request.nextUrl.pathname.startsWith('/about')) {
    return NextResponse.rewrite(new URL('/about-2', request.url))
  }
 
  if (request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.rewrite(new URL('/dashboard/user', request.url))
  }
}

 

* 오류 처리

export function middleware(request: NextRequest) {
  try {
    // 미들웨어 로직
    const token = request.cookies.get('auth-token')
    
    if (!token) {
      return NextResponse.redirect(new URL('/login', request.url))
    }

    return NextResponse.next()
  } catch (error) {
    // 예상치 못한 오류 처리
    console.error('Middleware error:', error)
    return NextResponse.redirect(new URL('/error', request.url))
  }
}

 

 

미들웨어 적용 시...

  • 모든 요청에 미들웨어가 실행되면 성능에 영향을 줄 수 있으므로, 필요한 경로에만 적용하는 것이 좋다.
  • 모든 요청에 대해 실행되므로 복잡한 로직보다는 간결하고 명확한 조건을 사용하자
  • 보안, 인증, 리다이렉션 등 핵심 기능에 집중