일렉트론 자동 업데이트 설정하기 (electron auto-updater)
일반적으로 일렉트론으로 빌드한 클라이언트 프로그램에는 많은 비즈니스 로직을 담지 않는다.
1. 클라이언트는 결국 사용자의 컴퓨터에 설치되기 때문에 작정하고 까보면 내부 코드를 파악할 수 있고,
2. 실제 서비스와 관련된 비즈니스 로직을 너무 많이 담으면 유지보수가 힘들어지며,
3. 특히나 단순히 WebView Wrapper로서 사용하는 거라면 더더욱 그렇다. 보여지는 것에 집중하지, 내부 로직은 담지 않는다.
그럼에도 불구하고, 부득이하게 내부 정책이나 서버 환경 변동에 따라 업데이트가 필요한 경우가 있다.
캡처 방지와 같은 보안 기능을 넣고 빼거나, 로딩 페이지 경로 등 환경변수에 변화가 있을 때에도 다시 빌드해서 배포해 주어야 한다.
이런 점을 고려했을 때,
버전이 업그레이드될 때 유저에게 재설치하라는 것보다는...
운영/보안적 측면에서 업데이트를 자동으로 진행하는 편이 유리하다.
빌드시 생성되는 파일들
일렉트론 클라이언트를 빌드하면 아래와 같은 파일들이 생성된다.
mac 옵션을 추가한 경우 client.dmg, latest-mac.yml 과 같은 파일도 포함된다.
total 1314104
-rw-r--r--@ 1 jiyunkim staff 9.7K 8 4 10:44 builder-debug.yml
-rw-r--r--@ 1 jiyunkim staff 1.4K 8 4 10:40 builder-effective-config.yaml
-rw-r--r--@ 1 jiyunkim staff 108M 8 4 10:41 Client-mac-arm64.dmg
-rw-r--r--@ 1 jiyunkim staff 116K 8 4 10:41 Client-mac-arm64.dmg.blockmap
-rw-r--r--@ 1 jiyunkim staff 104M 8 4 10:42 Client-mac-arm64.zip
-rw-r--r--@ 1 jiyunkim staff 112K 8 4 10:42 Client-mac-arm64.zip.blockmap
-rw-r--r--@ 1 jiyunkim staff 114M 8 4 10:43 Client-mac-x64.dmg
-rw-r--r--@ 1 jiyunkim staff 123K 8 4 10:43 Client-mac-x64.dmg.blockmap
-rw-r--r--@ 1 jiyunkim staff 110M 8 4 10:43 Client-mac-x64.zip
-rw-r--r--@ 1 jiyunkim staff 117K 8 4 10:43 Client-mac-x64.zip.blockmap
-rw-r--r--@ 1 jiyunkim staff 87M 8 4 10:44 Client-win-x64.exe
-rw-r--r--@ 1 jiyunkim staff 95K 8 4 10:44 Client-win-x64.exe.blockmap
-rw-r--r--@ 1 jiyunkim staff 118M 8 4 10:43 Client-win-x64.zip
-rw-r--r--@ 1 jiyunkim staff 811B 8 4 10:44 latest-mac.yml
-rw-r--r--@ 1 jiyunkim staff 342B 8 4 10:44 latest.yml
drwxr-xr-x@ 3 jiyunkim staff 96B 8 4 10:41 mac
drwxr-xr-x@ 3 jiyunkim staff 96B 8 4 10:40 mac-arm64
drwxr-xr-x@ 20 jiyunkim staff 640B 8 4 10:43 win-unpacked
각 파일의 역할
과거에는 Squirrel.Win/Mac 이라는 오픈소스 배포/업데이트 프레임워크를 사용해서 일렉트론 앱 자동 업데이트를 지원받았다.
RELEASE 파일과 .nupkg 패키지를 이용해서 Github Releases와 함께 자주 사용되었다.
하지만 지금은 권장 업데이트 방식이 electron-updater + generic 방식으로 바뀌는 추세다.
generic : 자체적으로 관리하는 HTTP(S) 기반의 일반 웹 서버를 업데이터 서버로 지정할 때 사용하는 Provider 이름.
elctron-builder 관련 config 파일에서 지정할 수 있다.
그리고 macOS에서는 별도 빌드 설정이 없을 때, 자동 업데이트를 제대로 사용하려면 .dmg 외에도 .zip 파일이 필요하다.
https://til.simonwillison.net/electron/electrion-auto-update
OS / 업데이트 방식 | 필수 메타데이터 | 필수 패키지 파일 | 비고 |
Windows – NSIS (electron-builder 기본) |
latest.yml | .exe, .exe.blockmap | blockmap은 패치 다운로드 시 일부만 받아서 적용하는 데 사용 |
macOS – dmg/zip | latest-mac.yml | .dmg + .dmg.blockmap .zip + .zip.blockmap |
.dmg는 초기 설치용, 자동 업데이트는 .zip 사용 |
Linux | latest-linux.yml | .AppImage 또는 .tar.gz | 플랫폼별 포맷에 맞게 제공, blockmap은 AppImage 업데이트 시 사용 가능 |
blockmap????
blockmap 파일은 마이크로소프트에서 아래와 같이 정의하고 있다.
The package block map file is an XML document that contains a list of the app’s files along with indexes and cryptographic hashes for each block of data that is stored in the package.
즉, 설치 파일의 모든 내용을 다운받지 않고 업데이트된 부분만 확인하고 다운받아서 설치할 수 있도록 돕는 XML 파일이다!
설치 파일을 작은 블록 단위로 해시하여 기록하고 변경된 부분만 다운로드하기 때문에,
네트워크 트래픽 절감과 더불어 빠르게 업데이트할 수 있게 도와준다!
latest.yml
version: 1.0.2
files:
- url: Client.exe
sha512: {...}
size: 85941005
path: Client.exe
sha512: {...}
releaseDate: '2025-07-21T21:08:37.539Z'
빌드 당시 buildConfig.json, package.json 에서 정의한 버전이나 파일명, 빌드한 시간 등
릴리즈에 필요한 메타데이터가 포함돼 있다.
항목명 | 설명 |
version | 앱의 버전 (package.json의 version과 동일) |
files | 설치 파일 목록 (여러 개일 수 있음) 각 항목은 url, sha512, size 포함 |
└ url | 설치 파일의 상대 경로 또는 이름 (feedURL 기준) |
└ sha512 | 설치 파일의 SHA-512 해시값 (무결성 검증에 사용) |
└ size | 설치 파일의 크기 (byte 단위) |
path | 기본 설치 파일 경로. 일반적으로 files[0].url과 동일 |
sha512 | 기본 설치 파일의 해시값. files[0].sha512와 동일 |
releaseDate | 이 릴리즈가 게시된 시간. 업데이트 여부 판단에 사용됨 |
autoUpdater가 자동으로 업데이트하는 과정
1. 앱 실행 → autoUpdater.checkForUpdates() 호출
2. 서버에서 latest.yml 다운로드
3. 버전 비교 후, 새로운 버전이 있는 경우 .exe.blockmap 다운로드 (맥의 경우 .dmg.blockmap)
4. 변경된 블록만 .exe에서 다운로드
5. 다운로드 완료 후 quitAndInstall() 로 시작
이 때, blockmap이 없는 경우에는 전체 파일을 재다운로드하고 설치한다.
그럼 빌드해서 나온 위와 같은 파일들을 특정 경로에서 공급받을 수 있게 설정했다는 가정 하에,
자동 업데이트를 설정해 보자.
Auto-update 설정 방법
https://www.electronjs.org/docs/latest/api/auto-updater
클라이언트 프로그램 내 main.ts를 아래처럼 구성한다. (업데이트와 관련 없는 코드는 표시하지 않음)
import { app } from "electron";
import log from "electron-log";
import { autoUpdater } from "electron-updater";
import semver from "semver/preload";
if (app) {
// 로그 파일 경로 설정
log.transports.file.level = "info";
autoUpdater.logger = log; // autoUpdator 관련 로그를 electron-log와 동일하게 처리
app.whenReady().then(async () => {
process.env.UPDATE_URL && autoUpdater.setFeedURL(process.env.UPDATE_URL);
const result = await autoUpdater.checkForUpdates();
if (result) {
log.info(result);
const { updateInfo } = result;
if (semver.lt(app.getVersion(), updateInfo.version)) {
//업데이트가 있을 경우 처리
...
return;
}
}
});
autoUpdater.on("update-downloaded", (info) => {
autoUpdater.quitAndInstall(true, true);
});
}
여기서 사용된 주요 함수를 살펴보자.
setFeedURL(options: PublishConfiguration | AllPublishOptions | string): void;
latest.yml 등 클라이언트 업데이트 관련 정보를 제공하는 경로를 정의한다. (단순히 string만 넣는 경우 url로 자동 설정)
우선 latest.yml을 읽어서 버전 등 업데이트 가능한 정보가 있는지 판단 후,
url 경로에서 latest.yml 내에 정의된 업데이트파일을 찾아 설치한다.
abstract quitAndInstall(isSilent?: boolean, isForceRunAfter?: boolean): void;
업데이트 파일이 다운로드가 완료된 후, 앱을 재시작하고 설치를 진행한다.
반드시 autoUpdater.on("update-downloaded") 의 콜백 함수 내에서 호출되어야 한다.
우선 어플리케이션을 종료한 후 quit 이벤트가 발생하기 전에 실행된다.
isSlient : true일 때 사용자에게 재시작 여부를 묻지 않고, 조용히 종료한 후 업데이트를 설치한다.
isForceRunAfter : 설치 완료 후 애플리케이션 재시작 여부 (isSilent가 true여도 적용, macOS에는 적용되지 않음)
semver로 편하게 버전 비교하기
Semantic Versioning의 줄임말로, 소프트웨어 버전 번호를 표준화된 방식으로 관리하기 위한 규칙이다.
일반적으로 x.y.z 형식의 숫자로 구성되고, 각각 의미를 갖고 있는 semantic으로 나눈다.
major.minor.patch | |
major | 호환되지 않는 API 변경이 있을 때 증가 ex. 기존 API를 제거하거나 방식이 바뀌었음 |
minor | 하위 호환되는 기능 추가시 증가 ex. 새로운 기능이 추가됐지만 기존 기능에 영향 없음 |
patch | 하위 호환되는 버그 수정시 증가 ex. 버그 수정 또는 내부 구현 변경 (기능 추가 없음) |
위 규칙 외에도, 버전만 보고 업데이트 가능 여부를 판단해주는 semver.lt(v1, v2) 와 같은 함수도 지원한다.
lt는 less than의 약자로, 파라미터로 주어진 두 버전을 SemVer 규칙에 따라 비교하여 boolean을 리턴해 준다.
semver.lt(v1, v2)는 return v1 < v2 와 같이 작동한다.
그 외에도 lte(less than or equal), gt(greater than), gte(greater than or equal),
eq(equal), neq(not equal) 등 여러 가지 비교함수가 있으므로 필요에 따라 사용하면 좋다.
'TIL > ETC' 카테고리의 다른 글
nginx http2 설정 (feat. http/1.x 부터 http/3) (7) | 2025.08.05 |
---|---|
fail2ban 설정하기 (9) | 2025.07.17 |
VPN 해제 후 공인 IP 기반 서비스 오픈과 보안 구성 (0) | 2025.07.16 |