[NextJS] 미들웨어(Middleware)

우지끈·2024년 12월 23일
0
post-thumbnail

Next.js 미들웨어(Middleware)는 특정 경로에 대한 요청이 서버에서 처리되기 전에 중간에 어떤 작업을 수행하고 싶을 때 사용한다. 이를 통해 인증, 리디렉션, 요청 데이터 처리 등 다양한 작업을 수행할 수 있다.


Use Cases

  • 인증 및 권한 부여: 사용자 신원을 확인하고 특정 페이지나 API 라우트에 접근하기 전에 세션 쿠키 확인

  • 서버 측 리디렉션: 특정 조건(예: 로케일, 사용자 역할)에 따라 서버 수준에서 사용자를 리디렉션

  • 경로 재작성: 요청 속성에 따라 경로를 동적으로 재작성하여 A/B 테스트, 기능 출시 또는 레거시 경로 지원

  • 봇 감지: 리소스를 보호하기 위해 봇 트래픽을 감지하고 차단

  • 로깅 및 분석: 페이지나 API가 처리되기 전에 요청 데이터를 캡처하고 분석

  • 기능 플래깅: 기능을 동적으로 활성화 또는 비활성화하여 원활한 기능 출시 또는 테스트 진행


미들웨어 설정

Next.js에서 미들웨어는 middleware.ts 또는 middleware.js 파일을 사용해 설정한다.

본격적으로 예시 코드를 살펴 보기 전에 알아두면 좋은 NextResponse의 4가지 메소드에 대해 먼저 짚고 넘어가겠다.

// 요청을 계속 처리. 단순히 사용자 요청을 그대로 진행
return NextResponse.next();

// about 경로로 redirect
return NextResponse.redirect(new URL('/about', request.url)); 

// faq 경로로 rewrite (url path는 그대로(!/faq)인데 실행되는 페이지 컴포넌트는 /faq)
return NextResponse.rewrite(new URL("/faq", request.url));

// 요청으로 가기전에 json 데이터 응답
return NextResponse.json({ data: { hello: "world" } });

예시 코드1
: 권한에 따른 redirect 로직

import { NextRequest, NextResponse } from 'next/server';

export function middleware(request: NextRequest) {
  const token = request.cookies.get('auth-token');

  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  return NextResponse.next();
}
  1. NextRequest: 들어온 객체 요청을 읽음
  2. NextResponse: 응답 반환
  3. request.cookies.get: 쿠키에서 인증 토큰 확인
  4. NextResponse.redirect: 인증되지 않은 사용자를 /login으로 리디렉션
  5. NextResponse.next: 다음 라우트로 요청 전달

예시 코드2
: 권한에 따른 rewrites 로직

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

// 미들웨어 함수
export function middleware(request: NextRequest) {
  // 쿠키에서 membershipLevel 값을 읽음 (기본값: 'guest')
  const membershipLevel = request.cookies.get('membershipLevel')?.value || 'guest';

  // '/posts' 경로에 접근할 때
  if (request.nextUrl.pathname.startsWith("/posts")) {
    if (membershipLevel === "admin") {
      // 회원 등급이 'admin'인 경우 '/admin/posts'로 경로 재작성
      return NextResponse.rewrite(new URL("/admin/posts", request.url));
    }
    // 그 외의 경우 정상적으로 접근
    return NextResponse.next();
  }
}

// 미들웨어 적용 범위 설정 (matcher 사용)
export const config = {
  matcher: [
    "/((?!_next/static|_next/image|favicon.ico).*)",
  ],
};
  1. request.cookies.get:
    • membershipLevel 쿠키 값을 가져와 사용자의 등급 확인
    • 만약 쿠키가 존재하지 않는 경우, 기본값으로 'guest' 사용
  2. request.nextUrl.pathname:
    • 사용자가 요청한 경로 확인
    • /post로 시작하는 경로에만 특정 로직 적용
  3. NextResponse.rewrite:
    • 사용자가 /post에 접근했을 때, membershipLevel'admin'인 경우 /admin/posts로 경로 재작성
    • 이 경우 브라우저의 URL은 그대로 유지되지만, 백엔드에서 실제로는 /admin/posts로 요청 전달
  4. NextResponse.next:
    • 사용자가 admin이 아닌 경우, 요청은 다음 단계로 넘어감

Matcher란?

미들웨어가 어떤 요청에 대해 실행될지를 필터링 하는 기능 \to config 객체에 matcher 키를 사용하여 정의할 수 있음

export const config = {
  matcher: [
    "/((?!_next/static|_next/image|favicon.ico).*)",
  ],
};

위 예시는 정규식을 통해 특정 경로를 제외한 모든 요청에 미들웨어를 적용하는 코드이다.

그리고,

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

다음처럼 특정 경로(/dashboard, /admin + 그 하위 경로에만 미들웨어 실행) 적용할 수도 있다.


주의사항

middleware 파일은 루트 또는 src/에 위치해야 한다!!!

Next.js는 루트 디렉토리 또는 src/ 디렉토리 기준으로 미들웨어를 감지하기에 app/ 이나 pages/ 내에서는 사용할 수 없다.

또한 미들웨어는 모든 요청을 가로채기 때문에 특정 페이지 디렉토리에 국한되지 않고 루트 또는 src/ 디렉토리에 위치해야 한다~! (권장 위치는 src/middleware.ts)

0개의 댓글

관련 채용 정보