RSS듀오랩스

Electron 배포 가이드: Windows 설치부터 macOS 공증까지

Electron글: , Duolabs16분 읽기blogelectronmacostechnical-notewindows

Electron 앱은 개발 환경에서 실행하는 것과 사용자에게 전달하는 과정이 꽤 다릅니다. 개발 중에는 명령 하나로 앱을 열 수 있지만, 실제 배포에서는 운영체제별 패키징과 설치 파일, 코드 서명, macOS 공증, 자동 업데이트까지 연결해야 합니다.

처음에는 Electron 배포를 소스 코드를 실행 파일로 묶는 작업 정도로 정리하려고 했습니다. 공식 문서를 따라 범위를 확인해 보니 패키징은 중간 단계에 가까웠습니다. 사용자가 경고 없이 설치하고, 이전 버전에서 새 버전으로 올라가며, 문제가 생겼을 때 원인을 확인할 수 있어야 배포가 끝납니다.

전체 흐름은 다음과 같습니다.

소스 코드
  → 테스트와 빌드
  → Electron 앱 패키징
  → 운영체제별 설치 파일 생성
  → 코드 서명
  → macOS 공증
  → 배포 파일 업로드
  → 자동 업데이트 메타데이터 배포
  → 신규 설치와 업데이트 검증

패키징 도구부터 정합니다

Electron 공식 문서는 패키징과 배포 도구로 Electron Forge를 권장합니다. Forge는 애플리케이션을 패키징하고 Windows와 macOS용 설치 결과물을 만드는 과정을 하나의 설정으로 관리합니다.

Electron Builder 같은 다른 도구를 사용할 수도 있습니다. 어느 도구를 선택하든 필요한 단계는 비슷합니다. 패키징 도구를 중간에 바꾸면 설치 형식과 자동 업데이트 규칙도 달라질 수 있으므로 프로젝트 초기에 업데이트 방식까지 함께 확인하는 편이 좋습니다.

빌드 전에 고정해야 할 값

설치 파일을 만들기 전에 다음 정보를 정합니다.

  • 앱의 고유 식별자인 App ID와 macOS Bundle ID를 정합니다.
  • 사용자에게 표시할 제품 이름을 정합니다.
  • 버전 번호를 올리는 규칙을 정합니다.
  • Windows용 아이콘과 macOS용 아이콘을 준비합니다.
  • 설정, 데이터, 로그가 저장될 위치를 정합니다.
  • 배포 파일과 업데이트 메타데이터를 둘 저장소를 정합니다.
  • 지원할 운영체제 버전과 CPU 아키텍처를 정합니다.

App ID와 Bundle ID는 배포를 시작한 뒤 자주 바꾸지 않는 편이 좋습니다. 운영체제와 업데이트 시스템이 같은 애플리케이션인지 식별하는 데 사용하기 때문입니다.

이 단계에서 비밀 정보도 분리해야 합니다. Electron 패키지 안에 포함된 값은 사용자가 확인할 수 있다고 가정해야 합니다. API 비밀키와 서버 인증 정보는 Renderer 번들이나 ASAR 파일에 넣지 않고 서버에서 관리해야 합니다.

운영체제와 CPU 아키텍처를 나눕니다

Windows와 macOS 모두 x64와 ARM64 환경이 있습니다.

운영체제 주요 아키텍처 일반적인 결과물
Windows x64, ARM64 EXE, MSI, ZIP
macOS x64, ARM64, Universal APP, DMG, ZIP

macOS에서는 Intel용 x64 앱과 Apple Silicon용 ARM64 앱을 각각 배포하거나, 두 아키텍처를 포함한 Universal 앱을 만들 수 있습니다. Universal 앱은 사용자가 아키텍처를 고르지 않아도 되지만 파일 크기가 커지고 네이티브 모듈 패키징이 복잡해질 수 있습니다.

SQLite나 이미지 처리 라이브러리처럼 네이티브 바이너리를 포함한 모듈을 사용한다면 Electron 버전과 운영체제, 아키텍처에 맞게 다시 빌드해야 합니다. 한 환경에서 만든 바이너리가 다른 환경에서도 실행될 것이라고 가정하면 패키징 후에만 오류가 나타나기 쉽습니다.

Windows는 설치 형식과 서명이 핵심입니다

앱을 패키징합니다

먼저 Electron 실행 파일과 애플리케이션 코드를 배포 가능한 디렉터리로 묶습니다. 제품 이름과 버전, 아이콘도 이때 적용됩니다.

