Windows에서 어디까지 싱글 바이너리로 만들 수 있는가 - 1 EXE로 가능한 범위, Windows 의존이 남는 곳, 배포 전 판단표
· 小村 豪 · Windows, 배포, 싱글 바이너리, .NET, C++, WebView2, WinUI
이 글은 다음 투고에서 시작되었습니다.
Windows에서 「가능하면 1 파일로 배포하고 싶다」는 꽤 평범한 요구입니다. 사내 도구, 장치 연계 도구, 감시 단말, 오프라인 환경, 인스톨러를 가능한 한 피하고 싶은 현장에서는 싱글 바이너리화는 매우 매력적입니다.
다만 이 이야기는 처음에 정리하지 않으면 대체로 도중에 어긋나게 됩니다. Windows에서 말하는 「싱글 바이너리로 하고 싶다」에는 실은 다음 4가지가 섞이기 쉽기 때문입니다.
- 배포물을 1개로 하고 싶다
- .NET이나 Visual C++의 런타임을 사전 설치 불필요로 하고 싶다
- 인스톨러나 관리자 권한 없이 두기만 하면 동작하게 하고 싶다
- 대상 Windows의 차이에 의존하고 싶지 않다
이 4가지는 같지 않습니다. 실무적으로는 이렇게 생각하는 것이 가장 어긋나지 않습니다.
배포물을 1 EXE로 집약하는 것은 꽤 할 수 있다.
하지만 대상 Windows에의 의존을 제로로 하는 것은 불가능하다.
이 글에서는 그 경계선을 Windows 앱의 실무용으로 정리합니다.
1. 먼저 결론
먼저 결론만 정리하면 이렇습니다.
- 일반적인 데스크톱 EXE라면 꽤 높은 곳까지 single binary화할 수 있습니다
- 다만 1 EXE로 할 수 있는 것과 대상 Windows에 의존하지 않는 것은 별개입니다
- Shell 확장, Windows 서비스, 드라이버, WebView2, WinUI 3의 일부는 파일 수보다 OS에 무엇을 등록하고 무엇을 전제로 하는가가 본론이 되기 쉽습니다
- 실무에서 가장 중요한 것은 single binary화하고 싶은가, 인스톨러 불필요로 하고 싶은가, OS 의존을 줄이고 싶은가를 나누어 정하는 것입니다
바꿔 말하면 Windows에서는 다음 선긋기가 꽤 실무적입니다.
- 배포물을 1개로 집약: 꽤 가능
- 추가 런타임을 끌어안다: 꽤 가능
- xcopy 배포로 집약: 앱 종별에 따름
- 대상 Windows 쪽의 의존을 없앤다: 불가능
2. 「싱글 바이너리」는 4단계로 나누어 생각한다
2.1 레벨 A: 배포물이 1개
가장 표면적인 것은 이것입니다.
- 메일로 1개 보낼 수 있다
- USB에 1개 두면 된다
- 전개처에
app.exe만 둔다
이것은 겉모습의 배포 단위 이야기입니다. 실제로는 기동 시에 임시 전개하고 있어도, OS 측의 DLL에 의존하고 있어도, 이 조건만이라면 충족할 수 있습니다.
2.2 레벨 B: 언어 런타임의 사전 설치가 불필요
다음은 대상 머신에 미리 .NET 런타임이나 VC++ 재배포 가능 패키지를 넣지 않아도 동작하는 상태입니다.
- C/C++의 정적 링크
- .NET의 self-contained
- .NET의 single-file
- .NET Native AOT
이 레벨이 되면 「단독으로 가져갈 수 있다」는 느낌이 꽤 강해집니다.
2.3 레벨 C: 인스톨이나 등록이 불필요
여기서부터 갑자기 어려워집니다.
단순한 EXE라면 두기만 해도 동작할 수 있습니다. 하지만 다음 같은 것은 별개입니다.
- Shell 확장
- Windows 서비스
- 커스텀 URL 스키마나 파일 관련 짓기
- 드라이버
- Explorer나 Office 등 다른 프로세스에 로드되는 컴포넌트
이 영역은 파일을 두기만 해서는 끝나지 않습니다. OS 측의 등록이나 호스트 측과의 연결이 필요합니다.
2.4 레벨 D: 대상 Windows에 의존하지 않는다
이것은 Windows에서는 불가능합니다.
Windows 앱은 최종적으로 Windows의 API, 로더, 보안 모델, 디바이스 스택 위에서 동작하기 때문입니다. single binary화할 수 있는 것은 앱 쪽의 책임 범위까지입니다. OS 자체까지 가지고 가는 것은 아닙니다.
3. 꽤 1 EXE로 하기 쉬운 영역
Windows에서도 다음 같은 앱은 비교적 1 EXE로 집약하기 쉽습니다.
- 단독 기동되는 데스크톱 도구
- EXE 자신이 UI와 처리를 가지는 업무 앱
- 통신, 파일 처리, 로그 수집, 감시, 장치 제어 같은 도구
- Explorer나 Office의 호스트 통합을 필요로 하지 않는 것
- Web 런타임을 전제로 하지 않는 UI
이 타입이라면 앱 본체에 포함하기 쉬운 것이 많습니다.
- 자체 코드
- 리소스
- 매니페스트
- 기정 설정
- 템플릿 데이터
- 일부의 서드파티 라이브러리
- 언어 런타임 본체
더욱이 DLL을 완전히 EXE 안에 매립하지 않더라도, EXE의 옆에 DLL을 두는 app-local 배포는 Windows에서는 평범하게 유력합니다. 실무에서는,
app.exe1개- 또는
app.exe+ 인접 DLL 몇 개 - 다만 인스톨러 불필요, 관리자 권한 불필요, xcopy로 배포 가능
이 형태가 억지로 1 EXE로 압축하는 것보다 유지보수하기 쉬운 경우가 꽤 있습니다.
4. 1 EXE여도 사라지지 않는 Windows 의존
「EXE 1개라면 대상 Windows에 의존하지 않는다」고 생각해 버리면 여기서 사고가 납니다. 실제로는 1 EXE여도 다음 의존은 남습니다.
4.1 OS 버전 의존
Windows API에는 각각 최저 서포트 OS가 있습니다. x64 / Arm64의 차이도 있습니다. 즉 단일 EXE로 해도,
- Windows 10까지 동작하는가
- Windows 11 전제인가
- Windows Server에서도 동작시키는가
- x86 / x64 / Arm64 중 어느 것을 대상으로 하는가
는 먼저 고정할 필요가 있습니다.
4.2 시스템 DLL 의존
이쪽이 1 EXE로 한 셈이라도 실행 시에는 당연히 OS 제공의 컴포넌트를 쓰고 있습니다.
kernel32.dlluser32.dlladvapi32.dll- COM 기반
- 서비스 제어 기반
이쪽은 Windows 측의 책임 범위입니다.
4.3 보안 모델 의존
- UAC
- 파일 ACL
- 서비스 제어 매니저
- 레지스트리
- 드라이버 서명 정책
이런 것들은 앱이 단독으로 끌어안을 수 없습니다.
4.4 호스트나 런타임 의존
단독 기동 EXE가 아니라 어떤 호스트에 올리는 설계라면 의존은 단번에 늘어납니다.
- WebView2를 쓴다: WebView2 Runtime이 필요
- WinUI 3 / Windows App SDK를 쓴다: 배포 모드의 정리가 필요
- Shell 확장을 만든다: Explorer 측으로의 등록이 필요
즉, UI나 통합의 선택이 그대로 배포의 어려움이 된다는 경우가 많습니다.
5. 기술별로 보는 현실적인 타협점
5.1 네이티브 C/C++
네이티브 C/C++는 single binary화의 자유도가 높은 쪽입니다. 정적 링크를 선택할 여지가 있고, 단독 기동 EXE라면 꽤 집약하기 쉽습니다.
다만 전부를 1 파일에 밀어 넣는 것보다,
- UCRT나 VC++ 런타임을 어떻게 할 것인가
- 서드파티 DLL을 app-local에 둘 것인가
- 대상 CPU / OS를 어디까지 좁힐 것인가
쪽이 실무상 중요합니다.
5.2 .NET
.NET은 single-file, self-contained, Native AOT가 있으므로 겉모습의 배포 단위는 꽤 작게 할 수 있습니다.
다만 구별은 필요합니다.
- framework-dependent: 대상 환경의 .NET에 의존
- self-contained: .NET 런타임을 끌어안는다
- single-file: 배포물을 하나로 집약
- Native AOT: 또한 기동 시 의존을 줄이지만 기능 제약도 있다
「single-file이니까 OS 의존이 줄어든다」는 것은 아닙니다. 줄어드는 것은 주로 앱 배포물의 집합입니다.
5.3 WebView2
WebView2를 채택하면 single binary의 어려움은 꽤 바뀝니다. 여기서의 본론은 EXE의 수가 아니라 WebView2 Runtime을 어떻게 다룰 것인가입니다.
올바른 질문은 「1 EXE로 할 수 있는가」보다 다음입니다.
- Runtime을 기존 환경 전제로 할 것인가
- Evergreen을 쓸 것인가
- Fixed Version을 동봉할 것인가
- 오프라인 배포에서 어디까지 책임을 질 것인가
5.4 WinUI 3 / Windows App SDK
WinUI 3도 채택한 시점에서 배포 요건이 바뀝니다. UI 기술의 선택이 그대로 배포 방식의 선택이 됩니다.
single binary를 최우선으로 한다면 먼저 UI 기술의 전제를 다시 보는 편이 빠른 경우가 자주 있습니다.
6. 본질적으로 「등록·의존」이 필요한 영역
6.1 Shell 확장
Explorer에 로드되는 Shell 확장은 단순한 「두기만 하면 되는 EXE」와는 다른 것입니다. 여기는 파일 수보다 Explorer에 어떻게 등록할 것인가가 본론입니다.
6.2 Windows 서비스
서비스 본체의 exe 자체는 1 파일로 할 수 있어도, 배포는 별개 문제입니다.
- SCM에의 등록
- 권한
- 기동 계정
- 복구 설정
을 생각할 필요가 있습니다. 즉 서비스는 「1 EXE로 한다」보다 「어떻게 설치할 것인가」를 파고드는 영역입니다.
6.3 드라이버
드라이버는 더욱 명확합니다. INF, 서명, 설치 절차까지 포함해 성립하므로 single binary의 씨름판에 처음부터 오르기 어렵습니다.
7. 실무에서의 판단표
대략 판단한다면 다음 표가 쓰기 쉽습니다.
| 만들고 싶은 것 | 1 EXE 현실도 | 먼저 생각해야 할 것 |
|---|---|---|
| 단독 기동의 Win32 / C++ 도구 | 높음 | 정적 링크, 대상 OS / arch |
| 단독 기동의 WinForms / WPF 도구 | 높음 | self-contained, single-file, Native AOT의 적성 |
| WinUI 3 / Windows App SDK 앱 | 중 | 배포 모드, 추가 의존 |
| WebView2 기반의 데스크톱 UI | 낮음에서 중 | Runtime의 배포 방식 |
| Explorer 우클릭 확장이나 프리뷰 | 낮음 | COM / 레지스트리 등록 |
| Windows 서비스 | 중 | SCM 등록, 권한, 갱신 절차 |
| 드라이버 동봉 앱 | 낮음 | INF, 서명, 설치 |
이 표에서 가장 중요한 것은 「바이너리의 수」와 「배포의 책임 범위」는 별개라는 것을 알 수 있다는 점입니다.
8. 배포 설계에서 먼저 정해야 할 것
single binary화를 성공시키고 싶다면 구현 전에 다음을 정하는 편이 잘 됩니다.
8.1 무엇을 1개로 하고 싶은가를 정한다
- 배포물을 1개로 하고 싶은가
- 런타임 사전 설치를 없애고 싶은가
- 인스톨러 불필요로 하고 싶은가
- 오프라인 갱신을 간단하게 하고 싶은가
이 답에 따라 고르는 기술이 바뀝니다.
8.2 최저 서포트 Windows와 arch를 먼저 고정한다
single-file도 Native AOT도 기본적으로 OS / architecture specific입니다. 여기를 애매하게 둔 채 「어쨌든 1 파일로」라고 진행하면 마지막에 API 부족이나 runtime 불일치로 막힙니다.
8.3 「동봉할 것」과 「Windows에 맡길 것」을 명문화한다
실무에서는 이 표를 써 두는 것만으로도 꽤 사고가 줄어듭니다.
- 앱에 동봉할 것
- 본체 exe
- 자체 DLL
- 설정 템플릿
- self-contained runtime
- Windows에 맡길 것
- 시스템 DLL
- OS API
- SCM / 레지스트리 / Explorer
- 드라이버 기반
- 별도로 전제하는 것
- WebView2 Runtime
- VC++ Redistributable
- Office / Excel
- 전용 드라이버
8.4 single binary를 우선한다면 호스트 통합을 줄인다
이것은 꽤 효과가 있습니다.
- Shell 확장을 그만두고 일반 EXE로 한다
- 서비스화하지 말고 태스크 스케줄러나 명시 기동으로 끝낸다
- WebView2가 아니라 네이티브 UI를 쓴다
- COM은 자기 프로세스 내에서 닫는다
요컨대 OS에 「로드시키는」, 「등록하는」 설계를 줄이는 만큼 single binary에 가까워집니다.
9. 정리
Windows에서의 single binary화는 꽤 할 수 있는 범위까지 가능합니다. 다만 올바른 이해는 다음 한 문장에 다합니다.
앱을 1 EXE로 할 수 있다.
하지만 그 앱이 의존하는 Windows까지 1 EXE로 할 수는 없다.
특히 기억해 두고 싶은 것은 다음 5점입니다.
- 단독 기동의 일반적인 EXE라면 꽤 1 파일 배포로 집약할 수 있다
- C/C++의 정적 링크, .NET single-file, Native AOT는 유력
- 다만 OS 버전, arch, 시스템 DLL, 보안 모델에의 의존은 사라지지 않는다
- Shell 확장, 서비스, 드라이버, WebView2, WinUI 3의 일부는 OS 등록이나 추가 런타임의 이야기가 본체가 된다
- single binary의 성패는 「무엇을 1개로 하고 싶은가」를 먼저 구분하는 것으로 정해진다
만약 single binary를 강하게 우선한다면 기술 선정 시점에서 OS와의 결합도를 낮추는 방향으로 설계하는 편이 훨씬 성공하기 쉽습니다.
10. 참고 자료
- Microsoft Learn, Create a single file for application deployment
- Microsoft Learn, Native AOT deployment overview
- Microsoft Learn, C runtime (CRT) and C++ standard library (STL) lib files
- Microsoft Learn, Dynamic-link library search order
- Microsoft Learn, Targeting your application for Windows
- Microsoft Learn, Creating Registration-Free COM Objects
- Microsoft Learn, Registering Shell Extension Handlers
- Microsoft Learn, CreateServiceW function
- Microsoft Learn, Overview of INF Files
- Microsoft Learn, Windows driver signing tutorial
- Microsoft Learn, Distribute your app and the WebView2 Runtime
- Microsoft Learn, Windows App SDK deployment guide for self-contained apps
관련 기사
같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.
ClickOnce란 무엇인가 - 구조, 업데이트, 어울리는 장면・어울리지 않는 장면을 실무 시점에서 정리
ClickOnce가 무엇이고 매니페스트, 캐시, 업데이트, 서명이 어떻게 맞물려 동작하는지를 Mermaid 그림과 함께 정리하고, 사내용 .NET 데스크톱 앱 배포에서 어울리는 안건과 어울리지 않는 안건을 실무 시점에서 판단할 수 있도록 도와드립니다.
Windows 앱에서 자식 프로세스를 안전하게 다루기 위한 체크리스트 - Job Object, 종료 전파, 표준 입출력, watchdog의 베스트 프랙티스
Windows 앱이 자식 프로세스에 의존할 때, 기동 API보다 프로세스 트리의 소유권과 종료 절차의 설계가 안정성을 좌우합니다. Job Object로 수명을 묶고, 종료 전파를 분리하며, stdout/stderr를 비동기로 흘리고 watchdo...
Windows의 관리자 특권이 필요해지는 것은 언제인가 - UAC, 보호 영역, 설계상의 구분 방법
Windows에서 관리자 권한이 필요한지는 사용자 직함이 아닌 앱이 건드리는 경계로 정해진다는 관점에서, UAC 동작과 보호 영역, per-user 대 per-machine, 매니페스트와 분리 모델까지 정리하여 불필요한 승격을 줄이는 설계 판단 ...
Windows 앱의 배포 방식을 어떻게 고를까 - MSI / MSIX / ClickOnce / xcopy / 자체 updater의 판단표
Windows 앱의 배포는 MSI/MSIX/ClickOnce/xcopy/자체 updater 가운데 어느 인스톨러가 새로운가가 아니라, OS 통합의 깊이와 갱신 책임을 누가 갖는가로 고르는 결정이라는 관점에서 실무 판단 기준을 정리합니다.
.NET의 Native AOT란 무엇인가 - JIT, ReadyToRun, trimming과의 차이를 먼저 정리
Native AOT가 publish 시점에 .NET 앱을 정적으로 굳히는 배포 모델임을 JIT, ReadyToRun, trimming, source generator와 비교해 정리하고, 어느 앱에 잘 맞고 어디서 막히는지 실무 관점에서 판별 기준...
관련 토픽
이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.
Windows 기술 토픽
Windows 개발, 장애 조사, 기존 자산 활용에 관한 KomuraSoft LLC 기사를 모은 토픽 허브입니다.
이 주제와 연결되는 서비스
이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.
Windows 앱 개발
상주 처리, 장비 연동, 운영 로그, 유지 보수 가능한 구조가 필요한 Windows 데스크톱 애플리케이션을 지원합니다.
저자 프로필
기사 저자의 프로필 페이지입니다.
Go Komura
합동회사 코무라소프트 대표
Windows 소프트웨어 개발, 기술 상담, 장애 조사를 중심으로 재현이 어려운 장애 조사와 기존 자산이 남아 있는 프로젝트에 강점이 있습니다.
공개 링크