TechFeedTechFeed
Frontend

엣지 런타임, 노드 모듈 미지원, 미들웨어 | 배포 로그만 모듈을 거절하면?

엣지 런타임은 fs, crypto, pg 같은 노드 모듈을 열지 못합니다. 로그에 찍힌 모듈을 미들웨어 임포트에서 빼고, 데이터베이스는 노드 라우트로 옮깁니다. 해시는 웹 크립토로 바꿉니다. 개발 서버가 조용해도 배포 번들은 거절할 수 있습니다. Next.js, 미들웨어, 버셀, 한국 1인 개발. 2026년 10월 문서.

by

엣지 런타임은 노드 내장 모듈을 열지 못합니다. 빌드 로그가 Edge Runtime에서 노드 모듈을 거절하면, 그 줄에 찍힌 모듈을 미들웨어 임포트 사슬에서 빼는 것이 먼저입니다.

로컬 개발 서버는 넘어가는데 버셀 배포만 이 줄에서 멈추는 경우가 있습니다. 카카오 콜백 미들웨어에 토큰 라이브러리나 데이터베이스 드라이버를 넣으면, 한국 프리뷰 빌드가 그 임포트에서 끊깁니다. 화면의 빨간 막만 보고 새로고침하면 같은 임포트가 배포 로그에 그대로 남습니다.


데이터베이스 조회는 노드 런타임 라우트로 옮기고, 서명은 웹 크립토로 바꿉니다. 파일 이름을 바꾸는 일과는 다른 칸입니다. 근거는 넥스트 엣지 런타임의 노드 모듈 오류입니다.


로그에 찍힌 모듈 이름부터

거절된 모듈 이름이 다음 파일의 단서입니다.


넥스트는 로컬에서 어느 파일이 그 모듈을 불러왔는지 콘솔과 브라우저에 보여 줍니다. 배포 로그에도 같은 모듈 이름이 남습니다. fs, net, crypto, pg, jsonwebtoken처럼 보이면 엣지 번들이 노드 전용 코드를 탄 것입니다.


직접 임포트가 아니어도 납니다. 미들웨어가 lib/auth.js를 부르고, 그 파일이 lib/db.js를 부르면 드라이버까지 엣지 그래프에 들어갑니다. 미들웨어 파일만 지우고 헬퍼가 남아 있으면 다음 빌드도 같은 줄입니다. 스택에 찍힌 첫 파일부터 따라 내려가세요.


공식 오류 문서는 프록시 파일과 엣지 라우트가 노드 런타임 기능을 쓸 때 이 일이 생긴다고 적습니다. 2026년 2월 엣지 런타임 문서도 파일 시스템 같은 네이티브 노드는 지원하지 않는다고 적습니다. 화면이 하얗게 되는 하이드레이션 줄과 코드가 다릅니다.


먼저 기억할 것 | 모듈 이름과 그 모듈을 연 파일을 한 쌍으로 적으세요. 런타임 설정을 바꾸기 전에 임포트 사슬을 끊는 쪽이 짧습니다.


유리벽 너머로 서버 랙이 보이는 빈 복도. 엣지에서는 안쪽 노드 기능이 닫힌 장면
유리 밖 입구에서는 안쪽 랙의 파일과 소켓을 직접 열 수 없다

엣지에서 되는 것과 막히는 것

웹 표준 요청과 응답은 되고, 노드 내장은 막힙니다.


하려는 일엣지둘 곳
fetch로 외부 주소 호출가능미들웨어에 둬도 됨
쿠키 이름만 검사가능미들웨어
웹 크립토로 해시가능전역 crypto.subtle
node:crypto, fs, net거절노드 런타임 라우트
pg, 프리즈마 기본 클라이언트거절노드 런타임 라우트

패키지라도 노드 내장을 부르면 같이 거절됩니다. 문서에 ESM이고 네이티브 노드를 안 쓴다고 적힌 패키지만 엣지에 남길 수 있습니다. require를 직접 호출하는 코드도 엣지에서는 허용되지 않습니다. 임포트 문법으로 바꾸라는 뜻이 아니라, 노드 전용 모듈을 그 파일에서 빼라는 뜻에 가깝습니다.


데이터베이스는 노드 라우트로

조회가 필요하면 그 핸들러의 런타임을 노드로 둡니다.


앱 라우터의 라우트 핸들러 기본값은 노드입니다. 누군가 export const runtime = 'edge'를 넣어 두었다면 그 한 줄이 드라이버를 거절합니다. 데이터베이스가 필요하면 그 선언을 nodejs로 바꾸거나 지웁니다. 미들웨어 파일에는 이 선언으로 노드를 켤 수 없는 버전이 많습니다. 미들웨어 안에서 프리즈마를 부르지 마세요.


입구에서는 쿠키가 있는지만 보고, 사용자 행을 읽는 일은 app/api/session/route.js로 넘깁니다. 카카오 콜백도 같습니다. 인가 코드를 쿼리에서 읽는 것까지는 입구에서 가능하고, 토큰 교환 뒤 테이블에 넣는 일은 노드 라우트입니다. 주소가 비어 new URL이 죽는 줄은 ERR_INVALID_URL이라 런타임 거절과 다릅니다.


공유 헬퍼를 둘로 나누세요. 쿠키와 리다이렉트만 있는 파일, 드라이버를 부르는 파일. 미들웨어는 앞 파일만 임포트합니다. 한 파일에 둘 다 있으면 번들러가 드라이버를 따라 들어옵니다.


