Electron 앱 빌드 시간 줄이기 — 30분에서 5분으로
PR마다 빌드 30분은 미친 짓이었다
Electron 앱의 CI/CD 파이프라인을 보면, 빌드 단계에서 30분이 걸렸다. 매 PR마다. 리뷰어들이 코드 리뷰를 기다리는 동안, 빌드는 여전히 진행 중이었다.
병목을 분석하고 최적화했다. 지금은 5분이다. 방법을 공유하겠다.
문제 분석: 뭐가 오래 걸리나
<?xml version="1.0"?>
원래 빌드 시간 분석:
1. npm install: 8분
- node_modules 재생성
- 의존성 다운로드
2. TypeScript 컴파일: 12분
- 전체 코드베이스 컴파일
3. electron-builder: 8분
- Mac 빌드 (3분)
- Windows 빌드 (3분)
- Linux 빌드 (2분)
총합: 28분
최적화 1: npm/pnpm 캐싱
<?xml version="1.0"?>
# GitHub Actions에서
- name: Setup Node with cache
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm' # 또는 'pnpm'
# 이미 설치되어 있으면 node_modules 복원
# 효과: 8분 → 30초 (npm install 스킵)
최적화 2: 선택적 빌드
<?xml version="1.0"?>
# package.json
{
"scripts": {
"build:mac": "electron-builder --mac",
"build:windows": "electron-builder --win",
"build:linux": "electron-builder --linux",
"build:ci": "electron-builder -mwl"
}
}
# GitHub Actions
- name: Build Electron
run: |
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
# 메인 브랜치: 모든 플랫폼 빌드
npm run build:ci
else
# 개발 브랜치: 현재 OS만 빌드
npm run build:${{ runner.os }}
fi
# runner.os = 'Linux', 'Windows', 'macOS' 중 하나
최적화 3: 증분 빌드
<?xml version="1.0"?>
# 전체 컴파일 대신 변경된 파일만 컴파일
# tsconfig.json에 incremental 추가
{
"compilerOptions": {
"incremental": true,
"tsBuildInfoFile": ".tsbuildinfo"
}
}
# GitHub Actions에서 캐싱
- name: Cache TypeScript build info
uses: actions/cache@v3
with:
path: |
.tsbuildinfo
dist/**/*.js
key: ${{ runner.os }}-tsc-${{ hashFiles('src/**/*.ts') }}
restore-keys: |
${{ runner.os }}-tsc-
# 효과: 12분 → 2분 (변경된 파일만 컴파일)
최적화 4: electron-builder 캐싱
<?xml version="1.0"?>
# .github/workflows/build.yml
- name: Cache electron-builder cache
uses: actions/cache@v3
with:
path: |
${{ github.workspace }}/node_modules/.cache
~/.cache/electron
~/Library/Caches/electron
key: ${{ runner.os }}-electron-${{ github.sha }}
restore-keys: |
${{ runner.os }}-electron-
# electron-builder는 캐시된 의존성 사용
# 효과: 8분 → 3분
최적화 5: 병렬 빌드**
<?xml version="1.0"?>
# GitHub Actions matrix로 병렬 빌드
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci
- run: npm run build
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: electron-builds-${{ matrix.os }}
path: dist/
# 3개 플랫폼이 동시에 빌드됨
# 효과: 8분 × 3 → 8분 (병렬화로 총 시간 감소)
최적화 6: 불필요한 파일 제외
<?xml version="1.0"?>
// electron-builder 설정
{
"build": {
"files": [
"dist/**/*",
"node_modules/**/*",
"package.json"
],
"extraMetadata": {
"name": "my-app"
}
},
"files": [
"!src",
"!**/*.map",
"!**/test/**/*",
"!**/node_modules/@types/**/*"
]
}
// .electronbuilderrc
{
"asar": true,
"asarUnpack": ["**/*.node"],
"directories": {
"buildResources": "assets"
}
}
// 효과: 불필요한 파일 제외로 빌드 크기 20% 감소
최적화 7: 코드 분할**
<?xml version="1.0"?>
// webpack 또는 esbuild 설정으로 코드 분할
// 메인 프로세스와 렌더러 프로세스 분리
// main.ts (메인 프로세스)
import { app, BrowserWindow } from 'electron'
// preload.ts (분리된 번들)
import { contextBridge } from 'electron'
// 빌드 결과
dist/
main.js (메인 프로세스)
preload.js (preload 스크립트)
renderer/
index.js (렌더러 번들)
최종 설정 예제
<?xml version="1.0"?>
# .github/workflows/build.yml (최적화 완료 버전)
name: Build
on:
push:
branches: [main, develop]
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
compile:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci
- run: npm run type-check
- run: npm run build:app
- uses: actions/upload-artifact@v3
with:
name: build-app
path: dist/
build:
needs: compile
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: build-app
path: dist/
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Cache electron
uses: actions/cache@v3
with:
path: ~/.cache/electron
key: ${{ runner.os }}-electron-${{ github.sha }}
- run: npm ci --production
- run: npm run electron:build
- uses: actions/upload-artifact@v3
with:
name: release-${{ matrix.os }}
path: release/
성과
- npm install: 8분 → 30초 (캐싱)
- 컴파일: 12분 → 2분 (증분)
- electron-builder: 8분 → 3분 (캐싱)
- 병렬화: 3개 OS × 8분 → 8분
- 총 시간: 28분 → 5분 (82% 감소)
마무리
Electron 빌드 시간 최적화는 모두 일반적인 CI 최적화 원칙이다. 캐싱, 병렬화, 선택적 빌드 — 이 세 가지만 제대로 해도 대부분의 빌드 시간을 줄일 수 있다.
매 PR마다 30분을 기다리는 건 개발 생산성을 크게 해친다. 5분이면 충분하다. 리뷰어도 곧바로 빌드 결과를 볼 수 있고, PR 머지 속도도 빨라진다.