Edge Runtime이 좋다는 건 알겠다. 사용자와 가까운 CDN 엣지 노드에서 코드가 실행되니까 레이턴시가 줄어든다. Cold start도 Node.js 서버리스 함수보다 빠르다. 그래서 API Route 하나를 Edge로 바꿔봤다가, 생각보다 많은 것이 안 되는 걸 알았다.
Edge Runtime ≠ Node.js
Edge Runtime은 Node.js가 아니다. V8 엔진 위에서 돌아가지만, 브라우저의 Web API에 가까운 환경이다. Node.js의 코어 모듈을 쓸 수 없다.
Next.js에서 Edge Runtime을 쓰려면:
// app/api/hello/route.ts
export const runtime = 'edge';
export async function GET() {
return new Response('Hello from Edge');
}이 한 줄(export const runtime = 'edge')이 실행 환경을 완전히 바꾼다.
안 되는 것들
1. Node.js 네이티브 모듈
fs, path, crypto의 일부, child_process, net — 전부 안 된다. 파일 시스템이 없으니 fs.readFile은 당연히 안 되고, path.resolve도 안 된다.
// Edge에서 이건 에러
import fs from 'fs';
import path from 'path';2. 대부분의 npm 패키지
내부적으로 Node.js API를 쓰는 패키지는 다 안 된다. 놀라운 건 꽤 많은 패키지가 어딘가에서 Node.js API를 쓰고 있다는 것이다.
실제로 겪은 사례:
jsonwebtoken— 내부에서 Node.jscrypto사용. 대신jose라이브러리를 써야 한다bcrypt— C++ 네이티브 바인딩. 대신bcryptjs(순수 JS)를 써야 한다sharp— 이미지 처리. Edge에서 동작하지 않음
// Node.js Runtime
import jwt from 'jsonwebtoken';
const token = jwt.sign(payload, secret);
// Edge Runtime
import { SignJWT } from 'jose';
const token = await new SignJWT(payload)
.setProtectedHeader({ alg: 'HS256' })
.sign(new TextEncoder().encode(secret));jose는 Web Crypto API를 기반으로 만들어져서 Edge에서 잘 동작한다.
3. 실행 시간 제한
Vercel Edge Functions는 기본 30초 타임아웃이 있고, Cloudflare Workers 무료 플랜은 10ms CPU 시간 제한이 있다. 무거운 연산이나 느린 외부 API를 호출하면 타임아웃에 걸린다.
4. 전역 상태/메모리
Edge 함수는 요청마다 새로 실행될 수 있고, 같은 인스턴스가 재활용될 수도 있다. 전역 변수에 의존하면 예측 불가능한 동작이 된다. 인메모리 캐시? 안 된다.
돌아가는 것들
1. Web 표준 API
fetch, Request, Response, URL, URLSearchParams, Headers, TextEncoder, TextDecoder, crypto.subtle — Web 표준 API는 다 된다.
export const runtime = 'edge';
export async function GET(request: Request) {
const url = new URL(request.url);
const query = url.searchParams.get('q');
const response = await fetch(`https://api.example.com/search?q=${query}`);
const data = await response.json();
return Response.json(data, {
headers: { 'Cache-Control': 'public, max-age=60' },
});
}2. KV/D1 같은 엣지 스토리지
Cloudflare의 KV, D1, R2 같은 엣지 네이티브 스토리지는 당연히 잘 동작한다. Vercel도 Edge Config, KV를 제공한다.
// Vercel KV
import { kv } from '@vercel/kv';
export const runtime = 'edge';
export async function GET(request: Request) {
const cached = await kv.get('popular-posts');
if (cached) return Response.json(cached);
const posts = await fetchPopularPosts();
await kv.set('popular-posts', posts, { ex: 300 }); // 5분 캐시
return Response.json(posts);
}언제 Edge를 쓰고, 언제 Node.js를 쓰나
모든 걸 Edge로 바꿀 필요는 없다. 오히려 대부분의 API Route는 Node.js Runtime이 맞다.
Edge가 적합한 경우:
- 인증 토큰 검증 (미들웨어)
- 리다이렉트/리라이트 로직
- A/B 테스트 분기
- 지역 기반 콘텐츠 제공
- 단순한 API 프록시
Node.js가 적합한 경우:
- 데이터베이스 직접 연결 (대부분의 DB 드라이버가 Node.js 전용)
- 파일 처리
- 무거운 연산
- Node.js 전용 라이브러리에 의존하는 로직
경험적으로, 미들웨어는 거의 항상 Edge가 맞고, API Route는 대부분 Node.js가 안전하다. Edge Runtime의 제약을 이해하고 적재적소에 쓰는 게 포인트다. 전부 Edge로 가겠다는 건 욕심이다.
