TechFeedTechFeed
개발자 작업환경

dlopen 실패, 노드 버전, 네이티브 모듈 | 노드만 올리면 모듈이 안 열리면?

노드 메이저만 올리면 NODE_MODULE_VERSION이 다른 .node를 process.dlopen이 거절합니다. process.versions.modules로 요구 숫자를 읽고 그 패키지를 npm rebuild합니다. 자바스크립트 경로 없음, exec format error, 권한 모델의 애드온 거절과 줄을 가릅니다. Node.js, sharp, CI, 한국 맥 개발. 2026년 9월 문서.

by

노드만 올렸더니 네이티브 모듈이 안 열리면, 디스크의 바이너리가 다른 빌드 번호로 만들어진 것입니다. 실패 로그에는 파일의 번호와 지금 프로세스가 요구하는 번호가 같이 찍힙니다.


맥에서는 로컬 데이터베이스 모듈이나 이미지 변환 모듈이 컨테이너보다 먼저 죽습니다. 요구 번호의 정본은 실행 중인 프로세스 출력이며, node -p process.versions.modules로 읽습니다. 다른 기기용 파일과 경로 오류는 문장이 다릅니다.


경로에 적힌 패키지만 다시 빌드하거나, 배포와 같은 메이저로 의존 폴더를 지우고 다시 설치하세요. 권한 모델이 네이티브 추가 기능을 막은 경우는 빌드 번호와 다른 코드입니다. 기준은 노드 오류 문서와 프로세스 버전입니다.


메시지 속 두 숫자 중 어느 쪽이 파일인가

compiled against ... NODE_MODULE_VERSION 115 쪽은 이미 디스크에 있는 .node가 빌드될 때 본 숫자입니다. This version of Node.js requires NODE_MODULE_VERSION 127 쪽은 지금 이 프로세스가 요구하는 숫자입니다. 파일을 127로 다시 만들거나, 프로세스를 115에 맞춰야 열립니다. 앱이 배포에서 돌 메이저에 파일을 맞추는 쪽이 맞습니다.


경로에 better_sqlite3.node가 있으면 패키지 이름은 대개 better-sqlite3입니다. sharp는 sharp-something.node로 보일 수 있습니다. 그 패키지만 다시 빌드하면 되고, 저장소 전체를 지우라는 뜻은 아닙니다. 공식 안내 문장도 npm rebuild 또는 npm install로 다시 컴파일하라고 적습니다.


표의 숫자는 자주 만나는 메이저의 예입니다. 패치가 올라가면 표와 달라질 수 있으니, 고치기 전에 항상 실행 중인 프로세스에서 읽으세요. 22.0에서 127로 올라간 뒤의 22 계열은 127을 요구하는 경우가 많고, 24는 137을 요구하는 빌드가 있습니다. 알파인 이미지에 127로 컴파일된 파일이 남아 있으면 24 런타임에서 같은 실패가 납니다. 이미지를 추측하지 말고 컨테이너 안에서 process.versions.modules를 출력하세요.


정본 한 줄 | node -p process.versions.modules 와 node -p process.versions.node 를 나란히 적습니다. 표만 보고 메이저를 내리지 않습니다.


광케이블 패치 패널. 노드 버전과 네이티브 모듈 빌드 숫자가 어긋난 자리
파일의 ABI와 프로세스의 ABI가 다르면 dlopen이 거절한다

못 여는 오류를 세 갈래로 나누기

모듈이 안 열린다는 말만 같으면 고치는 순서가 엇나갑니다. 로그의 코드와 첫 문장으로 갈래를 고르세요.


로그의미다음 동작
NODE_MODULE_VERSION 두 숫자같은 종류 바이너리인데 ABI가 다름그 노드로 rebuild
ERR_DLOPEN_DISABLED권한 모델이 애드온을 막음--allow-addons 또는 플래그 제거
Cannot find module자바스크립트 경로가 없음설치와 경로
exec format error운영체제나 CPU가 다른 파일이미지 플랫폼
node-gyp, 컴파일러 없음소스 빌드 도구가 없음프리빌드 또는 빌드 도구

