Skip to main content

네이티브 Node 모듈

Electron은 네이티브 Node.js 모듈을 지원한다. 하지만 Electron은 특정 Node.js 바이너리와 다른 애플리케이션 바이너리 인터페이스(ABI)를 사용한다. 예를 들어 OpenSSL 대신 Chromium의 BoringSSL을 사용하는 등의 차이점이 있다. 따라서 사용하려는 네이티브 모듈을 Electron용으로 다시 컴파일해야 한다. 그렇지 않으면 애플리케이션을 실행할 때 다음과 같은 오류가 발생한다:

Error: The module '/path/to/native/module.node'
was compiled against a different Node.js version using
NODE_MODULE_VERSION $XYZ. This version of Node.js requires
NODE_MODULE_VERSION $ABC. Please try re-compiling or re-installing
the module (for instance, using `npm rebuild` or `npm install`).

네이티브 모듈 설치 방법

네이티브 모듈을 설치하는 데는 여러 가지 방법이 있다:

Electron용 모듈 설치 및 재빌드

Electron 프로젝트에서도 다른 Node 프로젝트와 마찬가지로 모듈을 설치할 수 있다. 이후 @electron/rebuild 패키지를 사용해 Electron용 모듈을 재빌드한다. 이 모듈은 Electron 버전을 자동으로 파악하고, 헤더를 다운로드하거나 네이티브 모듈을 재빌드하는 수동 작업을 처리한다. Electron Forge를 사용한다면, 개발 모드와 배포 가능한 파일을 생성할 때 이 도구가 자동으로 실행된다.

예를 들어, 독립형 @electron/rebuild 도구를 설치하고 커맨드라인을 통해 모듈을 재빌드하려면 다음 명령어를 실행한다:

npm install --save-dev @electron/rebuild

# "npm install"을 실행할 때마다 이 명령어를 실행한다:
./node_modules/.bin/electron-rebuild

# Windows에서 문제가 발생한다면, 이 명령어를 시도한다:
.\node_modules\.bin\electron-rebuild.cmd

Electron Packager와 같은 다른 도구와의 통합 및 사용법에 대한 자세한 내용은 프로젝트의 README를 참고한다.

npm 사용하기

몇 가지 환경 변수를 설정하면 npm을 사용해 모듈을 직접 설치할 수 있다.

예를 들어, Electron의 모든 의존성을 설치하려면 다음과 같이 설정한다:

# Electron 버전 설정
export npm_config_target=1.2.3
# 시스템 아키텍처 설정
export npm_config_arch=x64
export npm_config_target_arch=x64
# Electron 헤더 다운로드 URL 설정
export npm_config_disturl=https://electronjs.org/headers
# node-pre-gyp에 Electron 빌드임을 알림
export npm_config_runtime=electron
# node-pre-gyp에 소스 코드에서 모듈 빌드하도록 설정
export npm_config_build_from_source=true
# 모든 의존성 설치 및 캐시를 ~/.electron-gyp에 저장
HOME=~/.electron-gyp npm install

Electron을 위한 수동 빌드

네이티브 모듈을 개발 중이고 이를 Electron 환경에서 테스트하려면, 해당 모듈을 Electron용으로 수동으로 다시 빌드해야 할 수 있다. 이때 node-gyp를 직접 사용해 Electron용으로 빌드할 수 있다.

cd /path-to-module/
HOME=~/.electron-gyp node-gyp rebuild --target=1.2.3 --arch=x64 --dist-url=https://electronjs.org/headers
  • HOME=~/.electron-gyp는 개발 헤더를 찾을 위치를 변경한다.
  • --target=1.2.3은 Electron의 버전을 지정한다.
  • --dist-url=...는 헤더를 다운로드할 위치를 지정한다.
  • --arch=x64는 모듈이 64비트 시스템용으로 빌드됨을 나타낸다.

커스텀 Electron 빌드를 위한 수동 빌드

공개 릴리스와 일치하지 않는 커스텀 Electron 빌드에 대해 네이티브 Node 모듈을 컴파일하려면, npm이 커스텀 빌드에 포함된 Node 버전을 사용하도록 지시해야 한다.

npm rebuild --nodedir=/path/to/src/out/Default/gen/node_headers

