수정 이력(4건, 최종 수정 2026년 08월 02일)
이 글에 적용한 변경 사항의 기록입니다. 보관해 둔 수정 전 버전은 DOI가 부여된 고정 URL에서 읽을 수 있습니다.
- 글 맨 앞에 「이 글의 지식 맵」 절을 추가했습니다. 본문에서 다루는 개념과 그 관계를 요약·그림·상세 페이지 링크로 정리한 것입니다. 본문의 주장은 바꾸지 않았습니다.
- 외부 리뷰(1283건)를 반영해 본문을 업데이트했습니다. 개별 변경 내용은 아래 이력을 참조하세요.
- Visual Studio 게시 절차를 마법사의 각 페이지 이름에 맞춰 풀어 썼습니다. 대상 독자와 per-user·bootstrapper·deploymentProvider 등의 용어 설명도 추가했습니다.
- 본문의 관련 글 링크 문구가 링크 대상의 현재 제목과 어긋나 있던 것을 실제 제목에 맞췄습니다. 본문 내용은 바꾸지 않았습니다.
- 최초 공개
이 글을 인용하기(DOI: 10.5281/zenodo.21635252)
이 글은 Zenodo에 보관되어 있습니다. 항상 최신 버전으로 연결되는 DOI와 지금 보고 있는 버전에 고정된 DOI를 아래에 함께 제시합니다.
고무라 고 (2026). 「ClickOnce란 무엇인가 - 동작 방식, 업데이트, 적합한 경우와 그렇지 않은 경우를 실무 관점에서 정리」. 합동회사 코무라소프트. https://doi.org/10.5281/zenodo.21635252 https://comcomponent.com/ko/blog/clickonce-what-is/
- DOI(최신 버전)
- 10.5281/zenodo.21635252
- DOI(이 버전)
- 10.5281/zenodo.21635253
Windows의 .NET 데스크톱 앱을 배포하는 이야기가 나오면, MSI나 MSIX에 가려 여러 번 이름이 나오는 것이 ClickOnce입니다.
다만 여기서 거칠게
- 오래된 기술이니 이제 쓰지 않는다
- 반대로, 쉬워 보이니 무엇이든 ClickOnce로 가면 된다
어느 쪽으로 기울여도 대개 빗나갑니다.
ClickOnce는 무엇이든 되는 만능 installer가 아닙니다. 한편, 사내 .NET 업무 앱을 표준 사용자에게 배포하고, 업데이트까지 저비용으로 돌리고 싶을 때는 지금도 상당히 유력합니다.
이 글에서는 ClickOnce가 무엇인지, 어떻게 동작하는지, 무엇이 뛰어나고, 어디서 무리가 생기는지를 Mermaid 다이어그램을 많이 넣으며 실무 관점에서 정리합니다. 내용은 2026년 4월 시점에 확인할 수 있는 Microsoft Learn 정보를 주된 전제로 합니다.
그림은 개념도입니다. Mermaid를 지원하는 Markdown 환경에서는 다이어그램으로 표시됩니다.
대상 독자
.NET Windows 데스크톱 앱(WinForms / WPF)을 어떻게 배포할지 검토하는 개발자와 그 배포와 업데이트를 운영하는 정보시스템 담당자를 대상으로 합니다. ClickOnce를 쓸지 아직 정하지 않은 단계를 가정하므로, 먼저 판단 재료를 늘어놓고 실제 게시 절차는 6.4에 두었습니다.
먼저 알아 둘 용어
본문에는 영어 그대로 나오는 용어가 몇 가지 있습니다. 처음 나올 때 막히지 않도록 먼저 정리합니다.
| 용어 | 의미 |
|---|---|
| per-user (이용자 단위) | 이용자마다 설치하는 방식입니다. 해당 사용자의 프로필 아래로 들어가며, 같은 단말의 다른 사용자에게는 보이지 않습니다. 관리자 권한 없이 설치되는 경우가 많습니다 |
| machine-wide (단말 단위) | 단말에 하나만 설치하고 모든 사용자가 같은 실체를 쓰는 방식입니다. Program Files 같은 공유 영역으로 들어가므로, 설치에는 보통 관리자 권한이 필요합니다 |
| bootstrapper | 앱 본체보다 먼저, 필요한 런타임이나 재배포 가능 패키지 같은 전제 조건을 확인하고 설치하는 작은 설치 프로그램입니다. ClickOnce에서는 setup.exe가 이에 해당합니다 |
| file patching | 업데이트할 때 새 버전 파일을 모두 다시 받는 것이 아니라, 이전 버전과 비교해 바뀐 파일만 가져오는 방식입니다 |
| deploymentProvider | 배포 매니페스트에 적히는, 업데이트를 어디서 가져올지를 가리키는 위치입니다. URL 또는 UNC 경로이며, 이미 설치된 클라이언트는 이곳을 계속 봅니다 |
| package identity | MSIX 같은 패키지가 갖는, Windows가 인식하는 고유 식별자입니다. 이름, 버전, 아키텍처, ResourceId, 게시자로 이루어진 5개 쌍으로 구성되며, 이를 전제로 하는 Windows 기능이 있습니다. ClickOnce로 배포한 앱은 이것을 갖지 않습니다 |
| DLL Hell | 공유된 DLL을 다른 앱이 덮어쓰거나 다른 버전으로 바꿔, 그때까지 동작하던 앱이 깨지는 Windows의 고전적인 문제입니다 |
목차
- 먼저 결론
- ClickOnce란 무엇인가
- ClickOnce를 구성하는 것
- 설치부터 시작까지의 흐름
- 업데이트 구조
- ClickOnce가 뛰어난 점
- 적합한 경우
- 맞지 않는 경우
- 실무에서 빠지기 쉬운 점
- 정리
- 관련 글
- 참고 자료
이 글의 지식 맵
ClickOnce는 배포 매니페스트와 애플리케이션 매니페스트를 중심으로 배포·업데이트·캐시 관리를 한꺼번에 다루는 .NET Windows 데스크톱 앱의 배포 모델입니다. per-user 배포로 표준 사용자에게 관리자 권한 없이 배포할 수 있고, file patching으로 변경분만 가져오며, 앱별·사용자별·버전별로 분리된 ClickOnce 캐시 덕분에 DLL Hell을 피하기 쉽습니다. 반면 machine-wide install이나 Windows service·driver 같은 OS 통합, package identity가 필요한 요건에는 맞지 않으므로 MSI나 MSIX부터 검토해야 합니다. 매니페스트 서명에는 코드 서명 인증서를 사용하며, 배포 위치를 옮길 때는 deploymentProvider 재검토와 재서명이 빠질 수 없습니다.
flowchart LR
accTitle: ClickOnce의 지식 맵
accDescr: ClickOnce가 배포 매니페스트와 애플리케이션 매니페스트를 중심으로 per-user 배포와 file patching에 의한 자동 업데이트를 구현하는 한편, machine-wide install이나 package identity, Windows service가 필요한 요건에서는 MSI나 MSIX 쪽으로 가야 한다는 관계를 보여주는 그림
clickonce["ClickOnce"]
per_user_deployment["per-user 배포(이용자 단위)"]
deployment_manifest["배포 매니페스트(.application)"]
application_manifest["애플리케이션 매니페스트(*.exe.manifest)"]
code_signing_cert["코드 서명 인증서"]
clickonce_cache["ClickOnce 캐시"]
dll_hell["DLL Hell"]
setup_exe_bootstrapper["setup.exe(bootstrapper)"]
file_patching["file patching"]
deployment_provider["deploymentProvider"]
machine_wide_install["machine-wide install(단말 단위)"]
msi["MSI(Windows Installer)"]
admin_rights["관리자 권한"]
msix["MSIX"]
package_identity["package identity"]
windows_service["Windows 서비스"]
publish_tool["Publish tool"]
dotnet[".NET(Core 이후)"]
dotnet_mage["dotnet-mage.exe"]
application_deployment_api["ApplicationDeployment API"]
dotnet_framework[".NET Framework"]
pubxml["게시 프로필(.pubxml)"]
offline_availability["오프라인 사용 가능 구성"]
application_settings_migration["애플리케이션 설정 이전"]
self_signed_cert["임시 자체 서명 인증서"]
clickonce -->|"이용한다"| deployment_manifest
deployment_manifest -->|"이용한다"| application_manifest
application_manifest -.->|"에서 구성할 수 있다"| code_signing_cert
deployment_manifest -.->|"에서 구성할 수 있다"| code_signing_cert
clickonce -->|"이용한다"| clickonce_cache
clickonce_cache -->|"완화한다"| dll_hell
setup_exe_bootstrapper -->|"보다 먼저 해야 한다"| deployment_manifest
clickonce -->|"이용한다"| file_patching
clickonce -.->|"전제로 한다"| deployment_provider
per_user_deployment -->|"양립하지 않는다"| machine_wide_install
clickonce -->|"권장되는 대응"| per_user_deployment
msi -->|"권장되는 대응"| machine_wide_install
machine_wide_install -.->|"전제로 한다"| admin_rights
msix -->|"권장되는 대응"| package_identity
clickonce -->|"사용은 비권장"| package_identity
clickonce -->|"사용은 비권장"| windows_service
publish_tool -->|"구현을 담당한다"| clickonce
publish_tool -.->|"전제로 한다"| dotnet
dotnet_mage -->|"구현을 담당한다"| deployment_manifest
application_deployment_api -->|"양립하지 않는다"| dotnet
application_deployment_api -->|"전제로 한다"| dotnet_framework
publish_tool -->|"이용한다"| pubxml
offline_availability -.->|"전제로 한다"| deployment_provider
clickonce -.->|"자동화한다"| application_settings_migration
self_signed_cert -->|"사용은 비권장"| clickonce
그림의 실선은 항상 성립하는 관계, 점선은 조건이 붙는 관계입니다(성립 조건은 상세 페이지의 관계별 설명에 적혀 있습니다). 관계 전체 목록(총 25건, 근거와 확신도 포함)과 주요 개념의 정의는 지식 맵 상세 페이지에 정리되어 있습니다(일본어). 데이터: JSON-LD / Turtle
1. 먼저 결론
ClickOnce를 한 줄로 말하면, .NET Windows 데스크톱 앱을 이용자 단위로 간단히 배포하고, 자동 업데이트까지 포함해 운영하기 위한 배포 기술입니다.
맞는 경우는 예를 들어 다음과 같습니다.
- WinForms / WPF 같은 사내 업무 앱
- 표준 사용자로 설치하고 싶다
- per-user 배포로 충분하다
- 업데이트를 built-in으로 갖고 싶다
- 배포 경로가 웹 사이트나 파일 공유면 된다
반대로, 이런 요건이라면 처음부터 다른 방식을 보는 편이 안전합니다.
- 모든 사용자 대상 machine-wide install
- Windows service, driver, in-process shell extension, 복잡한 COM 등록
- package identity가 필요
- 업데이트 채널, 단계적 배포, 자체 rollback UX까지 쥐고 싶다
- installer로서 OS에 깊게 들어가는 책임이 크다
요컨대 ClickOnce는 간단한 배포와 간단한 업데이트에는 강하지만, OS 통합이 무거운 경우에는 맞지 않는 방식입니다.
먼저 위치를 한 장으로 본다
flowchart TD
A["Windows 앱을 배포하고 싶다"]
B{"OS에 깊게 통합하는 요건이 있는가"}
C["MSI / MSIX 쪽에서 생각한다"]
D{".NET Windows 데스크톱 앱이고<br/>per-user 배포로 충분한가"}
E{"표준 사용자에게 배포하고 싶은가"}
F{"built-in 업데이트로 충분한가"}
G["ClickOnce가 유력"]
H["xcopy / 자체 updater도 비교"]
A --> B
B -- 예 --> C
B -- 아니오 --> D
D -- 아니오 --> H
D -- 예 --> E
E -- 아니오 --> H
E -- 예 --> F
F -- 예 --> G
F -- 아니오 --> H
2. ClickOnce란 무엇인가
ClickOnce는 Microsoft의 Windows 앱 배포 기술입니다. 공식 설명은 최소한의 사용자 조작으로 설치·실행할 수 있고, 스스로 업데이트할 수 있는 Windows 기반 앱의 배포 기술입니다.
여기서 중요한 것은 ClickOnce를 단순한 「installer의 한 종류」로 보지 않는 것입니다.
실제로는 ClickOnce가 다음을 한꺼번에 맡는 배포 모델입니다.
- 어떤 버전을 배포할지
- 그 버전에 어떤 파일이 포함되는지
- 업데이트를 어떻게 감지할지
- 업데이트를 어디서 가져올지
- 이용자별 안전한 장소에 어떻게 유지할지
- 시작 시 무결성을 어떻게 확인할지
ClickOnce의 본체는 setup.exe 자체가 아니라, 매니페스트를 중심으로 배포·업데이트·캐시 관리를 한꺼번에 다루는 구조로 보는 편이 본질에 가깝습니다.
현재의 .NET에서도 ClickOnce 자체는 일반적인 후보입니다. Visual Studio에서는 .NET Core 3.1과 .NET 5 이후를 대상으로 Publish tool을 쓰고, 매니페스트를 수동으로 다룰 때는 dotnet-mage.exe를 사용하는 형태입니다.
ClickOnce가 맡는 책임
flowchart LR
CO["ClickOnce"]
V["어떤 버전을 배포할지"]
U["업데이트를 어디서 가져올지"]
S["이용자별 안전한 장소에 유지"]
I["무결성을 확인하고 시작"]
CO --> V
CO --> U
CO --> S
CO --> I
3. ClickOnce를 구성하는 것
ClickOnce 구조를 이해하려면 다음 네 가지를 잡는 것이 지름길입니다.
| 요소 | 역할 |
|---|---|
배포 매니페스트 (.application) |
지금 배포해야 할 버전, 업데이트 위치, 업데이트 방법 등을 나타냅니다 |
애플리케이션 매니페스트 (*.exe.manifest) |
그 버전의 앱 본체, 의존 파일, 해시, 진입점 등을 나타냅니다 |
| 애플리케이션 파일 | exe, dll, config, 데이터 파일 등 |
setup.exe(선택) |
전제 조건을 확인하고 설치하는 bootstrapper입니다. 필요한 런타임이나 의존 항목이 있을 때 씁니다 |
여기서 핵심은 두 종류의 매니페스트입니다.
- 배포 매니페스트는 「이 앱의 지금 정답은 어느 버전인가」를 나타냅니다
- 애플리케이션 매니페스트는 「그 버전의 내용은 무엇인가」를 나타냅니다
즉 ClickOnce의 업데이트 판정은 먼저 배포 매니페스트에서 시작하고, 실제로 무엇을 받을지는 애플리케이션 매니페스트가 쥐고 있습니다.
네 요소의 관계
flowchart LR
Setup["setup.exe<br/>선택<br/>전제 조건 확인 / 설치"]
Deploy["배포 매니페스트 (.application)<br/>어떤 버전을 배포할지<br/>업데이트 위치 / 업데이트 조건"]
App["애플리케이션 매니페스트 (*.exe.manifest)<br/>그 버전의 내용<br/>파일 목록 / 해시 / 진입점"]
Files["앱 본체<br/>exe / dll / config / data"]
Cache["ClickOnce 캐시<br/>per-user / per-application"]
Setup --> Deploy
Deploy --> App
App --> Files
Files --> Cache
setup.exe는 주역이 아니라 보조
setup.exe는 눈에 잘 띄지만 ClickOnce의 주역이 아닙니다.
이것은 전제 조건을 확인하고 설치하는 보조 역할입니다.
예를 들어 올바른 .NET 런타임이나 추가 재배포 구성 요소가 필요할 때는 setup.exe가 먼저 그것을 맞춘 뒤, ClickOnce 본체의 배포로 들어갑니다.
4. 설치부터 시작까지의 흐름
ClickOnce의 흐름을 실무용으로 과감히 단순화하면 다음과 같습니다.
- 사용자가 웹 페이지나 파일 공유의
setup.exe또는.application을 엽니다 setup.exe를 쓰는 구성이라면 전제 조건을 확인하고 부족한 것을 넣습니다- ClickOnce가 배포 매니페스트를 읽습니다
- 배포 매니페스트가 가리키는 애플리케이션 매니페스트를 읽습니다
- 필요한 파일을 가져와 이용자별 ClickOnce 캐시에 배치합니다
- 오프라인 사용 있음 구성이면 시작 메뉴나 앱 목록에 등록합니다
- 이후에는 ClickOnce 관리 아래에서 앱을 시작합니다
핵심은 Program Files에 보통의 installer처럼 두는 발상이 아니다는 점입니다.
ClickOnce 앱은 이용자별 안전한 캐시 영역으로 들어가며, 앱별·이용자별로 분리됩니다. 여기가 ClickOnce의 큰 특징입니다.
설치부터 첫 시작까지
sequenceDiagram
participant U as 이용자
participant P as setup.exe / .application
participant D as 배포 매니페스트
participant A as 애플리케이션 매니페스트
participant C as ClickOnce 캐시
participant X as 앱 본체
U->>P: 연다
Note over U,P: setup.exe를 쓰는 구성에서는<br/>전제 조건 확인이 먼저 들어갑니다
P->>D: 가져와 읽는다
D->>A: 대상 버전을 참조한다
A->>C: 필요 파일을 가져와 무결성을 확인한다
C->>X: 배치하고 시작한다
온라인 전용과 오프라인 사용 있음
ClickOnce에는 크게 두 가지 형태가 있습니다.
- 온라인 전용: 공개 위치를 기점으로 실행하는 형태입니다. 고정 설치처럼 느껴지지는 않습니다
- 오프라인 사용 있음: 이용자 단말에 설치되어 시작 메뉴에서도 시작할 수 있는 형태입니다
사내 업무 앱에서는 실무상 오프라인 사용 있음을 고르는 경우가 많습니다.
flowchart LR
subgraph Online[온라인 전용]
O1["공개 위치를 기점으로 시작"]
O2["고정 설치처럼 느껴지지는 않는다"]
O3["네트워크가 전제가 되기 쉽다"]
O1 --> O2 --> O3
end
subgraph Offline[오프라인 사용 있음]
F1["사용자 영역에 설치"]
F2["시작 메뉴 등록"]
F3["로컬에서 시작"]
F4["지정 시점에 업데이트 확인"]
F1 --> F2 --> F3 --> F4
end
5. 업데이트 구조
ClickOnce에서 가장 알기 쉬운 강점은 역시 업데이트 모델이 built-in이라는 점입니다.
업데이트 판정은 배포 매니페스트에서 시작한다
ClickOnce 앱은 배포 매니페스트를 읽어
- 새 버전이 있는지
- 필수 업데이트인지
- 어디서 가져올지
를 확인합니다.
이어서 업데이트가 시작되면 ClickOnce는 file patching을 써서 불필요한 재다운로드를 피합니다. 감각으로는 새 버전의 애플리케이션 매니페스트와 현재 버전을 비교해, 바뀐 파일만 가지러 간다고 두면 실무에서 이해하기 쉽습니다.
업데이트 확인의 생각 방식은 다음 세 패턴으로 정리하면 알기 쉽습니다.
- 시작 전에 확인한다
- 시작 후에 확인한다
- 앱 쪽에 「업데이트 확인」 UI를 마련한다
다만 .NET Framework와 .NET 5+에서는 쓸 수 있는 API나 설정 UI에 차이가 있습니다. 오래된 ClickOnce 글의 기억만으로 구현에 들어가지 않는 것이 중요합니다.
업데이트 흐름
flowchart TD
Start["앱 시작"]
Check["배포 매니페스트를 확인"]
New{"새 버전이 있는가"}
Run["그대로 시작"]
Get["새 버전의 애플리케이션 매니페스트를 가져온다"]
Compare["파일의 서명 / 해시를 비교"]
Download["바뀐 분만 가져온다"]
Switch["새 버전을 올바른 형태로 만든 뒤 전환"]
Restart["필요하면 다시 시작한 뒤 새 버전으로 실행"]
Start --> Check --> New
New -- 아니오 --> Run
New -- 예 --> Get --> Compare --> Download --> Switch --> Restart
네트워크에 연결되어 있지 않으면 업데이트 확인 없이 그대로 실행된다는 전제도 알아 두면 실무에서 헷갈리기 어렵습니다.
버전은 분리되어 유지된다
ClickOnce는 「지금 파일을 그 자리에서 덮어쓴다」기보다 새 버전을 올바른 형태로 만든 뒤에 전환한다는 발상에 가깝습니다.
게다가 ClickOnce 캐시에는 현재 버전과 이전 버전이 분리되어 유지됩니다. 환경을 더럽히기 어렵고 버전 충돌을 피하기 쉬운 이유 중 하나입니다.
flowchart TB
subgraph UA[이용자A의 ClickOnce 캐시]
APrev["이전 버전"]
ACur["현재 버전"]
AData["설정 / 데이터"]
end
subgraph UB[이용자B의 ClickOnce 캐시]
BPrev["이전 버전"]
BCur["현재 버전"]
BData["설정 / 데이터"]
end
APrev --> ACur
AData --> ACur
BPrev --> BCur
BData --> BCur
여기서의 핵심은 두 가지입니다.
- 다른 사용자와 섞이기 어렵다
- 다른 버전과 충돌하기 어렵다
이른바 DLL Hell을 피하기 쉬운 것은 이 구조가 큽니다.
6. ClickOnce가 뛰어난 점
ClickOnce의 장점은 「쉽게 배포할 수 있다」만이 아닙니다. 실무에서 도움이 되는 점은 대체로 다음과 같습니다.
6.1 표준 사용자에게 배포하기 쉽다
ClickOnce는 per-user 전제의 배포와 궁합이 좋고, 관리자 권한 없이 설치하기 쉽다는 점이 큽니다.
사내 업무 앱에서 흔한 상황은
- 이용자는 표준 사용자
- IT 부서에 매번 설치를 의뢰하고 싶지 않다
- 그래도 업데이트는 멈추고 싶지 않다
는 조건입니다.
이 조건에서 ClickOnce는 상당히 강합니다. 「각 이용자 영역에, 안전하게, 업데이트를 포함해 들어간다」는 전제가 처음부터 맞습니다.
6.2 업데이트를 직접 구현하지 않아도 된다
자동 업데이트를 처음부터 만들면, 보기보다 할 일이 늘어납니다.
- 새 버전 확인
- 다운로드
- 무결성 확인
- 이전 버전과의 전환
- 실패 시 복구
- 업데이트 UI
- updater 자체의 취급
ClickOnce는 이 중 상당 부분을 기존 모델로 갖고 있습니다.
flowchart LR
subgraph Custom[자체 updater가 맡는 책임]
C1["새 버전 감지"]
C2["다운로드"]
C3["무결성 확인"]
C4["전환"]
C5["실패 시 복구"]
C1 --> C2 --> C3 --> C4 --> C5
end
subgraph Click[ClickOnce에 맡길 수 있는 책임]
K1["새 버전 감지"]
K2["가져오기와 검증"]
K3["전환"]
K1 --> K2 --> K3
end
물론 무엇이든 자유롭게 되는 것은 아닙니다. 다만 사내 앱에 필요한 「충분한 업데이트」는 상당히 채우기 쉽습니다.
6.3 앱끼리 충돌하기 어렵다
ClickOnce 앱은 앱별·이용자별·버전별로 분리됩니다.
이 때문에 예전부터 있던
- 공유 구성 요소의 버전 경합
- 어딘가의 DLL을 덮어써서 다른 앱이 깨진다
- 수동 교체로 환경이 더러워진다
같은 사고를 일으키기 어렵습니다.
6.4 Visual Studio에서 게시하기 쉽다
ClickOnce는 Visual Studio의 게시 기능과 궁합이 좋아, 배포까지의 거리가 짧다는 점도 이점입니다.
MSI authoring 같은 다른 난이도로 들어가기 전에,
- 먼저 게시하고
- 먼저 배포하고
- 먼저 업데이트를 돌리고
- 먼저 현장 피드백을 얻는다
는 흐름을 만들기 쉽습니다.
게시의 최소 절차
개념만으로는 거리가 멀므로 실제 조작도 둡니다. .NET Core 3.1 / .NET 5 이후 Windows 데스크톱 앱에서는 예전 Publish Wizard가 아니라 Publish tool을 씁니다. 대상은 Visual Studio 2019 버전 16.8 이후와 Visual Studio 2022입니다. .NET Framework 앱은 다른 마법사여서 절차가 다릅니다.
- 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 「게시」를 고릅니다. 메뉴라면 「빌드」에서 「게시」입니다.
- 이미 게시 프로필이 있으면 「게시」 페이지가 열리므로 「새로 만들기」를 고릅니다.
- 게시 대상 종류를 고르는 페이지에서 「폴더」를 고릅니다.
- 이어지는 「특정 대상」 페이지에서 「ClickOnce」를 고릅니다.
- 게시 경로를 입력하거나 「찾아보기」로 고릅니다. 여기는 빌드 결과물을 내보내는 위치입니다.
- 「설치 위치」 페이지에서 이용자가 어디서 설치할지를 지정합니다. 5의 내보내기 위치와 달라질 수 있다는 점이 처음에 막히기 쉽습니다. 웹 사이트, UNC 공유, CD / DVD / USB 중 하나를 고릅니다.
- 「설정」 페이지에서 오프라인 사용 여부를 정합니다. 오프라인 사용 있음으로 하면 시작 메뉴에 올라가고, 새 버전을 게시했을 때 자동 업데이트됩니다. 기본값에서는 업데이트 원본이 설치 위치와 같습니다. 다른 위치를 업데이트 원본으로 쓰려면 이 페이지의 업데이트 설정에서 지정합니다. 여기서 지정한 위치가 9.6의
deploymentProvider가 됩니다. - 같은 「설정」 페이지 위쪽 링크에서 배포에 넣을 파일(Application Files), 설치할 전제 조건 패키지(Prerequisites), 기타 옵션을 지정할 수 있습니다. 게시 버전과, 게시할 때마다 자동으로 올릴지도 여기입니다.
- 「매니페스트 서명」 페이지에서 매니페스트에 서명할지와 사용할 인증서를 지정합니다. 여기는 9.5의 이야기로 이어집니다.
- 「구성」 페이지에서 빌드 구성과, 프레임워크 종속인지 자체 포함인지, 대상 런타임 식별자를 고릅니다.
- 「완료」로 프로필을 저장하고 「요약」 페이지에서 「게시」를 누르면 빌드와 게시가 실행됩니다. 두 번째부터는 이 페이지의 「게시」만 누르면 됩니다.
실무에서 먼저 알아 둘 점은 다음 두 가지입니다.
- 게시 버전은 ClickOnce 프로필마다 독립입니다. 검증용과 운영용으로 프로필을 나누면, 각각의 버전 번호를 의식해 관리해야 합니다.
- Publish tool은
.pubxml이라는 게시 프로필을 만듭니다. 명령줄 MSBuild로 빌드할 때는 이.pubxml을 지정합니다. CI에 올릴 때의 입구는 여기입니다.
6.5 설정 이어받기도 비교적 수월하다
기본 애플리케이션 설정 공급자를 쓰는 경우, ClickOnce는 업데이트 시 이전 버전 설정을 새 버전으로 병합하는 구조를 갖고 있습니다.
다만 여기는 기본 설정 공급자 전제입니다. 자체 설정 저장이나 자체 공급자, 저장 위치 변경까지 들어가면 당연히 그대로는 끝나지 않습니다.
7. 적합한 경우
ClickOnce가 특히 맞는 것은 대체로 다음 같은 경우입니다.
| 상황 | ClickOnce와 궁합이 좋은 이유 |
|---|---|
| 사내 WinForms / WPF 업무 앱 | 표준 사용자 배포와 자동 업데이트가 맞물립니다 |
| 이용자 단위 설치면 충분하다 | per-user 배포가 자연스럽습니다 |
| 웹 사이트나 UNC 공유로 배포하고 싶다 | 배포 경로가 단순합니다 |
| 업데이트 빈도가 월 단위~주 단위 정도 | built-in 업데이트로 충분히 돌리기 쉽습니다 |
| 업데이트 UI를 제품 가치로 만들고 싶지 않다 | 기존 업데이트 모델을 쓸 수 있습니다 |
실무에서 궁합이 좋은 구체 예를 들면 이 정도입니다.
- 사내 업무 입력 앱
- 견적·수발주·재고 같은 데스크톱 업무 도구
- 장치 설정용 보조 앱
- 영업소·공장·백오피스에 배포하는 사내 전용 클라이언트
- 업데이트는 필요하지만 전용 updater를 만들 정도는 아닌 앱
이런 앱에서는 배포와 업데이트를 단순하게 하는 것 자체가 가치입니다. ClickOnce는 그 가치에 잘 부응합니다.
맞는지 여부의 판단 트리
flowchart TD
S["요건을 정리한다"]
Q1{"WinForms / WPF 같은<br/>.NET 데스크톱 앱인가"}
Q2{"per-user 배포로 충분한가"}
Q3{"표준 사용자에 넣고 싶은가"}
Q4{"웹 / 파일 공유로 배포할 수 있는가"}
Q5{"업데이트 UX를 너무 만들지 않아도 되는가"}
G["ClickOnce가 상당히 유력"]
O["다른 방식을 비교"]
S --> Q1
Q1 -- 아니오 --> O
Q1 -- 예 --> Q2
Q2 -- 아니오 --> O
Q2 -- 예 --> Q3
Q3 -- 아니오 --> O
Q3 -- 예 --> Q4
Q4 -- 아니오 --> O
Q4 -- 예 --> Q5
Q5 -- 예 --> G
Q5 -- 아니오 --> O
8. 맞지 않는 경우
한편 ClickOnce를 억지로 쓰지 않는 편이 좋은 경우도 분명합니다.
8.1 machine-wide install이 필요하다
ClickOnce는 per-user가 기본입니다.
- 모든 사용자 공통으로 넣고 싶다
Program Files전제로 넣고 싶다- 단말 전체에 설치·관리하고 싶다
라면 ClickOnce가 아니라 MSI 등이 자연스럽습니다.
8.2 Windows service / driver / shell extension / 복잡한 COM 등록
이 근처는 OS에 깊게 손을 대는 이야기입니다.
- Windows service
- driver
- in-process shell extension
- 기계적인 COM 등록을 전제로 하는 구성
까지 들어오면, ClickOnce의 「가볍게 배포하는」 전제에서 벗어납니다.
8.3 package identity가 필요하다
MSIX를 고르는 이유 중 하나에, package identity를 갖고 싶다는 요건이 있습니다.
ClickOnce는 이 방향이 아닙니다. 원하는 것이 modern packaging이나 Windows의 package identity 전제 기능이라면 MSIX를 우선하는 편이 낫습니다.
8.4 업데이트 UX나 배포 채널을 제품으로 쥐고 싶다
예를 들어
- stable / beta / preview 채널
- 단계적 배포
- telemetry를 보면서 롤아웃 비율 조정
- 백그라운드 다운로드의 세밀한 제어
- 자체 rollback 전략
- updater 자체의 복잡한 수명 주기
까지 원하게 되면 ClickOnce의 built-in 업데이트로는 부족해집니다.
8.5 복사해 두기만 하면 되는 운영으로 충분한 도구
반대로, 더 단순해도 되는 경우도 있습니다.
- 폴더째 두면 동작한다
- 업데이트도 수동 교체로 된다
- USB로 건넨다
- 폐쇄망에서 단순함이 최우선이다
라면 xcopy 배포가 마찰이 더 적을 수도 있습니다.
어떤 요건이면 다른 방식으로 기울이는가
flowchart LR
A1["모든 사용자 대상 설치"] --> B1["MSI / 일부 MSIX"]
A2["service / driver / shell extension / 복잡한 COM"] --> B2["MSI / 전용 installer"]
A3["package identity가 필요"] --> B3["MSIX"]
A4["단계적 배포 / 채널 / 자체 UX"] --> B4["자체 updater"]
A5["두기만 하면 충분"] --> B5["xcopy"]
ClickOnce는 더 복잡하거나 더 단순한 쪽 모두에 만능은 아닌 대신, 적당한 복잡도의 경우에 강한 방식입니다.
9. 실무에서 빠지기 쉬운 점
ClickOnce는 편리하지만 대충 들어가면 조금 막힙니다. 특히 다음은 먼저 알아 두면 편합니다.
9.1 「보통의 installer」와 같은 감각으로 보지 않는다
ClickOnce는 고정 설치 위치에 사람이 직접 관리하기 쉬운 형태로 두는 모델이 아닙니다.
실체는 ClickOnce가 관리하는 캐시로 들어가며, 버전마다 분리됩니다. 이 때문에
- 고정 EXE 경로를 전제로 한 운영
- 손으로 직접 덮어쓰는 운영
- 실체 파일 위치를 사람이 쥐는 운영
과는 궁합이 좋지 않습니다.
ClickOnce는 파일 배치를 사람이 관리하는 방식이 아니라, 배포 상태를 매니페스트로 관리하는 방식입니다.
9.2 오래된 ClickOnce 글은 .NET Framework 전제인 것이 많다
여기는 주의가 필요합니다.
지금도 검색 상위에는 .NET Framework 시절 ClickOnce 글이 많이 나옵니다. 다만 지금의 .NET에서는 사정이 조금 다릅니다.
- .NET Core 3.1 / .NET 5 / .NET 6에서는
ApplicationDeploymentAPI를 그대로 쓸 수 없습니다 - .NET 7 이후에는 일부 배포 속성을 환경 변수로 읽을 수 있습니다
- 매니페스트를 수동으로 다룬다면
dotnet-mage.exe가 전제가 됩니다 - Visual Studio 쪽도 예전 Publish Wizard 전제 이야기가 그대로 통하지 않는 경우가 있습니다
「ClickOnce는 안다」고 생각해도, 오래된 기억 그대로 구현하지 않는 편이 안전합니다.
9.3 전제 조건은 따로 생각한다
ClickOnce 자체는 배포 모델이지만, 앱이 동작하려면 전제 조건이 필요할 수 있습니다.
- 대응 런타임
- 추가 재배포 구성 요소
- 그 밖의 의존 항목
이때 setup.exe를 쓰는 bootstrapper 구성이 효력이 있습니다. 반대로 여기를 모호하게 두면 「ClickOnce로 배포했는데 동작하지 않는다」가 일어납니다.
9.4 설정 이어받기는 “무엇을 어떻게 저장하는지”에 달렸다
기본 설정 공급자라면 업데이트 시 설정 이전은 비교적 수월합니다. 다만
- 자체 설정 공급자
- roaming 전제
- 설정 저장 위치를 직접 바꾸고 있다
- 버전 차이로 설정 구조를 크게 바꾸고 있다
라면 당연히 그대로는 끝나지 않습니다.
9.5 서명과 업데이트 경로를 가볍게 보지 않는다
ClickOnce는 배포와 업데이트 구조를 갖고 있지만, 그렇다고 보안 책임이 사라지는 것은 아닙니다.
특히 운영에서는
- 서명 인증서를 어떻게 관리할지
- 게시자 이름을 어떻게 보여 줄지
- 업데이트 원본을 어떻게 관리할지
- 테스트용 자체 서명과 운영 서명을 어떻게 나눌지
를 처음에 정리하는 편이 낫습니다.
flowchart TD
Cert["코드 서명 인증서"]
AppMan["애플리케이션 매니페스트"]
DepMan["배포 매니페스트"]
Verify["클라이언트 쪽에서 검증"]
Run["업데이트 / 실행"]
Tamper["매니페스트 변조"]
Stop["검증 실패로 멈춘다"]
Cert --> AppMan
Cert --> DepMan
AppMan --> Verify
DepMan --> Verify
Verify --> Run
Tamper -. 검증 실패 .-> Stop
「자동 업데이트가 있다 = 안심」이 아니라, 무엇을 신뢰하고 그 신뢰를 어떻게 유지할지는 따로 생각해야 합니다.
9.6 배포 위치를 옮긴다면 deploymentProvider를 다시 본다
이것은 눈에 띄지 않지만 실무에서는 상당히 막힙니다.
이미 설치된 ClickOnce 앱은 배포 매니페스트 안의 deploymentProvider가 가리키는 위치를 업데이트 원본으로 보러 갑니다.
즉 공개 폴더를 통째로 다른 URL이나 다른 공유로 복사해도, deploymentProvider를 갱신하지 않으면 클라이언트는 원래 위치를 계속 보는 경우가 있습니다.
그리고 매니페스트를 손으로 바꿨다면 재서명이 필요합니다.
게시부터 업데이트 반영까지의 운영 흐름
flowchart TD
Build["빌드"]
AppManifest["새 애플리케이션 매니페스트 생성"]
SignApp["애플리케이션 매니페스트에 서명"]
UpdateDep["배포 매니페스트를 새 버전으로 갱신"]
SignDep["배포 매니페스트에 서명"]
Publish["공개 위치에 배치"]
Client["클라이언트가 업데이트를 감지"]
Build --> AppManifest --> SignApp --> UpdateDep --> SignDep --> Publish --> Client
결국 ClickOnce 운영에서 중요한 것은 파일을 두었는지보다 매니페스트와 서명의 정합성이 맞는지입니다.
10. 정리
ClickOnce는 한 줄로 말하면
.NET Windows 데스크톱 앱을 per-user로 간단히 배포하고, 업데이트까지 저비용으로 돌리기 위한 구조
입니다.
뛰어난 점은 주로 다음입니다.
- 표준 사용자에게 배포하기 쉽다
- built-in 업데이트 모델이 있다
- 변경분만 업데이트하기 쉽다
- 앱과 버전을 분리하기 쉽다
- Visual Studio에서 게시하기 쉽다
- 사내 업무 앱과 궁합이 좋다
다만 만능은 아닙니다.
- machine-wide install
- service / driver / shell extension
- 복잡한 COM 등록
- package identity
- 자체 채널이나 단계적 배포
- 업데이트 UX를 제품 가치로 만든다
같은 요건이 있다면 ClickOnce가 아니라 MSI / MSIX / 자체 updater 쪽에서 검토해야 합니다.
ClickOnce는 무엇이든 들어가는 간이 installer는 아니지만, 맞는 경우에는 지금도 상당히 강합니다.
배포하고 싶은 것이
- .NET Windows 업무 앱이고
- 이용자 단위 설치면 충분하고
- 표준 사용자에게 배포하고 싶고
- 업데이트를 직접 갖고 싶지 않다
라면 ClickOnce는 상당히 유력한 후보에 들어갑니다.
11. 관련 글
- Windows 앱 배포 방식 고르기 - MSI/MSIX/ClickOnce/xcopy/자체 업데이트
- 자동 업데이트의 보안 설계 - HTTPS만으로는 부족한 이유
- Windows에서 관리자 권한이 필요해지는 때는 언제인가 - UAC, 보호 영역, 설계상의 구별
관련 토픽
이 주제와 가까운 토픽 페이지입니다. 글을 출발점으로 관련 서비스나 다른 글로 이어집니다.
Windows 기술 토픽
Windows 개발, 장애 조사, 기존 자산 활용의 기술 토픽을 모은 입구입니다.
이 주제가 이어지는 서비스
이 글은 다음 서비스 페이지로 이어집니다. 가까운 입구부터 보시기 바랍니다.
Windows 앱 개발
사내 업무 앱, 장치 설정 도구, 기존 소프트웨어 수정 등에서 ClickOnce / MSI / MSIX / xcopy 중 어느 쪽이 마찰이 가장 적은지는, 구현 전 정리에서 상당히 달라집니다.
기술 상담·설계 리뷰
「ClickOnce로 충분한가」「MSIX나 MSI로 기울여야 하는가」「자동 업데이트를 built-in으로 끝낼 것인가, 직접 가질 것인가」 같은 구분은 구현 전에 정리하면 판단하기 쉬워집니다.
저자 프로필
고무라 고
합동회사 고무라소프트 대표
Windows 소프트웨어 개발, 기술 상담, 장애 조사를 중심으로, 기존 자산이 남는 경우나 원인이 잘 보이지 않는 장애 조사에 강점이 있습니다.
12. 참고 자료
- Microsoft Learn - ClickOnce deployment and security
- Microsoft Learn - ClickOnce for .NET on Windows
- Microsoft Learn - Deploy a .NET Windows Desktop app with ClickOnce
- Microsoft Learn - An overview of Package Identity in Windows apps
- Microsoft Learn - How ClickOnce performs application updates
- Microsoft Learn - Choosing a ClickOnce update strategy
- Microsoft Learn - ClickOnce deployment manifest
- Microsoft Learn - ClickOnce application manifest
- Microsoft Learn - ClickOnce cache overview
- Microsoft Learn - ClickOnce and application settings
- Microsoft Learn - Install prerequisites with a ClickOnce application
- Microsoft Learn - ClickOnce and Authenticode
- Microsoft Learn - Security, versioning, and manifest issues in ClickOnce deployments
관련 기사
같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.
Windows 앱 외주·수탁 개발을 의뢰하기 전에 정리할 점
Windows 앱 외주·수탁 개발을 의뢰하기 전에, 기존 소프트웨어 수정, 장치 연동, COM/ActiveX, 배포·업데이트, 유지보수를 정리하는 포인트를 설명합니다.
Windows에서 'Windows에서 PC를 보호했습니다'가 나타나는 이유
Windows 앱을 배포할 때 SmartScreen 경고가 나오는 이유를 코드 서명, EV/OV 인증서, Azure Artifact Signing, MSIX, Microsoft Store, ClickOnce, 사내 배포, App Control까지...
WMI/CIM을 C#·PowerShell에서 쓰기 ── 하드웨어 정보 가져오기·프로세스 모니터링·원격 조회의 실무 가이드
PC 시리얼 번호 조회, 디스크 여유 공간 모니터링, 프로세스 시작 감지의 흔한 답이 WMI/CIM입니다. Get-CimInstance 등 CIM cmdlet 사용법과 구 Get-WmiObject에서의 이전, C#의 System.Managemen...
Windows 앱의 다중 실행 방지 ── 이름 있는 Mutex와 이중 실행 시 활성화
업무용 Windows 앱의 다중 실행 방지를 이름 있는 Mutex로 구현하는 방법을 정리합니다. Global\와 Local\ 차이로 생기는 RDP 환경의 함정, AbandonedMutexException, 기존 인스턴스를 앞으로 가져오기까지 설명...
Windows에서 관리자 권한이 필요한 때는 언제인가 - UAC, 보호 영역, 설계로 구분하는 방법
Windows에서 관리자 권한이 필요한 상황을 UAC, 보호 영역, 서비스, 드라이버, per-user/per-machine 설계 관점에서 실무용으로 정리합니다.
관련 토픽
이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.
Windows 기술 토픽
Windows 개발, 장애 조사, 기존 자산 활용에 관한 KomuraSoft LLC 기사를 모은 토픽 허브입니다.
이 주제와 연결되는 서비스
이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.
Windows 앱 개발
상주 처리, 장비 연동, 운영 로그, 유지 보수 가능한 구조가 필요한 Windows 데스크톱 애플리케이션을 지원합니다.
기술 상담 & 설계 리뷰
설계 방향, 아키텍처 경계, 수명 관리, 기존 Windows 자산 처리 방법을 정리하는 데 도움을 드립니다.
자주 묻는 질문
이 기사 주제에 대해 상담 시 자주 나오는 질문을 모았습니다.
- ClickOnce란 무엇인가요?
- .NET Windows 데스크톱 앱을 이용자 단위로 간단히 배포하고, 자동 업데이트까지 포함해 운영하기 위한 배포 기술입니다. 공식 설명은, 최소한의 사용자 조작으로 설치·실행할 수 있고 스스로 업데이트할 수 있는 Windows 기반 앱의 배포 기술입니다. 실제로는 매니페스트를 중심으로 배포·업데이트·캐시 관리를 한꺼번에 다루는 배포 모델이며, 앱은 이용자별 안전한 캐시 영역에 앱별·이용자별·버전별로 분리되어 유지됩니다.
- ClickOnce는 앞으로도 쓸 수 있나요? 오래된 기술 아닌가요?
- 현재의 .NET에서도 ClickOnce는 일반적인 후보입니다. Visual Studio에서는 .NET Core 3.1과 .NET 5 이후를 대상으로 Publish tool을 쓰고, 매니페스트를 수동으로 다룰 때는 dotnet-mage.exe를 사용하는 형태입니다. 다만 .NET Framework 시절과는 사정이 다릅니다. .NET Core 3.1 / .NET 5 / .NET 6에서는 ApplicationDeployment API를 그대로 쓸 수 없고, .NET 7 이후에는 일부 배포 속성을 환경 변수로 읽습니다. 오래된 글의 기억만으로 구현에 들어가지 않는 편이 안전합니다.
- ClickOnce는 어떤 앱에 맞나요?
- 사내 WinForms / WPF 업무 앱을 표준 사용자에게 관리자 권한 없이 배포하고 싶고, per-user 배포로 충분하며, 업데이트를 built-in으로 갖고 싶을 때 특히 맞습니다. 배포 경로도 웹 사이트나 파일 공유면 됩니다. 반대로 모든 사용자를 대상으로 하는 machine-wide install, Windows service·driver·shell extension·복잡한 COM 등록, package identity가 필요한 요건, 업데이트 채널이나 단계적 배포까지 직접 쥐고 싶은 요건에는 맞지 않으므로 MSI / MSIX / 자체 updater 쪽에서 검토해야 합니다.
- ClickOnce 자동 업데이트는 어떤 구조인가요?
- 업데이트 판정은 배포 매니페스트(.application)에서 시작합니다. 앱은 배포 매니페스트를 읽어 새 버전이 있는지, 필수 업데이트인지, 어디서 가져올지를 확인합니다. 업데이트 시에는 file patching으로 새 버전의 애플리케이션 매니페스트와 현재 버전을 비교해 바뀐 파일만 가져오므로, 불필요한 재다운로드를 피합니다. ClickOnce 캐시에는 현재 버전과 이전 버전이 분리되어 유지되며, 새 버전을 올바른 형태로 만든 뒤에 전환하는 발상입니다. 네트워크에 연결되어 있지 않으면 업데이트 확인 없이 그대로 실행됩니다.