Electron 앱 빌드 시간 줄이기 — 30분에서 5분으로

게시일: 2025년 7월 18일 · 14분 읽기

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/

성과

마무리

Electron 빌드 시간 최적화는 모두 일반적인 CI 최적화 원칙이다. 캐싱, 병렬화, 선택적 빌드 — 이 세 가지만 제대로 해도 대부분의 빌드 시간을 줄일 수 있다.

매 PR마다 30분을 기다리는 건 개발 생산성을 크게 해친다. 5분이면 충분하다. 리뷰어도 곧바로 빌드 결과를 볼 수 있고, PR 머지 속도도 빨라진다.

iL
ian.lab

실무 개발자입니다. 현장에서 겪은 문제와 해결 과정을 기록합니다. 오류 제보는 연락처로 보내주세요.