Electron 앱 build부터 자동업데이트까지

YiJaeE·2021년 9월 12일
3

Electron

목록 보기
3/3
post-thumbnail
post-custom-banner

Electron은 크로스 플랫폼(macOS, Linux, Windows), 그리고 x64, ia32 등의 아키텍쳐를 지원한다. 당연히 Electron에서 지원하는 build 시스템도 있다. 별도의 라이브러리 없이 build 하고자 하는 경우 여기를 참고한다. gypninja를 활용해서 build를 지원하는데 이보다는 라이브러리를 사용하는 방법이 훨씬 일반적이다.

라이브러리는 주로 electron-package나 electron-builder를 사용한다. 나는 electron-builder를 이용해 Electron으로 생성한 어플리케이션을 build하는 방법을 소개하려고 한다.

electron-builder

electron-builder 소개 페이지(electron builder)에서는 electron-builder에 대해서 다음과 같이 설명하고 있다.

자동 업데이트 지원을 통해 macOS, Windows 및 Linux 배포용 electron 앱을 패키징하고 빌드하는 솔루션

라이브러리를 쓰지 않고도 build가 가능한데 굳이 electron-builder 라는 라이브러리를 사용하는 이유는 상술한 설명에서의 핵심 기능인 자동 업데이트 때문이다. electron-builder는 자동 업데이트를 github release와 연동한다. github를 사용하지 않는 방법도 있지만 이 글에서는

  1. build
  2. electron-autoUpdater
  3. 프로젝트 아이콘 변경

이렇게 세 가지의 흐름으로 작성하려고 한다.

build

먼저 electron-builder를 설치한다.

npm install --save-dev electron-builder

설치가 완료되었다면 package.json에 build 항목을 만들어 작성하는데 프로젝트의 성격, 자동 업데이트 여부 등에 따라 작성 내용이 달라진다. 이 글에서는 github를 통한 자동 업데이트와 아이콘 경로가 변경되어 있다는 점을 참고하자.

// package.json

"repository": {
    "type": "git",
    "url": "https://github.com/릴리즈할 저장소.git"
  },
"build": {
    "appId": "com.project",
    "copyright": "Copyright 2021 Project, Inc",
    "publish": {
      "provider": "github"
    },
    "mac": {
      "category": "public.app-category.productivity"
    },
    "win": {
      "certificateFile": "private/인증서.pfx",
      "certificatePassword": "",
      "verifyUpdateCodeSignature": true,
      "publisherName": "project.owner",
      "target": [
        {
          "target": "nsis",
          "arch": [
            "x64",
            "ia32"
          ]
        }
      ]
    },
    "linux": {
      "category": "Utility"
    },
    "directories": {
      "output": "build",
      "buildResources": "assets"
    }
  }

항목에 대한 설명은 다음과 같다.

  • repository: build 파일을 릴리즈할 깃허브 저장소
  • appId: 어플리케이션의 id com.blahblah 형태로 쓴다.
  • publish: github를 통한 업데이트를 할 때 작성하는 부분이다.
  • win
    • certificateFile: 기관으로부터 발급받은 (코드 사인된)인증서의 파일 위치를 작성한다.
    • certificatePassword: 인증서의 비밀번호를 작성한다.
    • verifyUpdateCodeSignature: 사용가능한 업데이트의 코드 사인을 확인할지 여부이다.
    • publisherName: 인증서를 발급받은 사람의 이름이다.
    • target
      • target: 생성되는 build 파일 형태
      • arch: 32비트를 지원하려면 [x64, ia32] 를 작성한다. 64비트만 지원하는 경우 이 항목은 필요하지 않다.
    • directories
      • output: build한 파일이 저장되는 디렉토리를 뜻한다.
      • buildResources: build시 필요한 리소스(아이콘 이미지)가 저장된 경로를 뜻한다.

package.json 구성이 끝났다면 build를 하는데, 기본 명령어는 다음과 같다.

npx electron-builder -mwl

m은 mac, w는 winodws, l은 linux를 의미한다. 세가지 옵션을 모두 쓸 필요는 없고 필요한 옵션만 사용하면 된다.

이렇게 하면 프로젝트의 build 폴더에 윈도우용 exe 설치파일, mac용 dmg 설치파일, linux용 snap 설치 파일이 생성된다.

이제 build는 완료되었다. 이번에는 자동업데이트 기능을 포함한 build 파일을 생성해보자.

electron-autoUpdater

autoUpdater를 적용하려면 반드시 서명된 인증서가 필요하다.
build를 할 때도 인증서가 필요하지만 build까지는 인증서가 없어도 할 수 있는 방법이 있는데(맥의 경우 키체인에서 발급받은 인증서로 확인 절차를 패스할 수 있음) autoUpdater를 적용하려면 반드시 서명된 인증서가 있어야 한다.

우선 autoUpdater를 설치한다.

npm install --save electron-updater

autoUpdater를 사용하려면 작성해야 할 코드가 있다. 프로젝트의 main.js에 작성하는데 위치는 다음 구문 바로 위에 작성한다.

// main.js

// update 구문을 여기에 작성

  mainWindow.on('closed', function () {
    equipmentManager.close();
    mainWindow = null;
  });

mainWinodw는 new BrowserWindow로 생성한 인스턴스를 뜻한다.
나는 updater.js 를 별도로 분리해 작성했다. 프로그램이 시작되고 1초 후에 업데이트를 감지하도록 했다.

// updater.js

const { dialog } = require('electron');
const { autoUpdater } = require('electron-updater');
const ProgressBar = require('electron-progressbar');

autoUpdater.autoDownload = false;

