autoUpdater는 Electron 애플리케이션에서 자동 업데이트 기능을 구현하는 데 사용되는 모듈이 모듈을 사용하면 애플리케이션이 스스로 업데이트를 다운로드하고 설치할 수 있게 됨
기본 개념
autoUpdater모듈은EventEmitter를 상속받아 이벤트 기반으로 동작함
- 지원 플랫폼: 현재 macOS와 Windows에서만 자동 업데이트를 지원.
- Linux는 기본적으로 지원하지 않으며, 대신 배포판의 패키지 관리자를 사용하는 것이 권장됨
플랫폼별 특이 사항
macOS
- 기반:
autoUpdater모듈은Squirrel.Mac에 기반하여 동작. 별도의 설정 없이 기본적으로 동작하지만, 서버 쪽에서 특정 요구 사항을 충족해야 할 수 있음.
- 앱 서명: macOS에서는 자동 업데이트를 위해 애플리케이션이 반드시 서명되어 있어야 함.
- App Transport Security (ATS): 업데이트 과정에서 이루어지는 모든 요청은 ATS의 적용을 받음
만약 ATS를 비활성화해야 한다면, 앱의
plist 파일에 NSAllowsArbitraryLoads 키를 추가해야 함.Windows
- 기반: Windows에서는
Squirrel.Windows에 기반하여 동작
- 설치 필수:
autoUpdater를 사용하기 전에 애플리케이션이 사용자 시스템에 설치되어 있어야 합니다. 이를 위해electron-winstaller,Electron Forge,grunt-electron-installer등의 패키지를 사용해 설치 프로그램을 생성하는 것이 권장됨
- 첫 실행 시 업데이트 비활성화:
electron-winstaller나Electron Forge를 사용하는 경우, 애플리케이션이 처음 실행될 때 업데이트를 시도하지 않도록 설정해야 함
electron-squirrel-startup: 데스크탑에 애플리케이션의 바로가기를 자동으로 생성하는 패키지로, 업데이트와 설치 과정에서 유용
- 앱 사용자 모델 ID: Windows에서는 Squirrel이 생성한 바로가기에
Application User Model ID가 부여됨. 이 ID는app.setAppUserModelIdAPI에서 동일하게 설정해야 Windows가 애플리케이션을 올바르게 인식하고 작업 표시줄에 고정할 수 있음.
이벤트
autoUpdater 객체는 여러 이벤트를 발생시킴error: 업데이트 도중 오류가 발생했을 때 발생합니다.
checking-for-update: 업데이트를 확인하는 작업이 시작되었을 때 발생
update-available: 새로운 업데이트가 있을 때 발생하며, 이때 업데이트는 자동으로 다운로드
update-not-available: 업데이트가 없을 때 발생
update-downloaded: 업데이트가 다운로드된 후 발생. 이 이벤트는 다운로드된 업데이트를 설치하기 전에 필요한 작업을 수행할 수 있는 기회를 제공.
before-quit-for-update:quitAndInstall()이 호출된 후, 애플리케이션이 종료되기 전에 발생. 이 이벤트를 통해 애플리케이션 창이 닫히기 전에 작업을 수행할 수 있음.
메서드
autoUpdater 객체는 여러 가지 메서드를 제공:setFeedURL(options): 업데이트를 다운로드할 URL을 설정하고 자동 업데이트를 초기화.options객체는url,headers(선택적, macOS 전용),serverType(선택적, macOS 전용) 등의 속성을 포함.
getFeedURL(): 현재 설정된 업데이트 피드 URL을 반환.
checkForUpdates(): 서버에 업데이트가 있는지 확인.setFeedURL을 먼저 호출해야 하며, 업데이트가 있으면 자동으로 다운로드됨.
quitAndInstall(): 업데이트가 다운로드된 후 애플리케이션을 재시작하고 업데이트를 설치. 이 메서드는update-downloaded이벤트가 발생한 후에만 호출해야 함.
사용 예시
- 피드 URL 설정:
const { autoUpdater } = require('electron'); autoUpdater.setFeedURL({ url: 'https://your-update-server.com/updates/latest', });
- 업데이트 확인 및 설치:
autoUpdater.checkForUpdates(); autoUpdater.on('update-downloaded', () => { autoUpdater.quitAndInstall(); });
autoUpdater모듈은 Electron 애플리케이션이 자동으로 업데이트할 수 있도록 도와주는 모듈
- Windows와 macOS에서만 지원하며, 각 플랫폼마다 특별한 설정이나 요구 사항이 있습니다.
- 업데이트를 다운로드하고 설치하는 과정은 이벤트 기반으로 진행되며, 개발자는 이러한 이벤트를 통해 사용자 경험을 맞춤 설정할 수 있습니다.
- Linux는 자동 업데이트를 기본적으로 지원하지 않으므로, 각 배포판의 패키지 관리자를 사용하는 것이 좋습니다.
- 이벤트
- 'error': 업데이트 중 오류 발생 시
- 'checking-for-update': 업데이트 확인 시작 시
- 'update-available': 사용 가능한 업데이트가 있을 때
- 'update-not-available': 사용 가능한 업데이트가 없을 때
- 'update-downloaded': 업데이트 다운로드 완료 시
- 'before-quit-for-update': 사용자가 quitAndInstall() 호출 시
- 주요 메서드
- setFeedURL(options): 업데이트 피드 URL 설정
- getFeedURL(): 현재 업데이트 피드 URL 반환
- checkForUpdates(): 서버에 업데이트 확인 요청
- quitAndInstall(): 앱 재시작 및 다운로드된 업데이트 설치
- 주의사항:
- checkForUpdates()를 두 번 호출하면 업데이트를 두 번 다운로드합니다.
- quitAndInstall()은 update-downloaded 이벤트 발생 후에만 호출해야 합니다.
- 성공적으로 다운로드된 업데이트는 다음 앱 실행 시 자동으로 적용됩니다.
자동 업데이트가 있는 경우 사용자에게 선택할 수 있는 옵션을 제공하고,
사용자가 수락하면 업데이트를 진행하도록 애플리케이션을 설정하려면,
autoUpdater와 IPC(Inter-Process Communication)를 활용할 수 있습니다. 이를 통해 업데이트가 감지되면 사용자에게 알림을 표시하고, 사용자가 수락하면 업데이트를 진행할 수 있습니다.
아래는 기존 코드에 이 기능을 추가하는 방법
1. main.js 업데이트
먼저,
autoUpdater를 설정하고, 업데이트가 있을 때 사용자에게 알림을 보내는 기능을 추가// main.js require("update-electron-app")(); const { app, BrowserWindow, ipcMain, dialog } = require("electron"); const { autoUpdater } = require("electron-updater"); // electron-updater 모듈을 불러옴 const path = require("node:path"); function createWindow() { let win = new BrowserWindow({ width: 800, height: 600, webPreferences: { preload: path.join(__dirname, "preload.js"), }, }); win.loadFile("index.html"); // IPC 핸들러 설정: 업데이트 수락 시 호출 ipcMain.handle("install-update", () => { autoUpdater.quitAndInstall(); // 업데이트를 설치하고 앱을 종료 후 재시작 }); } app.whenReady().then(() => { ipcMain.handle("ping", () => "pong"); createWindow(); // 앱이 준비되면 업데이트 확인을 시작 autoUpdater.checkForUpdates(); // 업데이트 확인 시작 autoUpdater.on('checking-for-update', () => { console.log('Checking for updates...'); }); // 업데이트 가능 시 이벤트 처리 autoUpdater.on('update-available', (info) => { console.log('Update available.'); BrowserWindow.getAllWindows()[0].webContents.send('update-available', info); // 업데이트 가능함을 렌더러 프로세스에 알림 }); // 업데이트가 없을 시 이벤트 처리 autoUpdater.on('update-not-available', () => { console.log('Update not available.'); }); // 업데이트 다운로드 완료 시 이벤트 처리 autoUpdater.on('update-downloaded', (info) => { BrowserWindow.getAllWindows()[0].webContents.send('update-downloaded', info); // 업데이트 다운로드 완료를 렌더러 프로세스에 알림 }); app.on("activate", () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } }); }); app.on("window-all-closed", () => { if (process.platform !== "darwin") app.quit(); });
2. preload.js 업데이트
메인 프로세스와 렌더러 프로세스 간의 통신을 위해 필요한 IPC 메시지를 설정
// preload.js const { contextBridge, ipcRenderer } = require("electron"); contextBridge.exposeInMainWorld("versions", { node: () => process.versions.node, chrome: () => process.versions.chrome, electron: () => process.versions.electron, ping: () => ipcRenderer.invoke("ping"), installUpdate: () => ipcRenderer.invoke("install-update"), // 업데이트 설치 요청 }); contextBridge.exposeInMainWorld("autoUpdater", { onUpdateAvailable: (callback) => ipcRenderer.on("update-available", callback), // 업데이트 가능 이벤트 수신 onUpdateDownloaded: (callback) => ipcRenderer.on("update-downloaded", callback), // 업데이트 다운로드 완료 이벤트 수신 });
3. renderer.js 업데이트
업데이트가 가능할 때와 다운로드가 완료되었을 때 사용자에게 알림을 표시하는 코드를 작성
// renderer.js const information = document.getElementById("info"); information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})`; const func = async () => { const response = await window.versions.ping(); console.log(response); }; func(); // 업데이트가 가능할 때 이벤트 처리 window.autoUpdater.onUpdateAvailable((event, info) => { const userResponse = confirm('A new update is available. Do you want to update now?'); if (userResponse) { window.versions.installUpdate(); // 업데이트 설치 요청 } }); // 업데이트가 다운로드되었을 때 이벤트 처리 window.autoUpdater.onUpdateDownloaded((event, info) => { alert('Update downloaded and will be installed on restart.'); });
4. index.html
이전과 동일하게 유지할 수 있음