문제 해결

네이티브 모듈을 설치했는데 작동하지 않는다면, 다음 사항들을 확인해야 한다:

  • 의심스러울 때는 먼저 @electron/rebuild를 실행한다.
  • 네이티브 모듈이 Electron 앱의 대상 플랫폼과 아키텍처와 호환되는지 확인한다.
  • 모듈의 binding.gyp에서 win_delay_load_hookfalse로 설정되지 않았는지 확인한다.
  • Electron을 업그레이드한 후에는 일반적으로 모듈을 다시 빌드해야 한다.

win_delay_load_hook에 대한 설명

Windows 환경에서 node-gyp는 기본적으로 네이티브 모듈을 node.dll에 링크한다. 하지만 Electron 4.x 이상 버전에서는 네이티브 모듈이 필요로 하는 심볼들이 electron.exe에 의해 내보내지며, node.dll은 존재하지 않는다. Windows에서 네이티브 모듈을 로드하기 위해 node-gypdelay-load hook을 설치한다. 이 훅은 네이티브 모듈이 로드될 때 트리거되며, node.dll 참조를 라이브러리 검색 경로에서 찾는 대신 로딩 실행 파일로 리다이렉트한다. 따라서 Electron 4.x 이상 버전에서는 네이티브 모듈을 로드하기 위해 'win_delay_load_hook': 'true'가 반드시 필요하다.

Module did not self-register 또는 The specified procedure could not be found와 같은 오류가 발생한다면, 사용하려는 모듈이 delay-load hook을 제대로 포함하지 않았을 가능성이 있다. 모듈이 node-gyp로 빌드된 경우, binding.gyp 파일에서 win_delay_load_hook 변수가 true로 설정되어 있고, 어디에서도 재정의되지 않았는지 확인해야 한다. 다른 시스템으로 모듈을 빌드하는 경우, 메인 .node 파일에 delay-load hook이 설치되어 있는지 확인해야 한다. link.exe 호출은 다음과 같이 구성되어야 한다:

 link.exe /OUT:"foo.node" "...\node.lib" delayimp.lib /DELAYLOAD:node.exe /DLL
"my_addon.obj" "win_delay_load_hook.obj"

특히 다음 사항을 주의해야 한다:

  • Electronnode.lib에 링크해야 하며, Node의 node.lib에 링크하면 안 된다. 잘못된 node.lib에 링크하면 Electron에서 모듈을 로드할 때 오류가 발생한다.
  • /DELAYLOAD:node.exe 플래그를 포함해야 한다. node.exe 링크가 지연되지 않으면 delay-load hook이 트리거될 기회를 얻지 못하고, Node 심볼이 제대로 해결되지 않는다.
  • win_delay_load_hook.obj가 최종 DLL에 직접 링크되어야 한다. 훅이 종속 DLL에 설정되어 있으면 적절한 시점에 트리거되지 않는다.

자체적으로 delay-load hook을 구현하려면 node-gyp의 예제를 참고하면 된다.

prebuild에 의존하는 모듈

prebuild는 여러 버전의 Node와 Electron을 위한 사전 빌드된 바이너리와 함께 네이티브 Node 모듈을 배포할 수 있는 방법을 제공한다.

prebuild를 사용하는 모듈이 Electron에서 사용할 수 있는 바이너리를 제공한다면, 사전 빌드된 바이너리를 최대한 활용하기 위해 --build-from-source 옵션과 npm_config_build_from_source 환경 변수를 생략해야 한다.

node-pre-gyp에 의존하는 모듈

node-pre-gyp 도구는 사전 빌드된 바이너리와 함께 네이티브 Node 모듈을 배포하는 방법을 제공한다. 많은 인기 모듈이 이 도구를 사용하고 있다.

때로는 이러한 모듈이 Electron에서 잘 작동하지만, Electron 전용 바이너리가 없는 경우 소스에서 빌드해야 한다. 이런 이유로, 이러한 모듈에 대해 @electron/rebuild를 사용하는 것이 권장된다.

npm 방식으로 모듈을 설치하는 경우, npm--build-from-source를 전달하거나 npm_config_build_from_source 환경 변수를 설정해야 한다.