Wails로 데스크톱 앱 만들기 #6 빌드와 배포 — 플랫폼별 패키징
앱이 완성됐으니 남은 일은 하나입니다. 다른 사람의 컴퓨터에서 실행되는 형태로 만드는 것입니다. 이번 글은 wails build가 만들어 내는 산출물의 구조, 플랫폼별 패키징, 그리고 Wails 배포에서 가장 자주 부딪히는 크로스 컴파일 제약과 그 해법인 CI 매트릭스 빌드를 다룹니다. 시리즈의 마지막 편입니다.
총 8편(본편 6편 + 심화 2편)입니다.
- #1 Wails란 — Go로 만드는 가벼운 데스크톱 앱
- #2 프로젝트 구조와 개발 루프 — wails dev와 바인딩
- #3 Go와 프론트엔드 연결 — 메서드 바인딩과 이벤트
- #4 시스템 통합 — 다이얼로그·메뉴·창 제어
- #5 실전 기능 — 설정 저장과 에러 처리
- #6 빌드와 배포 — 플랫폼별 패키징 ← 이번 글
wails build — 단일 바이너리 #
프로덕션 빌드는 명령 하나입니다.
wails build
# 산출물: build/bin/ 아래이 과정에서 프론트엔드가 프로덕션 모드로 빌드되고, 그 결과물이 Go 바이너리 안에 embed 됩니다. HTML, JS, CSS 가 전부 실행 파일 하나에 들어가므로, 배포물 옆에 자산 폴더를 따로 둘 필요가 없습니다. wails dev의 핫 리로드 서버는 개발 전용이고, 빌드된 앱은 내장 자산만으로 동작합니다.
플랫폼별 산출물 #
빌드를 실행한 OS 에 따라 산출물의 형태가 다릅니다.
| 플랫폼 | 기본 산출물 | 배포 형태 |
|---|---|---|
| Windows | 앱이름.exe | 그대로 전달하거나 NSIS 인스톨러 |
| macOS | 앱이름.app 번들 | dmg 로 감싸거나 zip 전달 |
| Linux | 실행 바이너리 | 그대로 전달, 배포판 패키징은 별도 |
Windows 는 exe 하나로도 배포가 되지만, 시작 메뉴 등록과 제거 지원까지 갖추려면 인스톨러를 만듭니다. Wails 는 NSIS 인스톨러 생성을 내장 지원합니다.
wails build -nsismacOS 산출물은 .app 번들입니다. 여기서 현실적인 관문이 코드 서명과 공증(notarization)입니다. 서명 없는 앱은 Gatekeeper 경고를 띄우고, 공증까지 마쳐야 다운로드한 사용자가 경고 없이 실행할 수 있습니다. Apple Developer Program 계정(연 99달러)과 codesign, notarytool 절차가 필요하다는 사실까지가 이 시리즈의 범위이고, 개인 배포 단계에서는 zip 전달 + 우클릭 열기 안내로 시작하는 경우도 많습니다.
Linux 는 바이너리가 그대로 나오며, WebKitGTK 라이브러리가 시스템에 있어야 실행됩니다. 배포판 패키지(deb, AppImage 등)로 만드는 것은 별도 도구의 영역입니다.
아이콘과 앱 메타데이터 #
프로젝트의 build/ 디렉터리가 패키징 리소스의 위치입니다. build/appicon.png를 교체하면 빌드 시 각 플랫폼 형식(icns, ico)으로 변환되어 들어가고, build/darwin/Info.plist와 build/windows/ 아래 파일로 플랫폼별 메타데이터를 조정합니다. 앱 이름과 산출물 파일명은 프로젝트 루트의 wails.json에서 관리합니다.
{
"name": "wails-todo",
"outputfilename": "wails-todo",
"frontend:install": "npm install",
"frontend:build": "npm run build"
}크로스 컴파일 제약과 CI 매트릭스 빌드 #
Go 는 크로스 컴파일이 자유로운 언어지만, Wails 앱은 원칙적으로 대상 OS 에서 빌드해야 합니다. 각 플랫폼의 WebView 와 네이티브 코드에 의존하기 때문입니다. macOS 에서 Windows 용을 빌드하는 우회가 일부 있지만, 공식 권장은 플랫폼별 빌드입니다.
세 OS 를 모두 갖추고 있지 않아도 방법이 있습니다. GitHub Actions 의 매트릭스 빌드가 세 플랫폼 러너에서 각각 빌드해 줍니다.
jobs:
build:
strategy:
matrix:
os: [windows-latest, macos-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with: { go-version: stable }
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: go install github.com/wailsapp/wails/v2/cmd/wails@latest
- run: wails build
- uses: actions/upload-artifact@v4
with:
name: app-${{ matrix.os }}
path: build/bin/Linux 러너에서는 WebKitGTK 개발 패키지 설치 스텝이 추가로 필요합니다. 태그를 푸시하면 세 플랫폼 산출물이 릴리스에 첨부되는 구성까지 확장하면, 혼자서도 3 플랫폼 배포가 유지됩니다.
크기와 성능 감각 #
Wails 를 선택한 이유가 숫자로 확인되는 지점입니다. 할 일 앱 수준의 프로젝트라면 산출물은 대략 다음 범위에 들어옵니다.
- Wails — 바이너리 한 자릿수 MB 대(프론트엔드 자산 포함). 런타임에 OS 의 WebView 를 빌려 쓰므로 브라우저 엔진을 담지 않습니다.
- Electron — 같은 앱이라도 Chromium 과 Node.js 를 동봉해 백 MB 대에서 시작합니다.
메모리 사용도 같은 구조적 이유로 가볍습니다. 다만 OS WebView 를 쓴다는 것은 렌더링 엔진이 OS 버전에 따라 달라진다는 뜻이기도 하므로, 아주 새로운 CSS 기능은 대상 OS 의 WebView 버전을 확인하고 쓰는 신중함이 필요합니다.
시리즈 전체 요약 #
여섯 편의 핵심을 한 줄씩 정리합니다.
- #1 Wails 는 Go 백엔드와 웹 프론트엔드를 OS WebView 로 묶는, Electron 보다 가벼운 데스크톱 프레임워크입니다.
- #2 wails dev 가 핫 리로드 개발 루프를 제공하고, 프로젝트는 Go 루트와 frontend 디렉터리로 나뉩니다.
- #3 Go 메서드는 바인딩으로 프론트엔드 함수가 되고, 역방향 통지는 이벤트로 흐릅니다.
- #4 다이얼로그, 메뉴, 창 제어, 클립보드 같은 OS 통합은 runtime 패키지가 담당합니다.
- #5 데이터는 UserConfigDir 에 저장하고, Go 의 error 는 프론트엔드의 거부된 Promise 로 이어집니다.
- #6 빌드는 단일 바이너리로 나오며, 플랫폼별 빌드 제약은 CI 매트릭스로 해결합니다.
마무리 — 그리고 심화 #
웹 기술로 화면을 만들고 Go 로 시스템을 다루는 조합은, 웹 개발 경험이 있는 사람이 데스크톱 앱에 진입하는 가장 완만한 경로 중 하나입니다. 여기까지 따라왔다면 아이디어를 실행 파일로 만들어 전달하는 한 사이클을 완주한 셈입니다.
본편은 여기서 마치고, 심화 두 편이 이어집니다. 본편이 바닐라로 진행한 앞단을 프레임워크로 바꾸는 #7 프론트엔드 프레임워크 붙이기, 그리고 막혔을 때 원인을 찾는 #8 디버깅입니다. 하나의 앱을 배포와 완성도까지 끌고 가는 실전은 Wails 실전 강좌에서 다룹니다.