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();
});플랫폼별 차이
| macOS | Windows | Linux | |
|---|---|---|---|
| 메커니즘 | Squirrel.Mac | Squirrel.Windows | electron-updater AppImage/deb |
| 서명 필수 | Yes (Developer ID) | Yes (Authenticode) | 선택 |
| diff update | blockmap | blockmap | blockmap |
| 사용자 클릭? | 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: betaautoUpdater.channel = 'beta'; // 사용자가 베타 옵트인 시What-if — 잘못 쓰면
- 함정 1: 코드 서명 안 한 빌드 → 업데이트 적용에서 macOS Gatekeeper 거부. 사용자 앱이 부팅 못 함.
- 함정 2: 업데이트 서버를 HTTP로 (HTTPS 아님) → MITM 통한 악성 업데이트 주입. 반드시 HTTPS.
- 함정 3:
quitAndInstall을 renderer에서 호출 → 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만으로 시작.