자바스크립트 모듈을 못 찾는 설치 경로는 Cannot find module 글입니다. 맥에서 만든 이미지를 다른 CPU 서버에서 실행하다 나는 exec format error는 도커 플랫폼 글입니다. 레지스트리에 그 버전이 없어 설치가 끝나지 않는 코드는 ETARGET 글입니다. 받은 파일 해시가 락과 다르면 EINTEGRITY 글이고, 그 단계가 지나 열린 .node의 ABI가 문제일 때만 이 글의 순서입니다.


실행할 노드로 그 패키지만 다시 빌드

미즈나 엔브이엠으로 메이저를 바꾼 직후, 셸의 node가 새 버전인지 먼저 확인합니다. 에디터 통합 터미널만 옛 버전을 보면, 바깥 터미널 설치는 성공하고 편집기에서만 dlopen이 납니다. which node와 버전 두 줄을 설치 전에 남기세요.


요구 숫자를 읽고 경로의 패키지만 다시 빌드
node -p process.versions.node node -p process.versions.modules which node npm rebuild better-sqlite3 npm rebuild sharp

rebuild 뒤에도 같은 두 숫자가 남으면, 그 셸의 노드가 아직 옛 메이저입니다. node_modules를 지우고 다시 설치하는 순서는 버전이 맞은 다음입니다. 옛 노드로 설치하면 파일은 다시 115로 만들어집니다.


프리빌드가 있는 패키지는 그 ABI용 압축을 받아 풀기도 합니다. 받아 둔 파일이 다른 메이저이면 소스 컴파일로 넘어가고, 컴파일러가 없으면 node-gyp 오류가 먼저 납니다. NODE_MODULE_VERSION 문장이 보일 때는 컴파일러를 깔기 전에 숫자를 맞추세요. 컴파일러 설치는 소스 빌드가 필요할 때의 다음 단계입니다.


  • [ ] 실패 프로세스가 요구하는 modules 숫자를 출력했다
  • [ ] 파일 쪽 숫자와 프로세스 쪽 숫자를 문장에서 갈랐다
  • [ ] which node가 배포와 같은 메이저다
  • [ ] 그 패키지만 rebuild한 뒤 같은 명령으로 다시 열었다

사람이 없는 서버실 통로. 로컬 노드와 액션 노드의 ABI를 맞추는 장면
로컬이 초록이어도 액션의 노드 메이저가 다르면 같은 파일이 안 열린다

락만으로 캐시한 모듈과 권한 모델

노트북은 22인데 액션은 20이면, 액션 로그의 요구 숫자는 115이고 저장소에 커밋되지 않은 맥의 파일은 127입니다. 워크플로의 node-version을 앱이 쓸 메이저로 맞춘 뒤, 그 러너에서 설치가 다시 돌게 하세요. 맥에서 만든 node_modules를 리눅스 잡으로 가져오면 ABI가 맞아도 운영체제가 달라 열리지 않습니다.


npm이 받는 압축 캐시와, 이미 컴파일된 node_modules 캐시는 다릅니다. 다운로드 캐시를 비워도 디스크의 .node는 남을 수 있습니다. node_modules를 락 파일 해시만으로 복원하면, 노드 메이저를 올린 커밋 뒤에도 옛 파일이 돌아옵니다. 키에 노드 버전과 아키텍처를 넣으세요. 한국에서 혼자 맥북으로 개발하면 로컬은 arm64이고 호스티드 러너는 x64인 경우가 많습니다. 숫자만 같고 CPU가 달라도 캐시를 공유하면 안 됩니다.


