개발자공부일기
Next.js에서 Node.js와 Edge환경 본문
최근 프로젝트에서 Middleware를 통해 인증 로직을 추가하던 중, 문제가 발생했다.
JWT 토큰을 검증하기 위해 jsonwebtoken 라이브러리를 사용했는데, 실행 시 "Edge 환경에서는 지원되지 않는다"는 에러가 나온 것이다.
분명히 환경을 바꾼 적이 없는데, 왜 Edge 환경에서 실행되는 걸까?
이번 글에서는 Next.js에서 Node.js와 Edge 환경이 각각 어디서 실행되고, 어떤 차이가 있는지를 정리해본다.
Next.js 안의 실행 영역
Next.js 프로젝트는 단순히 서버에서만 돌아가는 게 아니다. 내부적으로 여러 실행 영역이 나뉘어 있고, 각각의 영역이 다른 런타임을 사용한다. 크게 네 가지로 나눌 수 있다.
- 브라우저(Client)
- 사용자의 PC나 스마트폰에서 실행되는 부분
- React 클라이언트 컴포넌트
- Node.js나 Edge와 직접적인 관련은 없음
- 빌드 타임(Build Time)
- next build 시 실행되는 코드
- 항상 Node.js 환경에서 실행됨
- 서버(Server Components & API Routes)
- 서버 컴포넌트 렌더링, API Routes 실행
- 기본적으로 Node.js 런타임에서 실행되지만, Edge 런타임을 명시적으로 선택할 수 있음
- 미들웨어(Middleware)
- 요청(Request)이 들어오자마자 실행되는 전처리 단계
- 기본적으로 Edge 런타임에서 실행됨
Node.js Runtime
Node.js 런타임은 우리가 익숙한 서버 환경이다. Next.js의 API Route나 서버 컴포넌트는 기본적으로 Node.js 런타임에서 실행된다.
특징
- Node.js API 지원
fs, path, crypto 같은 Node.js 모듈 사용 가능 - 라이브러리 호환성 높음
Prisma, bcrypt, jsonwebtoken 등 대부분의 라이브러리 사용 가능 - 파일 시스템 접근 가능
파일 업로드/다운로드 처리 가능 - 긴 실행 시간 허용
복잡한 DB 쿼리나 무거운 연산 처리에 적합
한계
- 서버가 배포된 리전에 따라 지연(latency)이 생김
- Edge에 비해 초기 응답 속도가 다소 느림
Edge Runtime
Edge 런타임은 V8 Isolate 기반으로 동작하며, Cloudflare Workers와 유사한 구조를 갖고 있다.
Next.js에서 export const runtime = "edge";라고 선언하거나, middleware.ts / middleware.js 를 작성하면 Edge 환경에서 실행된다.
특징
- 전 세계 엣지 서버에서 실행
사용자와 가까운 지역에서 실행되어 지연을 최소화 - 빠른 응답
인증, 리다이렉트 같은 가벼운 작업에 적합 - Cold Start 거의 없음
서버리스 환경에서 즉시 응답 가능
제약
- Node.js API 사용 불가
fs, path, net 등 불가능 - 라이브러리 제약
Prisma, bcrypt, jsonwebtoken 등 Node 전용 라이브러리 사용 불가 - Web API만 사용 가능
예: JWT 검증은 crypto.subtle 같은 Web Crypto API 활용 필요 - 파일 시스템 접근 불가
업로드/다운로드는 외부 스토리지(S3 등)에 의존해야 함
Node.js와 Edge 비교
구분 | Node.js Runtime | Edge Runtime |
실행 위치 | 서버 (리전 단위) | 전 세계 엣지 서버 |
속도 | 상대적으로 느림 | 빠름 (저지연) |
라이브러리 호환성 | 거의 모든 Node 패키지 사용 가능 | Web API 기반만 가능 |
파일 접근 | 가능 (fs) | 불가 |
DB 접근 (Prisma 등) | 가능 | 불가 |
JWT 검증 | jsonwebtoken 가능 | Web Crypto API 필요 |
권장 작업 | DB 연동, 파일 업로드, 무거운 연산 | 인증, 리다이렉트, 캐싱 |
왜 Middleware는 Edge 환경일까?
Next.js의 middleware.ts는 Edge Runtime이 기본이다.
이는 미들웨어가 요청 초기에 빠르게 실행되어야 하기 때문이다.
- 로그인 여부 확인
- 특정 페이지 접근 제한
- 리다이렉트 처리
이런 작업은 무거운 DB 쿼리보다는 빠른 응답이 우선이므로 Edge 환경이 적합하다.
따라서 jsonwebtoken처럼 Node.js 전용 라이브러리는 사용할 수 없고, jose 패키지 같은 Edge 호환 라이브러리를 선택해야 한다.
결론
처음에는 환경을 따로 바꾼 적이 없는데 Edge 에러가 난 이유는, Next.js의 Middleware는 기본적으로 Edge Runtime에서 실행되기 때문이다.
Node.js와 Edge는 각각의 장단점이 있으므로, 작업 특성에 맞게 선택해야 한다.
- DB 쿼리, 파일 업로드, 무거운 연산 → Node.js Runtime
- JWT 검증, 인증, 리다이렉트, 글로벌 캐싱 → Edge Runtime
처음엔 그저 빠르게 오류를 지우고 싶어서 진행중인 프로젝트의 미들웨어를 node환경으로 명시할까 했지만 알아보니까 그렇게
해버리면 미들웨어의 장점이 다 사라져서 그냥 단순히 토큰의 유무만 검사하고 토큰이 없다면 로그인이 되어있지 않았음을 의미한다. 로그인이 되어있지 않았다면 로그인 페이지로 리다이렉트 하고 돌아올 경로를 저장했다가 로그인 할때 꺼내쓰도록 했다.
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
const PROTECTED_PATHS = [
"/dashboard",
"/community/boards",
"/profile",
"/settings",
];
export function middleware(req: NextRequest) {
const token = req.cookies.get("token")?.value; // 쿠키에서 로그인 토큰 확인
const { pathname, search } = req.nextUrl;
const isProtected = PROTECTED_PATHS.some((path) => pathname.startsWith(path));
if (isProtected && !token) {
// 로그인 안 했으면 로그인 페이지로
const loginUrl = new URL("/signin", req.url);
console.log("미들웨어를 들어옴");
// 로그인 후 돌아올 경로를 쿼리에 저장
loginUrl.searchParams.set("redirect", pathname + search);
return NextResponse.redirect(loginUrl);
}
return NextResponse.next();
}
export const config = {
matcher: [
"/dashboard/:path*",
"/community/boards/:path*",
"/profile/:path*",
"/settings/:path*",
],
};
로그인을 안한채로 로그인이 필요한 페이지에 들어갔더니 "미들웨어를 들어옴"이란 로그가 정상적으로 출력되었다.
'Language > Javascript' 카테고리의 다른 글
Node.js의 Libuv 라이브러리 (0) | 2025.02.26 |
---|---|
Node.js의 이벤트 루프 (0) | 2025.02.20 |
JWT (0) | 2025.02.11 |
깊은 복사와 얕은 복사 (0) | 2025.02.10 |
Express (0) | 2025.02.07 |