Electron 자동 업데이트 구현 삽질기 — electron-updater의 함정들

게시일: 2025년 5월 2일 · 16분 읽기

업데이트가 무한 루프 빠진 거 인지하는 데 3일 걸렸다. 사용자 컴퓨터는 계속 재부팅을 반복하고 있었다.

Setup: electron-updater 기본

npm install electron-updater

main.ts:

import { autoUpdater } from 'electron-updater';

app.on('ready', () => {
    autoUpdater.checkForUpdatesAndNotify();
    // ← 이 한 줄로 끝이라고 생각했다
});

package.json:

{
    "name": "my-app",
    "version": "1.0.0",
    "build": {
        "publish": {
            "provider": "github",  // 또는 "s3"
            "owner": "myname",
            "repo": "my-app"
        }
    }
}

문제 1: Code Signing 필수

업데이트가 검증되지 않으면 설치되지 않는다.

Mac에서:

// package.json build config
"build": {
    "mac": {
        "certificateFile": "path/to/certificate.p12",
        "certificatePassword": "password"
    }
}

Windows에서:

// package.json
"build": {
    "win": {
        "certificateFile": "path/to/certificate.pfx",
        "certificatePassword": "password"
    }
}

없으면:

Error: Code sign failed. Signing certificate not found. Unable to find a matching code signing certificate.

해결: Windows에서는 자체 서명 인증서로 테스트 가능:

// electron-builder는 자체 서명 인증서 생성
// 개발 중에는 코드 서명 건너뛰기
"build": {
    "win": {
        "sign": false  // ← 개발 중에만
    }
}

문제 2: 무한 업데이트 루프

우리의 경우:

버전 1.0.0 설치됨
자동 업데이트 체크 → 새 버전 1.0.1 있음
1.0.1 설치 및 재부팅
다시 시작된 앱이 자동 업데이트 체크 → 1.0.1이 이미 설치됨, 아무것도 안 함 (OK)

하지만 우리 경우:
계속 1.0.1을 "새 버전"으로 인식 → 무한 루프

원인: GitHub release가 잘못 설정됨

electron-updater는 다음을 읽음:

https://api.github.com/repos/myname/my-app/releases/latest

이 응답에서 "latest" release를 찾는다.

해결: GitHub에서 release를 "Latest Release"로 마크:

// GitHub UI
Release tab → Edit → "Set as the latest release" 체크

문제 3: Differential Updates가 안 됨

differential update는 변경된 부분만 다운로드하는 기능이다 (100MB → 5MB)

작동하려면:

1. 이전 버전의 .exe 또는 .app이 존재해야 함
2. GitHub release에 최소 2개 이상의 버전이 있어야 함
3. electron-builder가 자동으로 delta 파일 생성해야 함

github.yml (GitHub Actions):

name: CI

on:
  push:
    tags:
      - 'v*'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'

      - run: npm install
      - run: npm run build:electron

      - uses: softprops/action-gh-release@v1
        with:
          files: |
            dist/my-app-*.exe
            dist/my-app-*.dmg
            dist/*.blockmap  # ← Delta 정보
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

중요: dist/*.blockmap을 GitHub release에 업로드해야 delta update가 작동한다.

문제 4: S3 호스팅

GitHub 용량 제한 (100MB 이상 안 됨)이 있으면 S3 사용:

// package.json
"build": {
    "publish": {
        "provider": "s3",
        "bucket": "my-app-releases",
        "region": "us-east-1"
    }
}

AWS IAM 정책:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::my-app-releases/*"
        }
    ]
}

환경변수:

export AWS_ACCESS_KEY_ID=xxx
export AWS_SECRET_ACCESS_KEY=xxx
npm run build:electron  // ← S3에 자동 업로드

문제 5: 업데이트 UI

단순한 자동 업데이트는 사용자가 모른다.

좋은 UX:

import { autoUpdater } from 'electron-updater';

autoUpdater.on('checking-for-update', () => {
    mainWindow.webContents.send('update-status', '업데이트 확인 중...');
});

autoUpdater.on('update-available', () => {
    mainWindow.webContents.send('update-status', '새 버전 다운로드 중...');
});

autoUpdater.on('update-downloaded', () => {
    dialog.showMessageBox(mainWindow, {
        type: 'info',
        title: '업데이트 준비 완료',
        message: '앱을 다시 시작하여 업데이트를 적용합니다.',
        buttons: ['지금 다시 시작', '나중에']
    }).then(result => {
        if (result.response === 0) {
            autoUpdater.quitAndInstall();
        }
    });
});

autoUpdater.on('error', (error) => {
    mainWindow.webContents.send('update-error', error.message);
});

// 1시간마다 체크
setInterval(() => {
    autoUpdater.checkForUpdates();
}, 1000 * 60 * 60);

배포 체크리스트

□ package.json 버전 업데이트 (예: 1.0.0 → 1.0.1)
□ 코드 서명 인증서 준비
□ npm run build:electron 실행
□ dist/ 폴더에 .exe/.dmg/.blockmap 생성 확인
□ GitHub release 생성 및 파일 업로드
□ "Set as latest release" 체크
□ 이전 버전 앱에서 업데이트 테스트
□ 모니터링 (업데이트 성공률)

결론

electron-updater는 강력하지만 함정이 많다. 특히 code signing과 delta update 설정이 중요하다.

우리는 이 경험 후 모든 업데이트를 다음 버전부터 자동화했다:

  • Git tag 푸시 → GitHub Actions 자동 빌드 및 배포
  • release-it 도구로 버전/changelog 자동 관리
  • 모니터링: 업데이트 성공/실패율 추적

이제 업데이트는 안정적이다. 그리고 사용자는 자동으로 최신 버전을 받는다.

iL
ian.lab

실무 개발자입니다. 현장에서 겪은 문제와 해결 과정을 기록합니다. 오류 제보는 연락처로 보내주세요.