node_modules 캐시 키에 노드 버전을 넣기
- uses: actions/cache@v4 with: path: node_modules key: modules-${{ runner.os }}-${{ runner.arch }}-node-22-${{ hashFiles('package-lock.json') }}

다른 코드인 ERR_DLOPEN_DISABLED는 ABI가 맞는 파일도 프로세스가 열기를 거부한 상태입니다. 노드 20.12와 21.6 이후의 권한 모델에서 네이티브 애드온은 --allow-addons가 있을 때만 열립니다. 플래그 설명은 allow-addons에 있습니다. 권한 모델을 켠 앱이라면 그 플래그를 추가하세요. 켜지 않았다면 플래그를 빼서 일반 로딩으로 돌아가면 됩니다. ABI 불일치를 권한 플래그로 넘기지는 못합니다.


노드 메이저 예modules 예확인할 곳
20115실행 중 프로세스 출력
2212722.0에서 올라간 값. 출력으로 확인
24137127 프리빌드가 남아 있으면 재빌드

패키지 버전이 레지스트리에 없어 설치 자체가 실패한 뒤에 rebuild를 반복하면 같은 파일이 없습니다. 설치 로그의 코드가 ETARGET이면 버전 목록부터 보고, dlopen 문장이 나온 뒤에만 이 표의 숫자를 비교하세요.


권한 모델에서 애드온을 허용할 때만
node --permission --allow-addons server.js
케이블 트레이가 있는 서버실 구석. 캐시된 네이티브 모듈과 런타임 노드를 구분하는 장면
락 해시만으로 복원한 node_modules에는 옛 ABI가 남는다

참고 자료


내부 연계: Cannot find module, exec format error, ETARGET, EINTEGRITY.


115, 127, 137은 널리 쓰인 메이저의 예이고, 정본은 2026년 9월 29일에도 실행 중인 process.versions.modules입니다.


자주 묻는 질문

노드만 올렸는데 어제 되던 sqlite가 죽습니다.

어제 파일의 숫자와 오늘 프로세스의 숫자가 다릅니다. 오늘 셸의 node로 그 패키지를 rebuild하세요. 노드를 도로 내리려면 배포도 그 메이저인지 먼저 맞춥니다.


로컬은 되는데 액션만 dlopen입니다.

잡의 node-version이 노트북과 다릅니다. 요구 숫자를 로그에 찍고, node_modules 캐시 키에 그 버전과 아키텍처가 있는지 보세요. 맥의 arm64 폴더를 리눅스 잡이 복원해도 열리지 않습니다.


표에는 22가 127이라 적혀 있는데 출력이 다릅니다.

표는 예입니다. 그 프로세스가 출력한 modules 값이 파일을 맞출 숫자입니다. 패치와 배포판 프리빌드에 따라 문서의 옛 표와 다를 수 있습니다.


ERR_DLOPEN_DISABLED는 rebuild로 없어지나요?

숫자가 맞는 파일도 권한 모델이 막은 코드입니다. 애드온이 필요하면 --allow-addons를 켜고, 권한 모델을 쓸 일이 아니면 그 플래그를 빼세요. rebuild는 ABI가 다를 때의 순서입니다.


도커에서 같은 문장이 납니다. 플랫폼부터 바꿔야 하나요?

NODE_MODULE_VERSION이 보이면 컨테이너 안 노드로 다시 빌드합니다. exec format error만 보이면 CPU와 운영체제 글의 순서입니다. 두 문장이 동시에 없으면 한 가지만 고치세요.


npm install을 여러 번 해도 그대로입니다.

설치가 옛 node를 보고 있거나, 캐시가 옛 .node를 복원합니다. which node가 목표 메이저인지 확인한 뒤 그 키의 캐시를 지우고 다시 설치하세요. 패키지 버전이 없으면 설치 코드부터 다릅니다.


