[Trouble Shooting] .NET Agent 배포 파일 220MB → 5MB 최적화: SelfContained 분리와 WiX Burn 번들링
SelfContained 빌드로 220MB였던 Windows Agent MSI를 framework-dependent로 전환하고 WiX Burn 엔진으로 런타임 체크를 분리하여 5MB로 줄인 과정
문제 상황
Windows용 Agent 프로그램을 MSI로 배포하고 있었는데, 설치 파일 크기가 약 220MB였음.
원인은 SelfContained=true 옵션. .NET 런타임 전체를 MSI 안에 포함시키고 있었기 때문.
고객사에 배포할 때 다음 문제가 있었음:
- 다운로드 시간이 오래 걸림
- 사내 네트워크 환경에서 대용량 파일 전송 제한에 걸리는 경우 발생
- 이미 .NET이 설치된 환경에서도 불필요하게 런타임을 중복 포함
환경
- .NET 8 (Windows Desktop Runtime)
- WiX Toolset v4
- 빌드:
dotnet publish+ WiX MSI 패키징 - 구성 요소: Launcher, TrayIcon, Agent Service
원인 분석
.csproj 설정:
1
2
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
SelfContained=true는 .NET 런타임 + 앱 코드를 하나로 묶음. 런타임이 없는 환경에서도 실행 가능하지만, 파일 크기가 200MB 이상으로 불어남.
실제로 Agent 자체 코드는 1~2MB 수준인데, 나머지 전부가 런타임이었음.
해결 방법
1단계: Framework-Dependent로 전환
1
2
3
4
5
6
7
<!-- Before -->
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<!-- After -->
<SelfContained>false</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
PublishSingleFile은 framework-dependent 모드에서도 동작함. 앱 DLL들만 하나로 합쳐주고 .NET 런타임은 포함하지 않음.
이 변경만으로 Agent exe가 1~2MB 수준으로 줄어듦.
적용 대상:
Launcher.csproj—SelfContained=falseAgentTray.csproj— 동일 적용
2단계: 불필요한 컴포넌트 제거
기존 구조에는 Launcher, TrayIcon이 포함되어 있었는데, 실제 서비스 운영에서는 Agent Service만 필요했음.
- Launcher: 제거
- TrayIcon: 제거
- Agent Service 컨테이너만 분리하여 독립 실행 가능하도록 변경
3단계: WiX Burn 엔진으로 런타임 체크 추가
SelfContained=false로 바꾸면 대상 PC에 .NET 런타임이 설치되어 있어야 함. 이를 자동으로 처리하기 위해 WiX의 Burn 엔진을 도입함.
1
2
wix extension add WixToolset.Bal.wixext
wix extension add WixToolset.Netfx.wixext
Burn Bundle이 하는 일:
- .NET 8 Desktop Runtime 설치 여부 체크
- 없으면 설치 안내 (installer를 번들에 포함하거나 다운로드)
- 사용자가 설치를 거부하면 Agent 설치 취소
- 런타임 확인 후 기존 MSI 실행
빌드 변경
1
2
3
4
5
6
7
8
# Before: MSI 하나로 끝
dotnet publish -c Release
wix build Agent.wxs -o Agent.msi
# After: MSI + Burn Bundle
dotnet publish -c Release --self-contained false
wix build Agent.wxs -o Agent.msi
wix build Bundle.wxs -o AgentSetup.exe # Burn Bundle
최종 산출물이 Agent.msi → AgentSetup.exe (Burn Bundle)로 변경됨.
결과
| 항목 | Before | After |
|---|---|---|
| 설치 파일 크기 | ~220MB | ~5MB |
| 빌드 방식 | SelfContained MSI | Framework-Dependent + Burn Bundle |
| 런타임 포함 | ✅ 매번 포함 | ❌ 시스템에 위임 |
| 런타임 체크 | 없음 | Burn 엔진이 자동 처리 |
| 불필요 컴포넌트 | Launcher + TrayIcon 포함 | Agent Service만 포함 |
정리
SelfContained=true는 런타임 없는 환경에서 편하지만, 배포 파일 크기가 치명적으로 커짐. 대부분의 엔터프라이즈 환경에서는 .NET 런타임이 이미 설치되어 있거나 설치 가능하므로false가 합리적임.- WiX Burn 엔진은 MSI를 감싸는 부트스트래퍼(Bootstrapper) 역할을 함. 런타임 체크, 선행 설치, 조건부 실행을 하나의 exe로 묶을 수 있음.
- 배포 대상이 명확한 경우(사내 PC, 관리형 환경), framework-dependent + 런타임 사전 배포가 파일 크기와 업데이트 효율 모두에서 유리함.