애플리케이션 코드는 보통 app.asar로 묶을 수 있습니다. ASAR은 파일을 한 덩어리로 관리하기 위한 형식이지 암호화나 비밀 보호 장치가 아닙니다. 노출되면 안 되는 값은 포함하지 않아야 합니다.

네이티브 실행 파일이나 런타임에 직접 접근해야 하는 파일은 ASAR 밖으로 풀어 두는 설정이 필요할 수 있습니다. 개발 환경의 상대 경로에 의존하기보다 process.resourcesPath와 Electron의 경로 API를 기준으로 찾는 편이 안전합니다.

설치 파일을 만듭니다

패키징된 폴더를 ZIP으로 전달할 수도 있지만 일반 사용자에게는 설치 프로그램을 제공하는 편이 편리합니다.

Windows에서는 Squirrel 기반 설치 파일, MSI, 실행형 설치 파일, 포터블 ZIP 같은 형식을 검토할 수 있습니다. 일반 사용자용 앱과 기업에서 중앙 배포하는 앱은 요구사항이 다르므로 설치 대상과 업데이트 방식을 먼저 정해야 합니다.

사용자 계정에 설치할지, 시스템 전체에 설치할지도 중요합니다. 시스템 전체 설치는 관리자 권한이 필요할 수 있습니다. 권한이 없는 사용자도 설치해야 한다면 깨끗한 일반 계정에서 실제 설치 과정을 확인해야 합니다.

코드 서명을 적용합니다

서명되지 않은 Windows 앱은 다운로드하거나 실행할 때 게시자를 확인할 수 없다는 경고가 표시될 수 있습니다. 코드 서명은 게시자와 파일 무결성을 확인하는 수단입니다.

Windows에서는 지원되는 코드 서명 인증서나 클라우드 서명 서비스를 선택합니다. Electron Forge는 Azure Artifact Signing 같은 방식도 지원합니다. 사용할 수 있는 국가와 계정 조건, CI 연동 방법은 서비스별로 다르므로 신청 전에 확인해야 합니다.

앱 실행 파일만 서명하고 끝내기보다 최종 설치 파일까지 서명해야 합니다. 타임스탬프도 함께 적용하면 인증서가 만료된 뒤 서명 시점의 유효성을 확인하는 데 도움이 됩니다. 자세한 준비 항목은 Electron 공식 코드 서명 문서에서 확인할 수 있습니다.

코드 서명이 모든 SmartScreen 경고를 즉시 없애 준다고 단정해서는 안 됩니다. 인증서 방식과 파일의 배포 이력에 따라 초기 경고가 남을 수 있습니다. 실제 다운로드 주소에서 파일을 내려받고 실행해 보는 과정이 필요합니다.

깨끗한 Windows에서 확인합니다

개발 컴퓨터에는 이전 설치 파일과 설정, 런타임이 남아 있습니다. 이 환경에서만 테스트하면 신규 사용자가 겪는 문제를 놓치기 쉽습니다.

  • 처음 설치한 뒤 정상적으로 실행되는지 확인합니다.
  • 한글과 공백이 포함된 사용자 경로에서도 동작하는지 확인합니다.
  • 관리자 권한이 없는 계정에서 설치와 실행을 확인합니다.
  • Windows Defender와 SmartScreen에 표시되는 내용을 확인합니다.
  • 이전 버전에서 새 버전으로 업데이트되는지 확인합니다.
  • 실행 중인 앱을 업데이트할 때 파일 잠금 문제가 없는지 확인합니다.
  • 제거 후 설정과 사용자 데이터가 어떻게 남는지 확인합니다.

신규 설치와 업데이트 설치는 서로 다른 테스트입니다. 새 컴퓨터에서는 잘 설치되지만 이전 버전 위에 올릴 때만 실패하는 경우도 있습니다.

macOS는 서명 다음에 공증이 이어집니다

아키텍처를 결정합니다

Intel Mac을 지원하려면 x64 빌드가 필요하고 Apple Silicon을 지원하려면 ARM64 빌드가 필요합니다. 두 파일을 따로 배포하거나 Universal 앱으로 합칠 수 있습니다.

네이티브 모듈을 사용한다면 각 아키텍처에서 실제로 로드되는지 확인해야 합니다. Universal로 합치기 전에 x64와 ARM64 결과물을 각각 검증하면 원인을 찾기 쉽습니다.