조회는 노드 라우트에만
// app/api/session/route.js export const runtime = 'nodejs' export async function GET() { // 프리즈마와 pg는 이 파일에서만 부른다 return Response.json({ ok: true }) }
문 옆 콘크리트 턱 위의 짧은 광케이블과 작은 네트워크 상자
입구에 두는 일은 짧은 확인까지다. 창고 안 조회는 노드 쪽으로 넘긴다

노드 크립토 대신 웹 크립토

해시만 필요하면 전역 웹 크립토를 씁니다.


오류 문서가 드는 예가 이 교체입니다. node:crypto의 createHash 대신 crypto.subtle.digest를 부릅니다. 엣지에도 웹 크립토 전역이 있습니다. 노드 모듈을 임포트하는 순간 빌드가 거절하므로, 임포트 줄을 지우는 것이 먼저입니다.


서명 라이브러리가 노드 크립토를 안쪽으로 부르면 내 코드에 createHash가 없어도 같은 줄이 납니다. 그 라이브러리를 미들웨어에서 제거하세요. 검증이 복잡하면 노드 라우트로 요청을 넘기고, 미들웨어는 쿠키 유무만 봅니다.


브라우저 교차 출처 헤더 문제는 프리플라이트입니다. 엣지 빌드가 모듈을 거절하는 줄과 응답 헤더가 비어 브라우저가 막는 줄은 로그 위치가 다릅니다. 하나는 배포 빌드, 하나는 브라우저 콘솔입니다.


웹 크립토로 해시
const bytes = new TextEncoder().encode(value) const digest = await crypto.subtle.digest('SHA-256', bytes) const hex = [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('')

파일 이름만 바꾸지 않기 | 로그가 Edge Runtime을 가리키면 그 그래프에서 노드 모듈을 빼야 합니다. 파일 이름을 proxy로 바꾸는 절차는 이 글의 범위 밖입니다.


모듈 없음과는 다른 줄

패키지가 없는 줄과, 런타임이 그 패키지를 안 받는 줄은 설치로 안 갈립니다.


Cannot find module은 이름이나 작업 폴더 문제입니다. npm ci와 경로를 봅니다. 이 글의 오류는 설치가 끝난 뒤, 엣지 번들이 노드 전용 모듈을 포함하지 않겠다고 거절한 것입니다. 같은 패키지를 다시 깔아도 그래프가 같으면 다시 죽습니다.


패키지 exports가 서브패스를 막는 코드는 ERR_PACKAGE_PATH_NOT_EXPORTED입니다. 깊은 경로를 공개 입구로 바꿔도, 그 입구가 노드 내장을 부르면 엣지에서는 이 글의 오류로 바뀝니다. 코드 문자열을 먼저 읽으세요.


로그의미다음
Edge Runtime, 노드 모듈런타임이 내장을 거절이 글
Cannot find module패키지를 못 찾음설치와 작업 폴더
exports 서브패스공개 입구가 아님서브패스 글

참고 자료


내부 연계: 프리플라이트와 응답 헤더, 빈 주소로 new URL이 죽을 때, 모듈을 찾을 수 없음, exports가 서브패스를 막을 때.


인용한 동작은 2026년 10월 넥스트 공개 문서 기준입니다.


자주 묻는 질문

로컬 next dev는 되는데 배포만 거절합니다.

개발 서버가 그래프를 느슨히 보고, 배포 빌드가 엣지 번들을 만들 때 거절하는 경우가 있습니다. 로그의 모듈 이름을 미들웨어가 닿지 않는 파일로 옮기세요. 새로고침은 그 탭의 화면만 바꿉니다.


미들웨어에 runtime을 nodejs로 적으면 되나요?

미들웨어는 그 선언으로 노드 런타임이 되지 않는 버전이 많습니다. 데이터베이스는 라우트 핸들러로 옮기고, 그 파일에 nodejs를 두세요. 미들웨어에는 쿠키와 fetch만 남깁니다.


내 코드는 fs를 안 쓰는데도 fs에서 죽습니다.

불러온 패키지 안쪽이 fs를 부릅니다. 스택의 자기 파일에서 그 패키지 임포트를 지우세요. 미들웨어가 그 패키지에 닿지 않으면 빌드 그래프에서 빠집니다.


해시가 필요한데 노드 크립토를 꼭 써야 하나요?

SHA-256 정도면 crypto.subtle.digest로 됩니다. 임포트 없이 전역 웹 크립토를 쓰세요. 인증서나 파일 키가 필요하면 그 작업 전체를 노드 라우트로 옮기세요.


프리즈마를 미들웨어에서 한 번만 호출하면 괜찮나요?

호출 횟수가 아니라 번들에 드라이버가 들어가는지가 문제입니다. 한 번이어도 엣지는 pg 소켓을 열지 못합니다. 세션 조회는 노드 라우트로 빼세요.


CORS 에러와 같이 보이면 어느 쪽인가요?

배포 빌드가 Edge Runtime 문구로 멈추면 이 글입니다. 빌드는 초록인데 브라우저만 응답 헤더를 막으면 프리플라이트 글입니다. 로그가 생긴 위치를 먼저 가르세요.


이 오류는 엣지 번들이 노드 내장 모듈을 포함하지 않겠다는 뜻입니다. 로그의 모듈을 미들웨어 그래프에서 빼고, 조회는 노드 라우트에 두세요. 해시는 웹 크립토로 바꿀 수 있습니다. 관련 글: 프리플라이트, 모듈 없음.


엣지 런타임미들웨어Node.js웹 크립토프리즈마버셀넥스트프론트엔드

함께 보면 좋은 문제 해결

EXPLORE / Frontend

이어서 읽어보기

전체 토픽 둘러보기 →