목록

electron의 윈도우용 인스톨러 NSIS 설정

얼마 전부터 일렉트론으로 무언가를 하고 있는데 슬슬 인스톨러를 붙여볼 시점이 되어 electron-builder의 설정을 뒤적이며 삽질한 결과 몇가지 알게된 것이 기뻐 몇자 끄적여본다.

NSIS

electron-builder에서 윈도우용 인스톨러로는 nsis, appx, msi, squirrel 등을 선택할 수 있는데 나는 그 중에 nsis를 선택했다. 특별한 이유가 있지는 않고 electron-builder의 기본값이기도 하고 문서에서도 상대적으로 자세하게 설명되어 있기 때문에 선택했다. NSIS는 널소프트 스크립터블 인스톨 시스템의 약자로 추억의 프로그램 윈앰프의 인스톨러를 위해 만들어졌다고 한다.

package.json을 이용한 설정

electron-builder를 사용할 때는 package.json 파일에 build 설정을 추가할 수 있다. 여기에 입력할 수 있는 옵션들은 홈페이지에 자세히 나와있다. 주소마저 기억하기 쉽다. 그것은 바로 https://electron.build/이다. 가령 내 경우 현재 이 정도 설정을 추가했다.

{
  ...
  "productName": "소중한 앱이름",
  "scripts": {
    "build": "electron-builder build"
  },
  "dependencies": {
    ...소중한 의존모듈님들
  },
  "devDependencies": {
    ...소중한 개발의존모듈님들
  },
  "build": {
    "appId": "com.myappid",
    "files": [
      "나의소중한파일들의경로"
    ],
    "win": {
      "target": [{
        "target": "nsis",
        "arch": [
          "x64",
          "ia32"
        ]
      }],
      "icon": "나의소중한아이콘경로.ico"
    },
    "nsis": {
      "oneClick": false,
      "perMachine": true,
      "allowToChangeInstallationDirectory": true,
      "language": 1042,
      "include": "build/installer.nsh",
      "shortcutName": "단축아이콘 이름"
    },
    "directories": {
      "output": "빌드를마친파일이가야할경로"
    }
  }
}

하나씩 살펴보면 다음과 같다.

productName

인스톨러에 표시되는 프로그램 이름을 설정할 때 이 값을 사용한다.

scripts

electron-builder의 cli 명령은 문서에 잘 나와있다. npm script에 electron-builder build를 등록하여 사용하고 있다.

build

electron-builder의 본격적인 설정이다. 이름만 봐도 어느 정도 알 수 있다. 이름만으로 알 수 없는 설정은 다음과 같다.

nsis.oneClick

별도의 경로 설치없이 한방에 설치되게 할 것인가를 설정한다. 기본값은 true라서 이 설정없이 만든 인스톨러를 실행하면 %APPDATA%로 설치된다.

nsis.perMachine

사용자별 설치인지 기기 단위 설치인지 설정하는 옵션이다. oneClick 값에 따라서 기본값이 바뀐다고 문서에 설명되어 있다. oncClickfalse로 두고 인스톨러를 빌드해서 실행했더니 사용자가 선택하도록 하는 화면이 나왔다. perMachinetrue로 해서 선택화면이 나오지 않게 했다.

nsis.allowToChangeInstallationDirectory

사용자가 설치하면서 설치 디렉토리를 변경할 수 있는지 여부이다.

nsis.language

인스톨러의 언어를 지정한다. 설명에는 기본값이 시스템 언어라고 되어 있던데 내가 해보니 영문을 모르겠지만 영어로 나왔다. 여기에는 마이크로소프트의 LCID 값을 넣어줘야 한다고 되어 있다. 그런데 문서에 있는 링크로 가보면 필요한 값이 없어서 좀 더 찾아보니 이런 문서를 발견했다. 한국어는 1042이다.

nsis.shortcutName

바탕화면에 생성되는 단축아이콘의 이름이다.

nsis.include

NSIS가 사용하는 스크립트를 추가할 수 있다. build/installer.nsh 경로에 파일을 생성한다. 위에서 언급한 것처럼 설치 디렉토리의 기본값이 %APPDATA%라서 변경하기 위해서 여기에 스크립트를 사용했다. 문서의 경우에는 C:\MyApp에 설치하도록 설명하고 있는데, C외의 드라이브를 루트로 사용하는 사람들도 간혹 있기 때문에 불안한 방법이라고 생각되어 조금 더 찾아본 결과 아래와 같이 사용하기로 했다.

Var SystemDrive

!macro preInit
    ReadEnvStr $SystemDrive SYSTEMDRIVE
    SetRegView 64
    WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "$SystemDrive\앱이설치될폴더명"
    WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "$SystemDrive\앱이설치될폴더명"
    SetRegView 32
    WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "$SystemDrive\앱이설치될폴더명"
    WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "$SystemDrive\앱이설치될폴더명"
!macroend

변수는 !macro안에 선언할 수 없고 전역에 두어야 하는 모양이다. ReadEnvStr $SystemDrive SYSTEMDRIVE 구문은 변수 $SystemDrive에 환경변수인 SYSTEMDRIVE를 담도록 하고 있다. 그 아래는 64bit와 32bit 운영체제에 따라 별도의 경로를 설정할 수 있다.

가령 위의 경우처럼 $SystemDrive 대신에 $ProgramFiles64 또는 $ProgramFiles도 사용할 수 있는 것 같다. ProgramFiles의 경우에는 별도로 변수를 할당해 주지 않아도 경로 지정이 가능했다.

참고로 잘못된 경로를 넣으면 빌드에 실패한다. 나 같은 경우에는 시스템 드라이브 루트에 설치되게 하기 위해서 삽질을 하다보니 잘못 넣으면 빌드에 실패한다는 사실을 체감하고 말았다.

directories.output

빌드된 인스톨러가 저장되는 경로이다. 별도로 지정하지 않으면 dist 디렉토리에 저장된다.

그리고, node-gyp 또는 node-pre-gyp 빌드오류

일렉트론을 빌드할 때 네이티브 모듈을 재빌드하곤 하는데, 이유는 알 수 없지만 windows-build-tools로 설정해놓은 작업환경에서도 빌드가 실패했다. 빌드실패로 생기는 오류가 엉뚱한 점 중의 하나는 빌드에 실패한 후 바이너리 다운로드를 시도하다가 다운로드에 실패한 것으로 나오는 경우이다.

혹시 node-pre-gyp ERR! Tried to download(403): 같은 오류와 함께 URL이 생기는 오류라면 다운로드가 아니라 로컬환경에서 빌드가 되지 않아 생기는 오류를 의심하는 편이 문제를 빨리 해결하는데 도움이 될 것이다. 내 경우에는 sqlite3로 인해 다음과 같은 오류를 경험했다.

node-pre-gyp ERR! Tried to download(403): https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.0.0/electron-v1.8-win32-x64.tar.gz

결론적으로는 node-gyp 빌드가 가능한 환경을 달성하면 된다. 마이크로소프트의 Node.js 가이드라인에 수동 환경설정 과정이 소개되어 있다. 빌드에 성공한 방법은 다음과 같다.

이렇게 해도 실패한다면 node_modules 디렉토리를 삭제하고 의존 모듈을 다시 설치해보기를 추천한다. 혹시 그래도 안된다면… 멀리서나마 행운을 빌겠다.

2018년 6월 6일

© 2017 Hyunchul Kwak. All rights reserved.