한 사람이 맥에서 실행 환경을 바꾸면, 어제는 열리던 로컬 데이터베이스가 오늘 첫 실행에서 멈춥니다. 이때 컨테이너를 다시 만들거나 스키마를 지우면 원인과 다른 곳을 고치게 됩니다. 멈춘 창의 문장에 빌드 번호가 두 개 보이면, 파일 쪽 번호에 맞춰 프로세스를 내릴지, 프로세스 쪽 번호에 맞춰 파일을 다시 만들지만 정하면 됩니다. 배포가 도는 번호를 기준으로 파일을 다시 만드는 쪽이 다음 배포와 맞습니다.


에디터 안 터미널과 바깥 터미널이 서로 다른 설치를 보면, 한쪽 설치는 성공하고 다른 쪽에서만 열기가 거절됩니다. 설치 직전에 어느 실행 파일이 잡히는지 적어둡니다. 다시 빌드한 뒤에도 같은 두 번호가 남으면, 아직 옛 실행 파일이 그 창을 잡고 있는 것입니다. 의존 폴더를 지우는 일은 실행 파일이 목표 번호로 바뀐 다음에 합니다.


원격 작업이 노트북과 다른 번호를 요구하면, 작업 정의의 실행 환경을 앱이 쓸 번호로 맞춘 뒤 그 환경에서 설치가 다시 돌게 합니다. 노트북에서 만든 의존 폴더를 리눅스 작업으로 복사하면 번호가 같아도 운영체제가 달라 열리지 않습니다. 받아 둔 묶음 캐시와, 이미 컴파일된 폴더를 담아 두는 캐시도 다릅니다. 묶음 캐시를 비워도 디스크의 바이너리는 남을 수 있습니다. 폴더 캐시의 이름에 실행 환경 번호와 프로세서 종류가 없으면, 메이저를 올린 다음날에도 어제 파일이 돌아옵니다.


권한 모델을 켠 프로세스라면 네이티브 추가 기능을 허용하는 선택이 있어야 같은 파일이 열립니다. 켜지 않았다면 그 선택을 찾기보다 권한 모드 자체를 빼는 편이 맞습니다. 빌드 번호가 다른 파일은 허용을 켜도 열리지 않습니다. 컴파일러가 없다는 문장이 먼저 보이면 소스 빌드 도구의 자리이고, 번호 문장이 보이면 도구를 깔기 전에 번호를 맞춥니다. 예전 번호로 남아 있는 이미지 묶음은 더 높은 메이저에서 같은 거절을 만듭니다. 이미지 이름만 보고 번호를 외우지 말고, 그 컨테이너 안에서 프로세스 출력을 찍으세요. 표의 예와 출력이 다르면 출력을 따릅니다. 번호를 맞춘 뒤 같은 명령으로 모듈을 한 번 더 열어 보고, 그 출력을 작업 로그 옆에 남겨 두세요. 다음날 에디터가 옛 환경을 집으면 그 기록과 바로 비교됩니다. 컨테이너를 먼저 의심하는 순서는 문장에 빌드 번호가 없을 때로 미루면 됩니다. 빌드 번호를 맞춘 날의 프로세스 출력을 남기면, 에디터가 환경을 되돌린 아침에도 어디가 달라졌는지 문장 하나로 가릅니다.


dlopen 실패 중 NODE_MODULE_VERSION이 두 개 찍히면 파일의 ABI와 프로세스의 ABI가 다른 상태입니다. 실행할 노드의 process.versions.modules에 맞춰 그 패키지를 다시 빌드하세요. 경로 없음, 다른 CPU 이미지, 버전 없음, 해시 불일치, 권한 모델의 애드온 거절은 다른 로그입니다. 관련 글: Cannot find module, exec format error, ETARGET.


dlopenNODE_MODULE_VERSION네이티브 모듈Node.jsrebuildsharpCI작업환경

함께 보면 좋은 문제 해결

EXPLORE / 개발자 작업환경

이어서 읽어보기

전체 토픽 둘러보기 →