module.exports = () => {
  autoUpdater.checkForUpdates();

  let progressBar;
  
/* 업데이트가 가능한지 확인하는 부분이다.
업데이트가 가능한 경우 팝업이 뜨면서 업데이트를 하겠냐고 묻는다.
Update를 클릭하면 업데이트 가능한 파일을 다운로드 받는다. */
  autoUpdater.on('update-available', () => {
    dialog
      .showMessageBox({
        type: 'info',
        title: 'Update available',
        message:
          'A new version of Project is available. Do you want to update now?',
        buttons: ['Update', 'Later'],
      })
      .then((result) => {
        const buttonIndex = result.response;

        if (buttonIndex === 0) autoUpdater.downloadUpdate();
      });
  });

/* progress bar가 없으면 업데이트를 다운받는 동안 사용자가 그 내용을 알 수 없기 때문에
progress bar는 꼭 만들어준다. */
  autoUpdater.once('download-progress', (progressObj) => {
    progressBar = new ProgressBar({
      text: 'Downloading...',
      detail: 'Downloading...',
    });

    progressBar
      .on('completed', function () {
        console.info(`completed...`);
        progressBar.detail = 'Task completed. Exiting...';
      })
      .on('aborted', function () {
        console.info(`aborted...`);
      });
  });

  // 업데이트를 다운받고 나면 업데이트 설치 후 재시작을 요청하는 팝업이 뜬다.
  autoUpdater.on('update-downloaded', () => {
    progressBar.setCompleted();
    dialog
      .showMessageBox({
        type: 'info',
        title: 'Update ready',
        message: 'Install & restart now?',
        buttons: ['Restart', 'Later'],
      })
      .then((result) => {
        const buttonIndex = result.response;

        if (buttonIndex === 0) autoUpdater.quitAndInstall(false, true);
      });
  });
};

이제 autoUpdate를 사용할 수 있는 준비가 완료되어 최초 릴리즈 파일이 생성되었다. 이제 깃허브에 release를 해야한다.

깃허브는 release 기능을 제공하고 있는데, autoUpdate에 사용할 깃허브 저장소는 package.json에 작성된 것이기만 하면 된다. 깃허브에 프로젝트 저장소가 있다면 거기에서 바로 release 기능을 사용해도 되지만 그게 아니라 깃랩 등의 서비스를 활용하고 있었다면 깃허브에 release만을 위한 저장소를 생성하면 된다. 이 저장소에는 프로젝트 코드까지 업로드할 필요는 없다. build가 완료된 파일만 release할 것이기 때문이다.

깃허브에 저장소를 생성하고 나면 저장소 우측에 Release 링크가 있는 것을 확인할 수 있다.

여기에서 Create a new release를 클릭하면 다음과 같은 화면이 나타난다. 여기에 tag, release 이름, 내용, 파일 등을 추가해 Publish release를 해준다.

설치 파일은 exe, dmg 둘 다 업로드하거나 필요에 따라 하나만 업로드해도 무방하다. 그러나 latest.yml 파일은 반드시 함께 업로드 해야 한다.

그러면 최초 release 파일이 생성되어 다음과 같이 파일이 생성된다.

이 설치파일을 저장한 뒤, 이제 autoUpdate가 제대로 동작하는지 보기 위해서 release 파일을 하나 더 만들어야 한다. tag는 이전 설치파일보다 높은 숫자로 설정해야 한다. release를 마치고 기존에 받아뒀던 파일을 실행해보면 다음과 같은 팝업이 나타나게 된다.

Update를 클릭하면 progress bar가 나타나고

Update 파일을 다운받고 나면 설치 후 재시작 하겠냐는 팝업이 나타난다.

재시작을 하고 나면 버전이 update된 프로젝트를 확인할 수 있다!

프로젝트 icon 변경

프로젝트 icon은 별도의 코드가 필요하지 않다. 이미지 파일이 저장된 경로만 잘 작성해주면 된다.
electron-builder에서 권장하는 icon 파일 형태는 다음과 같다.

mac: icns (png 가능) / png 파일일 경우 @2 파일도 함께 추가해야 한다.
windows: ico (png 가능)
linux: png

그런데 apple의 App Icon 가이드를 보면 다음과 같은 구문이 있다.

Don’t provide app icons in ICNS or JPEG format.
The ICNS format doesn’t support features like wide color gamut or deliver the performance and efficiency you get when you use asset catalogs.
JPEG doesn’t support transparency through alpha channels, and its compression can blur or distort an icon’s images. For best results, add deinterlaced PNG files to the app icon fields of your Xcode project’s asset catalog.

애플의 가이드에서 png 파일의 사용을 권장했기 때문에 나는 assets 폴더에 icon을 추가했는데 구조는 다음과 같다.

icons 폴더 내부의 파일들은 사이즈에 유연하게 대비하기 위해 작성한 파일들이다.
icons 폴더의 형제 레벨에 작성된 icon.icoicon.png가 icon을 변경할 때 필요한 최소한의 파일이 된다.

원래 electron-builder에서 icon 파일을 탐색하는 경로는 build지만 위에서 package.json에 경로를 재지정해주었기 때문에

"buildResources": "assets"

electron-builder는 icon 파일은 build 폴더가 아닌 assets 폴더에서 탐색하게 된다.


참고
electron
electron-builder
electron auto update
electron build icons
electron-updater 프로그램 자동 업데이트

profile
개발을 개발개발 🐾
post-custom-banner

1개의 댓글

comment-user-thumbnail
2022년 8월 18일

안녕하세요 좋은글 감사합니다.
질문사항이 있어서요! 혹시 깃허브 업로드 용량제한이 있는데 혹시 노드모듈이나 일렉트론(크로미움 )용량은 어떻게 줄여서 커밋하시는건가요? ㅜㅜ

답글 달기