본문 바로가기
학습 정리(공식문서,강의)/Next.js

9. 미들웨어

by 맨날개발 2024. 12. 9.
오늘 정리한 내용은 공식 문서 정리입니다.

미들웨어를 사용하면 요청이 완료되기 전에 코드를 실행할 수 있다. 미들웨어 파일은 프로젝트의 루트 경로에 middleware.js 이름으로 생성하면 된다.

 

🎈 유스케이스

  • 인증 및 권한 부여 : 특정 페이지에 대한 접속 권한을 미들웨어에서 확인 후 접속을 차단하거나 허가할 수 있다.
  • 서버사이드 리다이렉트 : 특정 조건에 따라 서버 레벨에서 유저를 리다이렉트할 수 있다.
  • 봇 탐지 : 봇 트래픽을 감지하고 차단하여 리소스 보호가 가능하다.
  • 로깅 및 분석 : 모든 페이지 접속 전 미들웨어를 통하도록 설정할 수 있어 요청 데이터에 대한 분석이 가능하다.

 

👓 미들웨어에 어울리지 않는 상황

  • 복잡한 데이터를 가져오거나 조작 : 미들웨어에서직접 데이터를 가져와서 조작하는 목적으로 제작된 것이 아니다. 이는 라우트 핸들러 또는 서버사이드에서 구현하는게 좋다.
  • 무거운 계산 작업 : 미들웨어에서 무거운 작업을 진행하게 되면 페이지 로드가 지연될 수 있다. 무거운 계산 작업은 라우트 핸들러 내에서 수행되어야 한다.
  • 광범위한 세션 관리 : 세션 관리를 할 수 있긴 하지만 제한적으로만 관리되어져야 한다.
  • 데이터베이스 직접 접근 : 데이터베이스에 대한 접근은 라우트 핸들러나 서버에서 수행하는 것이 좋다.

 

🛒 경로 매칭

따로 특정 경로를 매칭하지 않으면 모든 경로에 대해 호출된다.

 

아래는 호출 순서이다.

  1. next.config.js의 headers
  2. next.config.js의 redirects
  3. 미들웨어
  4. next.config.js의 beforeFiles
  5. 파일시스템 라우트
  6. next.config.js의 afterFiles
  7. 동적 라우트
  8. next.config.js의 fallback

 

📯 Matcher

미들웨어 파일 내에서 config 변수를 export 하면 된다.

export const config = {
  matcher: ['/about/:path*', '/dashboard/:path*'],
}

 

아래와 같이 정규식을 사용할 수 있다.

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - api (API routes)
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico, sitemap.xml, robots.txt (metadata files)
     */
    '/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)',
  ],
}

 

 

matcher 구성방법

  1. 반드시 ‘/’ 로 시작해야 한다.
  2. 경로에 파라미터를 포함할 수 있다 : /about/:path
  3. 파라미터에 수정자를 가질 수 있다 : /about/:path*
    • *는 0 또는 그 이상
    • ?는 0 또는 한개
    • +는 한 개 이상
    • /about/(.*) 와 같다.

 

🚩 NextResponse

  • redirect 및 rewrite 제공
  • 응답 쿠키, 응답 헤더 설정 가능
redirect는 다른 주소로 이동하는 것, rewrite는 주소는 동일하고 서버 처리만 다른 주소로 요청

 

 

💊 쿠기

Next.js는 NextRequest와 NextResponse에서 쿠키 확장을 통해 쿠키에 액세스하고 조작할 수 있는 편리한 방법을 제공한다.

더보기
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
  // Assume a "Cookie:nextjs=fast" header to be present on the incoming request
  // Getting cookies from the request using the `RequestCookies` API
  let cookie = request.cookies.get('nextjs')
  console.log(cookie) // => { name: 'nextjs', value: 'fast', Path: '/' }
  const allCookies = request.cookies.getAll()
  console.log(allCookies) // => [{ name: 'nextjs', value: 'fast' }]
 
  request.cookies.has('nextjs') // => true
  request.cookies.delete('nextjs')
  request.cookies.has('nextjs') // => false
 
  // Setting cookies on the response using the `ResponseCookies` API
  const response = NextResponse.next()
  response.cookies.set('vercel', 'fast')
  response.cookies.set({
    name: 'vercel',
    value: 'fast',
    path: '/',
  })
  cookie = response.cookies.get('vercel')
  console.log(cookie) // => { name: 'vercel', value: 'fast', Path: '/' }
  // The outgoing response will have a `Set-Cookie:vercel=fast;path=/` header.
 
  return response
}

 

 

⚽ 헤더

NextResponse API를 사용해서 요청 및 응답 헤더를 설정할 수 있다.

더보기
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
  // Clone the request headers and set a new header `x-hello-from-middleware1`
  const requestHeaders = new Headers(request.headers)
  requestHeaders.set('x-hello-from-middleware1', 'hello')
 
  // You can also set request headers in NextResponse.next
  const response = NextResponse.next({
    request: {
      // New request headers
      headers: requestHeaders,
    },
  })
 
  // Set a new response header `x-hello-from-middleware2`
  response.headers.set('x-hello-from-middleware2', 'hello')
  return response
}

 

 

🧵 CORS

미들웨어에서 CORS 헤더를 설정하여 단순 요청 및 사전 프리플라이트 요청을 포함한 CORS을 허용할 수 있다.

더보기
import { NextRequest, NextResponse } from 'next/server'
 
const allowedOrigins = ['https://acme.com', 'https://my-app.org']
 
const corsOptions = {
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Authorization',
}
 
export function middleware(request: NextRequest) {
  // Check the origin from the request
  const origin = request.headers.get('origin') ?? ''
  const isAllowedOrigin = allowedOrigins.includes(origin)
 
  // Handle preflighted requests
  const isPreflight = request.method === 'OPTIONS'
 
  if (isPreflight) {
    const preflightHeaders = {
      ...(isAllowedOrigin && { 'Access-Control-Allow-Origin': origin }),
      ...corsOptions,
    }
    return NextResponse.json({}, { headers: preflightHeaders })
  }
 
  // Handle simple requests
  const response = NextResponse.next()
 
  if (isAllowedOrigin) {
    response.headers.set('Access-Control-Allow-Origin', origin)
  }
 
  Object.entries(corsOptions).forEach(([key, value]) => {
    response.headers.set(key, value)
  })
 
  return response
}
 
export const config = {
  matcher: '/api/:path*',
}

 

코드 출처 https://nextjs.org/docs/app/building-your-application/routing/middleware

'학습 정리(공식문서,강의) > Next.js' 카테고리의 다른 글

11. 서버 액션  (0) 2024.12.24
10. 데이터 페칭과 캐싱  (0) 2024.12.16
8. 리다이렉트와 라우트 핸들러  (0) 2024.12.06
7. Linking and Navigating  (0) 2024.12.03
6. 인터셉팅 라우트  (0) 2024.11.29