인증서와 계정을 준비합니다

웹사이트에서 직접 macOS 앱을 배포하려면 일반적으로 Apple Developer Program 계정과 Developer ID Application 인증서가 필요합니다. Mac App Store에 배포하는 경우에는 인증서와 샌드박스, 권한 설정이 달라지므로 별도의 배포 경로로 봐야 합니다.

CI에서 서명한다면 인증서와 비밀번호, Apple 공증용 인증 정보를 Secret으로 관리해야 합니다. 인증서 파일이나 비밀번호가 저장소와 빌드 로그에 남지 않도록 확인합니다.

앱 전체에 코드 서명을 적용합니다

Electron 앱에는 메인 실행 파일 외에도 Framework와 Helper 앱, 네이티브 라이브러리가 포함됩니다. 최종 .app 파일만 겉에서 서명하는 것으로 끝나지 않고 내부 실행 코드가 올바른 순서로 서명되어야 합니다.

카메라, 마이크, 화면 녹화 같은 운영체제 권한을 사용한다면 Info.plist의 권한 안내 문구와 Entitlements도 준비해야 합니다. 누락된 권한 설명이나 잘못된 Entitlements는 다른 Mac에서 실행하거나 권한을 요청할 때 문제가 됩니다.

Apple 공증을 진행합니다

코드 서명을 마친 앱은 Apple 공증 서비스에 제출합니다. Apple이 앱을 검사한 뒤 성공 결과를 반환하면 공증 결과를 배포 파일에 연결하고 최종 상태를 검증합니다.

일반적인 순서는 다음과 같습니다.

앱 빌드
  → 내부 구성 요소와 앱 번들 서명
  → 공증 제출
  → 공증 결과 확인
  → 공증 티켓 연결
  → DMG 또는 ZIP 생성
  → 최종 파일 검증

Electron 공식 코드 서명 문서도 macOS 외부 배포에서 서명과 공증을 함께 안내합니다. 개발 컴퓨터에서 앱이 실행된다는 사실만으로 배포 준비가 끝났다고 판단하기 어려운 이유입니다.

DMG와 ZIP을 준비합니다

DMG는 사용자가 앱을 Applications 폴더로 옮기기 쉬운 배포 형식입니다. ZIP은 압축 배포뿐 아니라 자동 업데이트 구성에서 필요할 수 있습니다.

DMG가 열리고 앱을 복사할 수 있는지만 확인해서는 충분하지 않습니다. 브라우저로 DMG를 내려받아 설치한 앱과 자동 업데이트가 내려받은 앱을 각각 확인해야 합니다.

다른 Mac에서 Gatekeeper를 확인합니다

직접 빌드한 Mac에는 개발 과정의 신뢰 정보와 기존 파일이 남아 있을 수 있습니다. 가능하면 깨끗한 다른 Mac에서 공개 배포와 같은 경로로 파일을 내려받아 확인합니다.

  • 첫 실행 때 Gatekeeper 경고가 어떻게 표시되는지 확인합니다.
  • Intel과 Apple Silicon에서 각각 실행되는지 확인합니다.
  • 카메라, 마이크, 알림 등의 권한 문구를 확인합니다.
  • DMG에서 Applications 폴더로 복사한 뒤 재실행합니다.
  • 이전 버전에서 최신 버전으로 자동 업데이트되는지 확인합니다.
  • 앱을 재실행한 뒤 설정과 데이터가 유지되는지 확인합니다.

자동 업데이트는 별도 기능으로 다룹니다

Electron의 autoUpdater는 Windows와 macOS 업데이트 흐름을 지원합니다. 다만 새 설치 파일을 서버에 올리는 것만으로 자동 업데이트가 완성되지는 않습니다.

일반적으로 다음 요소가 함께 필요합니다.

  • 현재 버전보다 높은 새 버전의 앱 파일이 있어야 합니다.
  • 운영체제와 배포 형식에 맞는 업데이트 메타데이터가 필요합니다.
  • 업데이트 파일을 내려받을 저장소가 필요합니다.
  • 다운로드한 파일과 코드 서명을 검증해야 합니다.
  • 사용자가 작업 중일 때 재시작 시점을 안내해야 합니다.
  • 다운로드나 설치 실패를 기록하고 다시 시도할 수 있어야 합니다.

