Windows 네이티브 앱 개발은 혼란스러운 상태
(domenic.me)- Windows용 유틸리티 앱 개발 경험을 통해 네이티브 앱 개발 환경의 복잡성과 비효율성이 드러남
- Win32에서 WinUI 3까지 이어지는 UI 프레임워크의 잦은 세대 교체로 인해 일관된 기술 기반 유지가 어려움
- 최신 Windows App SDK는 필수 기능 미지원, P/Invoke 의존, 불완전한 C# 상호운용성 등으로 실용성이 낮음
- 배포 과정에서도 MSIX 서명 비용, Store 등록 거절, .NET 런타임 의존성 등 현실적 제약이 큼
- 결과적으로 많은 개발자가 Electron·Tauri 같은 웹 기반 프레임워크로 이동하며, Microsoft가 네이티브 개발을 우선하지 않는 상황임
Windows 네이티브 앱 개발의 혼란
-
개인 프로젝트와 문제 인식
-
Windows 전용 유틸리티 앱 ‘Display Blackout’ 개발 과정에서 현재 네이티브 앱 개발 환경의 문제점이 드러남
- 이 앱은 다중 모니터 환경에서 게임 중 좌우 화면을 검은색 오버레이로 끄는 기능을 제공
- 필요한 기능은 디스플레이 열거, 경계 계산, 글로벌 단축키 처리, 트레이 아이콘 표시, 시작 시 자동 실행, 설정 저장 등
- 기존 AutoHotkey 스크립트나 Microsoft Store 앱이 존재하지만, 학습 목적과 UI 개선을 위해 직접 개발을 시도
- 결과적으로 Windows 네이티브 앱 개발 환경이 극도로 복잡하고 비효율적임을 확인
-
Windows 전용 유틸리티 앱 ‘Display Blackout’ 개발 과정에서 현재 네이티브 앱 개발 환경의 문제점이 드러남
Windows 프로그래밍의 역사
- 초기에는 C 기반 Win32 API가 중심이었으며, 이후 MFC가 객체지향적 추상화를 제공
- 2002년 .NET 1.0과 함께 C# 및 Windows Forms가 등장해 메모리 관리와 현대적 언어 기반을 제공
- 2006년 WPF가 도입되어 XAML 기반 UI와 GPU 렌더링을 지원
- 2012년 WinRT, 2015년 UWP로 이어지며 샌드박스형 앱 모델과 Microsoft Store 배포를 목표로 함
- 2021년 Windows App SDK와 WinUI 3이 등장해 WinRT/UWP 기능을 통합했으나 또 다른 API 계층을 추가
- UI 프레임워크의 진화 경로는 다음과 같음 Win32 → MFC → WinForms → WPF → WinRT XAML → UWP XAML → WinUI 3
개발 경로의 갈림길
- WinUI 3 앱 개발에는 C++, C#/XAML (Framework-dependent), C#/XAML (.NET AOT) 세 가지 선택지가 존재
- C++은 성능이 좋지만 메모리 안전성 부족
- Framework-dependent 방식은 Windows에 최신 .NET(10)이 기본 포함되지 않아 사용자 설치가 필요
- .NET AOT는 런타임 전체를 바이너리에 포함, 단순 앱도 9MiB 이상으로 커짐
- Rust 바인딩 프로젝트는 중단된 상태
- 배포는 MSIX 패키징이 권장되지만,
- 코드 서명 인증서 비용(연 $200~300) 이 높고
- 서명 없는 사이드로딩은 PowerShell 명령 필요 등 사용자 경험이 나쁨
- Microsoft Store 등록도 “지속적 가치 부족” 사유로 거절됨
- .NET을 Windows Update로 배포하거나, MSIX 종속 패키지로 제공하는 개선책이 제시됨
- 현재의 Windows 개발 체계는 “절반만 완성된 상태”로 평가됨
누락된 기능과 기술적 단절
- Microsoft가 반복적으로 새로운 API 계층을 도입하고 기존 기능을 폐기하면서 각 세대마다 기능 공백이 발생
- WinUI 3 기반 Windows App SDK의 제약 사항
-
디스플레이 열거는 가능하지만 변경 감지는P/Invoke 필요
-
비활성화 상태의 무테 창 생성도P/Invoke 필요
-
글로벌 단축키 처리는지원되지 않음
- 시작 시 실행과 설정 저장은 가능
- 트레이 아이콘 및 메뉴 표시는 표준 API 부재, 서드파티 래퍼에 의존
- 창 크기 자동 조정 기능도 WPF 이후 사라짐
- Win32 API와의 상호운용을 위한 CsWin32는 미완성 상태
- 문자열 구조체 처리 오류와 C# 언어 한계로 불완전
- C#은 Win32의
[optional, out]매개변수를 표현할 방법이 없음 - C# 언어는 20년간 UI 데이터 바인딩의 반복적 보일러플레이트 문제를 해결하지 못함
-
INotifyPropertyChanged구현이 여전히 번거롭고 언어 차원의 개선 부재
-
결론 및 대안
- 현재 Microsoft는 네이티브 앱 개발을 우선하지 않음
- 관련 이슈 트래커는 버그와 미응답 보고로 가득
- Windows App SDK의 변경 로그는 머신러닝 API 추가 중심
- Visual Studio Code, Outlook, Start 메뉴 등 주요 앱조차 웹 기술 기반으로 작성
- 커뮤니티는 Avalonia, Uno Platform 같은 서드파티 UI 프레임워크로 이동 중
- 이들은 WPF 철학을 계승하고 크로스플랫폼 지원을 강화
- 그러나 현재로서는 Electron이나 Tauri 같은 웹 기반 프레임워크가 더 현실적 선택
- TypeScript/React/CSS 조합이 C#/XAML보다 생산적이며
- Win32 API 접근도 가능
-
Tauri는시스템 WebView를 활용해Chromium 번들 불필요
- WebView2 런타임은 4주마다 업데이트, 반면 시스템 .NET은 4.8.1에 고정
- Microsoft가 Windows App SDK 개선과 배포 체계 단순화를 추진한다면 회복 가능성이 있으나
- 현재로서는 대부분의 개발자가 기대하지 않음
- 결론적으로 “웹 스택을 선택하겠다”는 판단으로 마무리됨
Hacker News 의견들
-
나도 다른 사람들처럼 Win32를 고수하는 게 맞다고 생각함
오랜 기간 Win32로 개발해온 입장에서, 필요한 기능은 8KB 이하의 독립 실행 파일로 충분히 구현 가능함
디스플레이 열거, 창 생성, 단축키 후킹, 시작 프로그램 등록, 설정 저장, 트레이 아이콘 표시 등 모두 몇백 바이트 수준의 API 호출로 가능함
하지만 2026년에 새 프로젝트를 메모리 안전하지 않은 언어(C++) 로 작성하는 건 시대착오적임
다만, 신뢰되지 않은 입력이 거의 없는 앱이라면 굳이 선전(Propaganda)에 휘둘릴 필요는 없음- 메모리 안전성과
_UNICODE문제를 피하고 싶다면 .NET Framework로 절반의 시간에 같은 걸 만들 수 있음 - 예전에는 Delphi나 MFC 같은 얇은 레이어가 이런 문제를 해결했지만 지금은 유행이 지나고 대체제가 없음
“NoFramework” 운동이 다시 나와서 RAD 시대로 돌아가야 한다고 생각함 - Win32는 여전히 풍부한 문서와 도구가 있고, 앞으로도 오래 살아남을 것임
하지만 새 프로젝트에서 C++을 선택하는 건 신중해야 함
메모리 안전 언어에서도 Win32를 쓸 수 있음 — 예를 들어 windows-rs - 일반 사용자 눈에 Win32 앱을 예쁘게 보이게 하려면 어떻게 해야 하는지 궁금함
- Winamp 개발자들은 어떻게 그렇게 훌륭한 Win32 앱을 만들었을까 궁금함
당시엔 Borland Delphi가 가장 인기 있는 도구였음
- 메모리 안전성과
-
기존 WinRT, UAP, UWP 앱이 아니라면 WinUI 3.0이나 WinAppSDK는 피해야 함
Win32, MFC, WinForms, WPF 같은 검증된 기술을 계속 쓰는 게 낫고,
Microsoft 외부 생태계라면 Qt, VCL, Firemonkey, Avalonia, Uno, ImGUI 등을 고려할 만함
WinUI 3.0은 너무 엉망이라 Microsoft조차 커뮤니티에 오픈소스로 넘기려는 중임 -
임베디드 개발자인데, 장치와 통신하는 Win32 GUI 프로그램을 만드는 게 여전히 쉬움
XP 시절 코드가 Windows 11에서도 그대로 동작했고, VC6 프로젝트를 Visual Studio 2022로 열어도 문제없이 빌드됨
이런 하위 호환성은 다른 플랫폼에서 보기 힘듦- 나는 차라리 투박한 Win32 코드를 계속 쓰는 게 낫다고 느낌
Apple의 Cocoa는 구조는 “우아”하지만 실제로는 복잡하고 문서도 불친절함 - 요즘 개발자들은 매주 바뀌는 생태계에 익숙해서, 오래된 게 “유지보수 안 되는 것”이라 생각하는 경향이 있음
- 다만 고해상도 DPI나 입력 처리 문제 등은 여전히 까다로움
- 32비트에서 64비트로 완전 이전하는 게 가장 큰 도전이었음
- 문자열 정의 방식이 너무 많아서 혼란스러움
- 나는 차라리 투박한 Win32 코드를 계속 쓰는 게 낫다고 느낌
-
순수 Win32 API는 여전히 실용적인 선택임
C++로 MFC 비슷한 래퍼를 직접 만들면 2~3주 안에 완성 가능하고, 이후엔 완전한 제어권을 가질 수 있음
Microsoft의 강력한 하위 호환성 덕분에 Win32 기반 앱은 장기적으로 안정적임
10년 넘게 업데이트한 예시를 여기에서 볼 수 있음- 다크 모드 지원이 가장 큰 문제임
시스템 색상과 컨트롤이 하드코딩되어 있어서 어두운 테마와 충돌함
메뉴나 메시지 박스, 파일 대화상자 등 일부 UI만 다크 모드를 지원해 일관성이 깨짐 - 이 접근법은 Windows 11 스타일 UI를 만들지 못함
관련 논의는 이 글 참고 - 예전에 WTL 3.0을 썼는데, MFC보다 훨씬 가볍고 Win32 기능에 모두 접근 가능했음
현재는 오픈소스로 유지되고 있고 버전 10까지 나와 있음 - MFC 스타일 래퍼의 API 설계를 잘 하면, AI가 구현을 대신 작성해줄 수도 있음
- 차라리 C++ Builder나 Delphi를 쓰는 게 낫지 않냐는 의견도 있음
- 다크 모드 지원이 가장 큰 문제임
-
Windows 앱을 여러 개 만들어본 경험상,
(1) Win32 API는 오래됐지만 매우 안정적이고,
(2) Microsoft 소유 UI 툴킷은 피해야 함 — 결국 Win32 레벨의 제어가 필요해짐- 다만 WPF와 WinForms는 예외적으로 안정적임
지난 20년간 Microsoft가 만든 UI 기술 대부분이 WPF의 변형이었음
WPF를 계속 발전시켰다면 지금쯤 UI 개발의 표준이 되었을 것임
- 다만 WPF와 WinForms는 예외적으로 안정적임
-
사용자 입장에서는 네이티브 앱이 빠르고 좋지만, 개발은 정말 복잡한 혼돈임
Outlook과 Teams 같은 앱이 점점 나빠지는 이유도 이 때문임- 아이러니하게도 Outlook과 Teams가 웹앱 기반(Electron) 이라서 그런 문제를 겪음
포커스, 키보드 내비게이션 등에서 네이티브 감각을 흉내내기 어려움 - 나도 개인 도구를 만들 때 TypeScript + Bun + Electrobun 조합을 씀
Electrobun 프로젝트 참고 - Microsoft조차 Electron으로 앱을 만들고 있으니, 다른 개발자들에게 뭘 기대하겠음
- 아이러니하게도 Outlook과 Teams가 웹앱 기반(Electron) 이라서 그런 문제를 겪음
-
“C++로 새 프로젝트를 만드는 건 범죄”라는 말엔 동의하지 않음
GUI는 안전성보다 성능과 제어가 중요하고, C++은 여전히 검증된 언어임
Qt는 2026년에도 최고의 GUI 프레임워크 중 하나로, 메모리 안전 기능을 내장하고 있음- 하지만 Qt는 일부 Linux 배포판에서만 진정한 네이티브로 동작함
- Qt 앱은 런타임이 필요하므로 완전한 네이티브라 보긴 어려움
- 물론 관리형 환경에 비하면 불편하지만, 임베디드 환경에서는 여전히 유용함
-
왜 최신 .NET 런타임이 Windows 11에 기본 포함되지 않는지 의문임
이는 Microsoft가 일관된 사용자 경험을 포기한 또 다른 사례로 보임- .NET 버전이 너무 많고 완전한 하위 호환이 아니기 때문에,
Windows Update로 모두 배포하는 건 비현실적임
대신 AOT 컴파일된 독립 실행 파일로 배포할 수 있음 (약 9MiB)
Electron보다 훨씬 작고 효율적임 - 예전엔 Windows Update로 배포했지만, 업데이트가 앱을 깨뜨리거나 너무 커서 비효율적이었음
지금은 DLL을 함께 패키징하는 게 더 나음 - .NET 5 이후 보안 모델과 네임스페이스가 크게 바뀌어
OS에 내장하기 어려워졌음
빠른 릴리스 주기를 유지하려고 OS 업데이트와 분리한 것임 - 현재는 레거시 .NET Framework가 OS에 포함되고,
.NET Core는 별도로 설치해야 하는 구조임
- .NET 버전이 너무 많고 완전한 하위 호환이 아니기 때문에,
-
오랜만에 Tauri로 Windows와 Mac용 앱을 만들어봤는데,
개발과 빌드는 쉬웠지만 코드 서명 문제로 동료들이 설치를 못 했음
Mac에서는 터미널 명령으로 해결했지만, Windows는 Smart App Control을 꺼야 했고
이 기능은 재설치 없이는 다시 켤 수 없음
보안 목적은 이해하지만, 설치 과정이 이렇게 어려울 줄은 몰랐음 -
“왜 Electron을 쓰지 않느냐”는 질문의 답은 간단함 —
Electron 앱은 사용자 경험이 나쁨
개발은 쉽지만, 성능과 품질을 희생함
좋은 제품을 만들고 싶다면 어렵더라도 네이티브로 가야 함
개인적으로는 C#이 TypeScript보다 훨씬 낫다고 생각함