⚡ Electron6. 패키징 & 배포Auto-Update — Squirrel과 electron-updater

Auto-Update — Squirrel과 electron-updater

이 문서가 답하는 질문: “사용자에게 binary로 배포한 앱을 어떻게 URL처럼 자동 갱신하는가?” 한 줄 답 (Pyramid Top): *“Auto-update는 서명된 새 binary를 다운로드하고 원자적으로 교체하는 메커니즘 — 그 핵심은 Squirrel(맥/윈도우 분리 구현체)과 electron-updater가 가린 추상화다.”


Why — 왜 존재하는가

웹앱은 URL 한 줄로 새 버전이 적용된다. Electron 앱은 바이너리다. 사용자가 매번 새 버전을 다운로드하지 않게 — 앱 안에 업데이터를 내장해야 한다.

문제이전 해법한계
매번 수동 설치”새 버전 받으세요” 알림사용자가 안 받음 → 보안 위험
강제 업데이트앱 시작 시 차단UX 망가짐
백그라운드 다운로드 + 재시작 시 교체Squirrel / Sparkle코드 서명·서버 인프라 필요

웹: URL 갱신 = 즉시. 데스크톱: binary 교체 = 수 분~수 시간의 설계 작업.


How — 어떻게 동작하는가

핵심: 다운로드 → 검증 → 적용의 3단계. 적용은 앱이 종료된 후 외부 헬퍼(Squirrel)가 수행한다.


What — 구체 사양·수치·예시

electron-updater (electron-builder 진영)

// main.js
const { autoUpdater } = require('electron-updater');
const log = require('electron-log');
 
autoUpdater.logger = log;
autoUpdater.autoDownload = true;
autoUpdater.autoInstallOnAppQuit = true;
 
app.whenReady().then(() => {
  autoUpdater.checkForUpdatesAndNotify();
});
 
autoUpdater.on('update-available', (info) => {
  log.info('Update available', info.version);
});
autoUpdater.on('update-downloaded', (info) => {
  // 사용자에게 알림 — "지금 재시작" / "나중에"
  dialog.showMessageBox({
    type: 'info',
    buttons: ['지금 재시작', '나중에'],
    title: '업데이트 준비됨',
    message: `${info.version} 버전이 준비됐습니다.`,
  }).then(({ response }) => {
    if (response === 0) autoUpdater.quitAndInstall();
  });
});
autoUpdater.on('error', (err) => {
  log.error('Updater error', err);
});

업데이트 서버 설정 (electron-builder)

# electron-builder.yml
publish:
  - provider: github          # GitHub Releases 사용
    owner: my-org
    repo: my-app
    releaseType: release      # 또는 prerelease
  # 또는
  - provider: s3
    bucket: my-app-updates
    region: us-east-1
  # 또는 Hazel/Nucleus 서버
  - provider: generic
    url: https://updates.mycompany.com

빌드 시 자동으로 다음 파일이 함께 업로드된다:

latest.yml          # macOS arm64 메타
latest-mac.yml      # macOS Intel
latest.yml          # Windows
my-app-1.2.0.dmg    # 실제 binary
my-app-1.2.0.dmg.blockmap  # 차등 업데이트용

Squirrel 직접 사용 (electron-forge 진영)

// main.js — autoUpdater는 Node API와 Electron API 두 가지가 있음
const { autoUpdater } = require('electron');  // Squirrel 직접
const server = 'https://update.electronjs.org';
const url = `${server}/my-org/my-app/${process.platform}-${process.arch}/${app.getVersion()}`;
 
autoUpdater.setFeedURL({ url });
setInterval(() => autoUpdater.checkForUpdates(), 10 * 60 * 1000); // 10분마다
 
autoUpdater.on('update-downloaded', () => {
  autoUpdater.quitAndInstall();
});

플랫폼별 차이

macOSWindowsLinux
메커니즘Squirrel.MacSquirrel.Windowselectron-updater AppImage/deb
서명 필수Yes (Developer ID)Yes (Authenticode)선택
diff updateblockmapblockmapblockmap
사용자 클릭?dialog → quitAndInstall자동 또는 dialog자동 또는 dialog
설치 위치/Applications%LocalAppData% (Squirrel) 또는 Program Files (NSIS)/opt 또는 ~/.local

차등(delta) 업데이트

# 1.0.0 → 1.1.0 빌드 시 blockmap이 함께 생성됨
# 사용자는 변경된 블록만 다운로드 (예: 200MB binary → 30MB diff)

blockmap은 내용 기반 chunk hash. binary가 80% 같으면 80%만큼 다운로드 면제.

채널(channel) 분리

# beta 채널
publish:
  - provider: github
    releaseType: prerelease
    channel: beta
autoUpdater.channel = 'beta';  // 사용자가 베타 옵트인 시

What-if — 잘못 쓰면

  • 함정 1: 코드 서명 안 한 빌드 → 업데이트 적용에서 macOS Gatekeeper 거부. 사용자 앱이 부팅 못 함.
  • 함정 2: 업데이트 서버를 HTTP로 (HTTPS 아님) → MITM 통한 악성 업데이트 주입. 반드시 HTTPS.
  • 함정 3: quitAndInstallrenderer에서 호출 → preload 없으면 IPC 통해 호출해야 함. IPC 채널 검증 필수.
  • 함정 4: 다운로드 검증 누락 — 자체 서명 검증 안 하고 적용 → 변조 binary 설치. 표준 updater는 자동 검증하지만 커스텀 구현 시 빠뜨림.
  • 함정 5: 강제 즉시 재시작 → 사용자 작업 잃음. 항상 옵션 제공.
  • 함정 6: 너무 자주 체크 (1분마다) → 서버 비용·사용자 네트워크 부담. 보통 1~6시간 간격.

Insight — 흥미로운 이야기

“Squirrel은 Mac의 Sparkle을 모델로 만들었다”

2008년 Andy Matuschak이 만든 Sparkle은 macOS 데스크톱 앱 자동 업데이트의 de facto 표준이었다. GitHub의 Cheng Zhao(Electron 창시자)는 Atom Shell에서 같은 패턴이 필요했고 — Sparkle을 플랫폼 중립으로 다시 그린 것이 Squirrel이다.

흥미로운 반전은 — Squirrel이 Mac과 Windows에서 완전히 다른 코드베이스라는 점. macOS는 LaunchAgent로 업데이트 헬퍼를 띄우고, Windows는 NuGet 패키지로 변경분을 적용한다. 두 구현을 하나의 autoUpdater API로 추상화한 게 Electron의 영리한 설계 — 개발자는 quitAndInstall() 한 줄만 알면 된다.

더 흥미로운 건 — Slack, Discord, VSCode 같은 거대 Electron 앱이 모두 Squirrel을 쓰지 않는다. 자기 인프라가 필요한 규모가 되면 Electron의 기본 autoUpdater를 떠나, 자체 다운로드/검증/롤백 시스템을 짓는다. Squirrel은 시작점이지 종착점이 아니다.


요약

  • electron-updater = 빠른 시작. Squirrel = 가장 작은 단위.
  • 업데이트 = 다운로드 + 검증 + 교체. 셋 중 하나만 빠져도 사고.
  • 서버: GitHub Releases / S3 / Hazel / Nucleus / 자체.
  • 채널·delta는 나중에 도입 가능 — 처음엔 stable만으로 시작.