| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 백준
- sstream
- 문법
- data_structure
- Heap
- singly Linked List
- 5397
- list
- Pair
- 자료구조
- class_template
- connected_component
- 13305
- function_template
- template
- 구현
- sort
- deletion
- c++
- red-black tree
- 예제
- Algorithm
- Biconnected_Component
- '0'
- 총정리
- qsort
- 알고리즘
- STL
- Articulation_Point
- Critical_Path_Analysis
- Today
- Total
- Today
- Total
- 방명록
어제의 나보다 성장한 오늘의 나
[Next.js] Middleware를 활용한 인증 처리 통합 본문
기존 인증 로직 관리 문제
프로젝트 내 인증 및 권한 검사 로직이 각 페이지와 API 핸들러에 흩어져 있었습니다.
- 각 페이지마다 인증/인가 처리를 하고 있으며,
- API 보호를 위해 각 handler 내부에 반복적으로 인증 검사를 호출하고 있었습니다.
이런 방식은 새 기능을 추가할 때마다 중복 로직이 추가되고, 또 로직이 흩어져 있어서 관리도 어렵습니다.
그래서 요청이 들어오는 가장 앞단, 즉 middleware에서 인증을 일괄 처리해보기로 했습니다.
이렇게 하면 인증에 대한 처리를 각 페이지나 API에서 따로 신경 쓰지 않아도 되는 장점이 있습니다.
Middleware으로 기존 로직 마이그레이션
우선 기존의 접근 제어 로직을 middleware.ts에 그대로 옮겨 적용해봤습니다.
middleware.ts
export async function middleware(request: NextRequest) {
const token = request.cookies.get("token")?.value;
if (!token) {
return NextResponse.redirect(new URL("/logout", request.url));
}
try {
const payload = await verifyToken(token);
const hasPermission = checkPermission({
path: request.nextUrl.pathname,
role: payload.role,
permissions: payload.permissions,
});
if (!hasPermission) {
return NextResponse.redirect(new URL("/forbidden", request.url));
}
return NextResponse.next();
} catch {
return NextResponse.redirect(new URL("/logout", request.url));
}
}
그러나 실행과 동시에 다음과 같은 에러가 발생했습니다.
Error: The edge runtime does not support Node.js 'crypto' module.
이 때부터 뭔가 쉽지 않겠다는 생각이 들었습니다...
열심히 알아보니 middleware에는 독특한 특징이 있었습니다.
Middleware는 next 서버 (node runtime) 와는 다르게 edge runtime 위에서 동작합니다.
https://nextjs.org/docs/app/api-reference/edge
Edge Runtime이란?
- Node.js가 아닌 Web API 기반의 경량 실행 환경
- 빠르고 가볍지만, Node 내장 모듈을 사용할 수 없고 사용 가능 API가 제한 적임
즉, 기존에 사용하던 MongoDB 클라이언트, node-cache, createHash 같은 기능을 지원하지 않습니다.
*edge에서 지원하는 API들
https://nextjs.org/docs/app/api-reference/edge#reference
그럼 기존 로직을 그대로 사용하는 것은 어려워 보이는데 어떻게 해결할 수 있을까??
시도 1: Middleware를 Node.js 런타임으로 전환
Next.js의 canary 버전에서는 middleware의 runtime을 'nodejs'로 설정할 수 있습니다.
middleware.ts
export const config = {
runtime: "nodejs", // Canary 버전에서만 지원
};
이렇게 하면 Node 전용 API를 사용할 수 있어 기존 로직으로 구현할 수 있습니다.
그러나 canary는 실험적이기 때문에 안정성이 떨어지고, production에서는 사용이 권장되지 않아 보류하였습니다.
시도 2: Edge-safe 방식으로 구현
이슈 1) JWT 라이브러리 사용 제약
많은 JWT 라이브러리(예: jsonwebtoken)는 Node.js 전용 API에 의존하고 있어 Edge Runtime에서 사용할 수 없습니다.
-> 그러나 다행히 현재 사용중인 jose는 Edge 환경에서도 지원됩니다.
이슈 2) Node.js 내장 모듈 사용 불가 (node:crypto, node:cache 등)
Edge Runtime에서는 node:crypto 등 Node 고유 모듈을 사용할 수 없습니다.
-> Web Crypto API를 사용하여 해시, 암호화 등의 기능을 대체할 수 있습니다.
const hashBuffer = await crypto.subtle.digest(
"SHA-256",
new TextEncoder().encode("hello")
);
이슈 3) MongoDB 클라이언트 사용 불가
기존에는 JWT 검증을 위해 JWK 키를 MongoDB에서 가져오는 구조였지만, Edge 환경에서는 DB 클라이언트가 동작하지 않아 직접적인 DB 접근이 불가능합니다.
-> JWK 키를 /api/jwks 같은 endpoint에 공개하고, middleware에서 fetch()를 통해 가져오는 방식으로 개선할 수 있습니다. 이는 엔터프라이즈 환경에서 JWK 키가 외부에 노출된다는 우려가 있긴 합니다.
현 상황에서 Edge-safe 방식의 단점
위와 같이 구현하면 Edge-safe 방식으로도 가능은 하지만,
- 여러 인증 로직을 직접 Edge 환경에 맞게 재구현해야 하고,
- middleware의 책임이 지나치게 커진다는 단점이 있습니다.
“어차피 fetch를 활용 할 거면, 로직 자체를 Route handler에 위임하는 게 더 낫지 않을까?”
시도 3: 토큰 검증 로직을 Route handler로 위임 ✅
- middleware.ts: 토큰 유무 판단 및 리다이렉트 처리만 수행
- Route Handler (/api/auth): JWT 서명 검증, 권한 검사 등 핵심 로직 처리
middleware.ts
export async function middleware(req: NextRequest) {
const token = req.cookies.get("token")?.value;
const pathname = req.nextUrl.pathname;
if (!token) {
return NextResponse.redirect(new URL("/logout", req.url));
}
const authResult = await fetch(`{NEXT_BASE_URL}/api/auth`, {
method: "POST",
headers: {
Cookie: token,
},
body: JSON.stringify({
pathname,
}),
});
if (authResult.status === 401) {
return NextResponse.redirect(new URL("/logout", req.url));
} else if (authResult.status === 403) {
return NextResponse.redirect(new URL("/forbidden", req.url));
}
return response;
}
장점
- middleware는 요청 흐름만 제어 → 코드가 간단하고 가독성 높음
- 인증 로직은 Node.js 환경에서 자유롭게 구현 가능
- JWK를 기존처럼 외부에 노출할 필요 없음
최종 결정 및 요약
현재 상황에서는 토큰 검증 로직을 Route handler로 위임하는 방식이 가장 현실적이고 적합하다고 판단했습니다.
핵심 인증/권한 로직은 그대로 유지하면서도, Edge 환경의 제약을 피할 수 있기 때문입니다.
Next.js App Router의 middleware는 인증 흐름을 통일하는 데 효과적인 도구입니다.
하지만 Edge Runtime이라는 제약 조건 때문에 Node.js 고유 기능들을 사용할 수 없으므로, 모든 인증 로직을 middleware 내부에서 처리하기에는 한계가 있습니다.
따라서 우리는 다음과 같은 구조를 선택했습니다:
• middleware: 요청 흐름을 제어 (토큰 유무 판단, 리다이렉트 등)
• Route handler (/api/auth): Node.js 환경에서 실제 토큰 검증 및 권한 판단 수행
향후에 Next.js에서 정식 릴리즈에서 middleware의 Node.js runtime 지원이 될 수 있다고 하니 지켜 봐야겠습니다 :)
'Next.js' 카테고리의 다른 글
| [Next.js] 데이터 요청 구조를 Server Action으로 통합해보기 (0) | 2025.07.21 |
|---|---|
| [Next.js] pre-fetch를 통한 초기 렌더링 최적화 (0) | 2025.07.05 |
| [Next.js] timezone 불일치로 인한 Hydration Failed 이슈 (0) | 2025.07.05 |
| [Next.js] 서버 컴포넌트에서의 에러 처리와 ErrorBoundary (2) | 2025.07.03 |
| [NextJS] Next.js 프로젝트에서 CSS 프레임 워크 결정 하기 (0) | 2024.03.25 |