Windows와 macOS는 설치 형식과 업데이트 메타데이터가 다를 수 있으므로 플랫폼별 결과물을 따로 관리하는 편이 안전합니다. 공개 GitHub 저장소와 GitHub Releases를 사용한다면 update.electronjs.org도 검토할 수 있습니다. 비공개 제품은 자체 저장소나 업데이트 제공 서비스를 구성해야 합니다.

업데이트 호환성도 놓치기 쉽습니다. 서버 API를 먼저 바꾸면 아직 업데이트하지 않은 데스크톱 앱이 동작하지 않을 수 있습니다. 서버는 일정 기간 이전 앱 버전을 받아들이거나, 지원이 끝난 버전에 명확한 업데이트 안내를 보내야 합니다.

CI에서는 운영체제별 빌드를 분리합니다

Electron 배포 파일은 CI에서 반복해서 생성하는 편이 좋습니다. 일반적인 구성은 다음과 같습니다.

버전 태그 생성
  ├─ Windows Runner
  │    ├─ 테스트
  │    ├─ Windows 패키징
  │    ├─ 코드 서명
  │    └─ 설치 파일 업로드

  └─ macOS Runner
       ├─ 테스트
       ├─ macOS 패키징
       ├─ 코드 서명
       ├─ Apple 공증
       └─ DMG와 ZIP 업로드

macOS 서명과 공증에는 macOS와 Xcode 환경이 필요합니다. Windows도 사용하는 인증서나 클라우드 서명 방식에 맞는 실행 환경을 준비해야 합니다.

릴리스 태그와 앱 내부 버전, 설치 파일 이름, 업데이트 메타데이터의 버전은 하나의 값에서 만들면 불일치를 줄일 수 있습니다. 인증서와 비밀번호는 CI Secret에 보관하고, 로그에 값이 출력되지 않게 해야 합니다.

실제 배포 전에 확인할 목록

구분 확인할 내용
앱 정보 App ID, 제품 이름, 버전이 올바른지 확인합니다
아이콘 Windows와 macOS 결과물에 아이콘이 적용됐는지 확인합니다
패키징 개발용 파일과 비밀 정보가 포함되지 않았는지 확인합니다
네이티브 모듈 운영체제와 아키텍처별로 다시 빌드됐는지 확인합니다
Windows 서명 앱과 설치 파일이 정상적으로 서명됐는지 확인합니다
macOS 서명 Helper와 Framework를 포함해 서명됐는지 확인합니다
macOS 공증 공증 성공과 최종 배포 파일 상태를 확인합니다
신규 설치 깨끗한 환경에서 설치와 첫 실행을 확인합니다
업데이트 이전 버전에서 최신 버전으로 올라가는지 확인합니다
제거 앱 제거 후 사용자 데이터 처리 방식을 확인합니다
장애 대응 업데이트 실패와 서버 장애 때 동작을 확인합니다

개발 중에는 보이지 않던 문제

Electron 배포에서 자주 막히는 부분은 개발 모드에서 확인하기 어렵다는 공통점이 있습니다.

첫 번째는 파일 경로입니다. 패키징 후에는 실행 위치와 리소스 경로가 달라집니다. 개발 디렉터리를 기준으로 만든 상대 경로는 설치된 앱에서 깨질 수 있습니다.

두 번째는 네이티브 모듈입니다. Electron의 ABI와 운영체제, CPU 아키텍처에 맞지 않는 바이너리는 개발 환경에서는 동작하고 특정 배포 파일에서만 실패할 수 있습니다.

세 번째는 버전 정보입니다. 설치 파일과 업데이트 메타데이터의 버전이 다르면 새 버전을 찾지 못하거나 같은 업데이트를 반복해서 시도할 수 있습니다.

마지막은 서명 범위입니다. Windows 설치 파일이나 macOS Helper 가운데 하나라도 서명이 빠지면 최종 앱의 신뢰 검증이 실패할 수 있습니다.

이 과정을 살펴보면 Electron 배포는 실행 파일 생성 작업이 아니라는 점이 분명해집니다. Windows에서는 설치 형식과 서명, 실제 다운로드 환경의 검증이 중요합니다. macOS에서는 아키텍처와 앱 전체의 서명, Apple 공증이 이어집니다. 두 플랫폼 모두 이전 버전에서의 자동 업데이트까지 통과해야 사용자에게 전달할 준비가 끝납니다.

마지막 수정:

공유하실 때는 출처(Duolabs)와 원문 주소를 표시해 주세요.