Next.js 미들웨어(Middleware)는 특정 경로에 대한 요청이 서버에서 처리되기 전에 중간에 어떤 작업을 수행하고 싶을 때 사용한다. 이를 통해 인증, 리디렉션, 요청 데이터 처리 등 다양한 작업을 수행할 수 있다.
인증 및 권한 부여: 사용자 신원을 확인하고 특정 페이지나 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();
}
NextRequest
: 들어온 객체 요청을 읽음NextResponse
: 응답 반환request.cookies.get
: 쿠키에서 인증 토큰 확인NextResponse.redirect
: 인증되지 않은 사용자를 /login
으로 리디렉션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).*)",
],
};
request.cookies.get
:membershipLevel
쿠키 값을 가져와 사용자의 등급 확인'guest'
사용request.nextUrl.pathname
: /post
로 시작하는 경로에만 특정 로직 적용 NextResponse.rewrite
:/post
에 접근했을 때, membershipLevel
이 'admin'
인 경우 /admin/posts
로 경로 재작성/admin/posts
로 요청 전달NextResponse.next
:admin
이 아닌 경우, 요청은 다음 단계로 넘어감미들웨어가 어떤 요청에 대해 실행될지를 필터링 하는 기능 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
)