수정 이력(7건, 최종 수정 2026년 09월 03일)
이 글에 적용한 변경 사항의 기록입니다. 보관해 둔 수정 전 버전은 DOI가 부여된 고정 URL에서 읽을 수 있습니다.
- Codex 리뷰에 따라 상담·문의 링크에 /ko/ 로케일 접두를 붙였습니다. 본문의 기술적인 주장은 바꾸지 않았습니다.
- 관련 기사 링크를 한국어 permalink에 맞추는 등 CI가 지적한 표시용 수정을 반영했습니다. 본문의 기술적인 주장은 바꾸지 않았습니다.
- permalink·저자 표기·지식 맵 래퍼·깨진 내부 링크 등 CI가 지적한 표시용 수정을 반영했습니다. 본문의 기술적인 주장은 바꾸지 않았습니다.
- 기사 서두에 「이 글의 지식 맵」 절을 추가했습니다. 본문에서 다루는 개념과 그 관계를 요약·그림·상세 페이지 링크로 정리한 것입니다. 본문의 주장은 바꾸지 않았습니다.
- 외부 리뷰(1283건) 대응으로 본문을 업데이트했습니다. 개별 변경 내용은 아래 이력을 참조하십시오.
- 네이티브와 Web 사이에서 메시지가 오가는 흐름을 시퀀스 그림으로 만들고, 어디서 검사하는지를 나타냈습니다. DevTools를 여는 방법 3가지와 콘솔에서 통신을 확인하는 4단계, 전제 조건 표(지원 OS, 지원 개발 환경, 필요한 NuGet과 런타임)를 추가했습니다.
- 본문의 관련 기사 링크 문구가 링크 대상의 현재 제목과 어긋나 있던 것을 실제 제목에 맞췄습니다. 본문 내용은 바꾸지 않았습니다.
- 최초 공개
이 글을 인용하기(DOI(등록된 아카이브): 10.5281/zenodo.21635342)
아래 DOI는 이전에 등록된 아카이브를 가리키며 현재 본문과 다를 수 있습니다. 현재 본문을 참조할 때는 이 페이지의 URL을 사용하세요.
Go Komura (2026). 「IE모드의 다음은 WebView2로 충분한가 ── ActiveX가 동작하지 않는 제약과 현실적인 전환 설계」. 합동회사 코무라소프트. https://comcomponent.com/ko/blog/webview2-embed-web-ui-in-windows-apps/
- DOI(등록된 아카이브)
- 10.5281/zenodo.21635342
- DOI(마지막 등록 버전)
- 10.5281/zenodo.21635343
이전 기사 「IE모드 의존 사내 Web 시스템을 어떻게 연명하고, 어떻게 빠져나올 것인가」에서는 IE 모드는 어디까지나 기한이 있는 연명 조치이며, 병행해서 출구를 설계해야 한다고 썼습니다. 그 「출구」 상담을 받다 보면 높은 빈도로 등장하는 것이 WebView2입니다. 「사내 Web 시스템을 전용 앱 안에 표시하고 싶다」「데스크톱 앱의 일부 화면만 Web 기술로 만들고 싶다」「Electron은 무겁다고 들었는데 대안이 있는가」──어느 경우든 WebView2가 선택지로 올라오는 장면입니다.
한편 WebView2에는 도입 전에 알아 두어야 할 버릇이 있습니다. 런타임을 어떻게 배포할지, 사용자 데이터 폴더를 어디에 둘지, 네이티브 측과 Web 측을 어떻게 대화시킬지. 그리고 무엇보다 IE 모드에서 동작하던 ActiveX는 WebView2에서는 동작하지 않는다는, 전환 계획의 근간에 관련된 제약입니다. 이 글에서는 WebView2의 기본 구조부터 배포·설계·보안, IE 모드 탈출과의 현실적인 조합 방법까지 정리합니다.
1. 먼저 결론
- WebView2는 Chromium 기반 Microsoft Edge를 Windows 앱에 임베드하는 컨트롤입니다. WinForms / WPF / WinUI / Win32 C++에서 사용할 수 있으며, 기존 데스크톱 앱에 「일부만 Web UI」를 더하는 용도에 맞습니다.1
- 런타임은 원칙적으로 Evergreen(자동 업데이트되는 공유 런타임) 을 사용합니다. Windows 11에는 기본 탑재되어 있지만 「이미 설치되어 있다」고 전제하지 않고, 설치 프로그램에서 존재 확인과 bootstrap을 넣는 것이 공식 권장입니다.2
- 오프라인 환경이나 검증된 구성을 고정하고 싶은 공장·제조 라인에는 Fixed Version(앱 동봉) 이 있지만, 동봉물이 250MB를 넘고 보안 업데이트를 직접 배포할 책임을 집니다. 쉽게 고르지 마십시오.3
- 처음에 빠지기 쉬운 것은 사용자 데이터 폴더(UDF) 입니다. 기본값에서는 exe 옆에 만들어지므로 Program Files 아래에 설치한 앱에서는 시작에 실패합니다.
%LOCALAPPDATA%아래를 명시 지정하는 것을 정석으로 하십시오.4 - 네이티브⇔Web 연동은
PostWebMessageAsJson/WebMessageReceived에 의한 메시지 교환을 기본으로 하고,AddHostObjectToScript(COM 객체 공개)는 신뢰할 수 있는 콘텐츠에 한정합니다.1 - WebView2 안에서 ActiveX는 동작하지 않습니다. ActiveX를 포함한 IE 모드 의존 페이지를 「WebView2로 바꾸면 끝」으로 처리할 수 없으며, ActiveX가 담당하던 처리를 네이티브 측으로 옮기는 설계가 필요합니다. 여기가 IE 모드 탈출 계획의 핵심입니다.5
그림의 실선은 항상 성립하는 관계, 점선은 조건이 붙는 관계입니다(성립 조건은 상세 페이지의 관계별 설명에 적혀 있습니다). 관계 전체 목록(총 19건, 근거와 확신도 포함)과 주요 개념의 정의는 지식 맵 상세 페이지에 정리되어 있습니다(일본어). 데이터: JSON-LD / Turtle
2. WebView2의 기본 구조
WebView2는 「SDK(앱에 넣는 API)」와 「런타임(클라이언트에 설치되는 Edge 기반 실행 환경)」의 두 가지로 이루어집니다. Visual C++ 런타임이나 .NET 런타임과 같은 구도이며, 앱은 NuGet 패키지 Microsoft.Web.WebView2를 참조하여 빌드하고, 실행 시에는 클라이언트상의 런타임을 써서 동작합니다.3
지원 플랫폼은 넓고, .NET Framework 4.6.2 이후 / .NET Core 3.1 이후의 WinForms·WPF, WinUI, Win32 C++에서 이용할 수 있습니다. 기존 WinForms 업무 앱의 한 화면만 WebView2로 만드는 식의 단계적 사용이 가능하다는 점이, 프레임워크 자체를 갈아타는 방식(Electron 등)에 대한 큰 이점입니다. UI 프레임워크 자체의 선정은 「WinForms / WPF / WinUI 판단표」도 참조하십시오.
검토 입구에서 매번 묻는 전제 조건을, 공식 문서 기재대로 한 곳에 모아 둡니다.
| 항목 | 내용 |
|---|---|
| 지원 클라이언트 OS | Windows 10(SAC 1709 이후), Windows 10의 각 LTSC / IoT Enterprise, Windows 116 |
| 지원 서버 OS | Windows Server 2016 / 2019 / 2022(LTSC), Windows Server(SAC)6 |
| 지원하는 개발 환경 | Win32 C/C++, .NET Framework 4.6.2 이후, .NET Core 3.1 이후, .NET 5 이후, WinUI 2.0 / 3.06 |
| IDE | Visual Studio 2017 이후. 공식 튜토리얼은 Visual Studio Code에는 지원하지 않는다고 명시되어 있습니다7 |
| SDK | NuGet 패키지 Microsoft.Web.WebView2(프로젝트마다 추가)7 |
| 실행 시 필요한 것 | WebView2 런타임. 원칙 Evergreen, Windows 11에는 기본 탑재(제 3장)3 |
| Windows 이외의 디바이스 | Xbox, HoloLens 2에서도 이용할 수 있습니다6 |
최소 임베드는 다음과 같은 코드가 됩니다(WPF/WinForms 공통 방식).
var env = await CoreWebView2Environment.CreateAsync(
browserExecutableFolder: null, // Evergreen 런타임을 사용한다
userDataFolder: Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"KomuraSoft", "MyApp", "WebView2"));
await webView.EnsureCoreWebView2Async(env);
webView.CoreWebView2.Navigate("https://internal.example.co.jp/app/");
포인트는 기본값에 맡기지 않고 CoreWebView2Environment를 직접 만든다는 점입니다. 이유는 다음 두 장에서 설명합니다.
도입 절차 자체는 단순하며, WinForms / WPF라면 다음 흐름입니다.
- NuGet으로
Microsoft.Web.WebView2를 프로젝트에 추가한다(디자이너의 도구 상자에도 WebView2 컨트롤이 나타납니다) - 폼/윈도우에 컨트롤을 배치한다
- 위 코드처럼
EnsureCoreWebView2Async로 초기화한 뒤Navigate한다
여기서 하나, 처음에 반드시 잡아 두고 싶은 API상의 주의가 있습니다. webView.CoreWebView2는 초기화가 끝날 때까지 null입니다. 폼 생성자에서 CoreWebView2.WebMessageReceived += ...처럼 이벤트를 구독하려다 NullReferenceException이 나는 것은 전형적인 실수이며, 초기화 관련 처리는 「EnsureCoreWebView2Async의 await 이후」로 모으는 것이 기본형입니다. Source 속성에 대입하면 초기화가 암묵적으로 시작되지만, 환경(UDF 위치 등)을 지정하고 싶은 앱에서는 명시적으로 EnsureCoreWebView2Async(env)를 먼저 호출하는 구성으로 통일하는 편이 사고가 없습니다.
또한 WebView2의 이벤트는 모두 UI 스레드에서 발생합니다. WebMessageReceived 안에서 무거운 처리(장비 액세스나 파일 I/O)를 그대로 쓰면 Web 측 조작감까지 함께 멈추므로, 네이티브 측 처리는 async/await로 빼냅니다. 이 원칙은 「WPF/WinForms의 UI 스레드와 async/await」에서 쓴 내용이 그대로 적용됩니다.
3. 런타임 배포 ── Evergreen과 Fixed Version
3.1 Evergreen(권장)
Evergreen은 클라이언트에 설치된 공유 런타임을 모든 WebView2 앱이 사용하고, 런타임은 자동 업데이트되는 방식입니다. 보안 패치가 자동으로 적용되고 디스크 소비가 작다는 이유로 공식에서 명확히 권장합니다.8
실무에서의 주의는 세 가지입니다.
- 존재 확인을 구현한다. Windows 11에는 기본 탑재되고 Windows 10에도 널리 배포되어 있지만, 그래도 「들어 있지 않은 단말」은 존재합니다. .NET에서는
CoreWebView2Environment.GetAvailableBrowserVersionString()으로 확인할 수 있지만, 런타임 미도입 환경에서는 이 호출 자체가 예외(WebView2RuntimeNotFoundException)로 실패하므로, try/catch로 감싸 「예외=미설치」로 판정하고 bootstrapper(작은 온라인 설치 프로그램) 또는 독립 실행형 설치 프로그램 실행으로 진행하는 형태로 설치에 넣습니다.2 - 런타임 업데이트 추종을 설계한다. 런타임이 업데이트되어도 실행 중인 앱은 이전 버전을 계속 사용합니다.
NewBrowserVersionAvailable이벤트를 받아 「다시 시작하면 업데이트가 적용된다」는 동선을 만들어 두는 것이 권장 패턴입니다.2 - 사내 업데이트 통제와 맞춘다. Edge 브라우저와 WebView2 런타임의 업데이트 정책은 별개입니다. 그룹 정책으로 런타임 업데이트를 멈추고 있는 환경에서는 Evergreen의 전제(최신이 들어가 있다)가 깨지므로, 비교적 새로운 API를 쓰는 경우에는 feature 검출을 넣습니다.8
3.2 Fixed Version(한정 용도)
Fixed Version은 특정 버전의 런타임을 앱에 동봉하는 방식입니다. 동작 검증이 끝난 구성을 고정할 수 있으므로, 오프라인 제조 장치나 변경 관리가 엄격한 환경에서는 합리적인 선택이 됩니다. 다만,
- 동봉 바이너리는 250MB를 넘고, 배포물이 그만큼 커진다2
- 런타임은 자동 업데이트되지 않으므로 브라우저 엔진의 취약점 수정을 자신의 릴리스로 배포할 책임을 진다
- 업데이트를 게을리하면 「오래된 Chromium을 실은 업무 앱」이 사내에 계속 남는다
는 무거운 대가가 있습니다. 표시하는 콘텐츠가 완전히 폐쇄망·자사 관리이고, 릴리스 사이클에 런타임 업데이트를 넣을 체제가 있는 경우에 한정해 고르십시오.
4. 처음에 빠지기 쉬운 함정 ── 사용자 데이터 폴더
WebView2는 Cookie·캐시·권한 등을 사용자 데이터 폴더(UDF)에 저장합니다. UDF 위치를 지정하지 않으면 기본 위치(많은 구성에서 exe와 같은 장소의 옆)에 만들려고 하므로, Program Files 아래에 설치된 앱에서는 쓰기에 실패하고 초기화 오류가 납니다. 개발 머신(디버그 실행, 쓰기 가능한 폴더)에서는 동작하는데 설치하는 순간 동작하지 않는──전형적인 「배포하고 나서야 드러나는」 장애입니다.4
대책은 단순하며, 앞의 코드 예처럼 %LOCALAPPDATA% 아래의 앱 전용 폴더를 항상 명시 지정하는 것입니다. 함께 다음도 설계에 넣어둡니다.
- UDF는 사용자별·앱별로 나눈다(여러 앱에서 공유하지 않는다)
- 네트워크 드라이브 위에 두지 않는다(속도 저하·손상·데이터 손실의 원인이 됩니다)4
- 제거 시나 「로그인 정보를 지우기」 기능에서 UDF를 삭제하는 절차를 정해 둔다(Cookie나 사이트 데이터가 남는 장소임을 운영자가 모르면, 퇴사자 단말 정리 등에서 빠집니다)
앞의 기사 「업무 Windows 앱의 로컬 데이터 저장」에서 쓴 「exe 옆에 쓰지 않는다」 원칙의 WebView2 판이라고 생각하십시오.
5. 네이티브⇔Web의 연동 설계
WebView2를 「단순한 브라우저 틀」 이상으로 만드는 것이, 네이티브 코드와 Web 콘텐츠의 상호 연동입니다. 수단은 주로 두 가지입니다.1
「어느 쪽이 어떤 API로 보내고, 어느 쪽이 어떤 이벤트로 받는지」는 말로 설명하면 혼동하기 쉬우므로, 먼저 왕복의 전체 그림을 둡니다. 네이티브 측은 PostWebMessageAsJson으로 보내고 WebMessageReceived로 받는다. Web 측은 window.chrome.webview.postMessage로 보내고 message 이벤트로 받는다는 대칭형입니다.
sequenceDiagram
participant N as 네이티브 측 호스트 앱
participant W as WebView2 컨트롤
participant P as Web 페이지 JavaScript
Note over N,P: 초기화: EnsureCoreWebView2Async 완료 후에 구독한다
N->>W: WebMessageReceived를 구독
P->>W: window.chrome.webview.addEventListener로 message를 구독
Note over P: 이용자가 「라벨 인쇄」를 누른다
P->>W: window.chrome.webview.postMessage로 의뢰를 보낸다
W->>N: WebMessageReceived가 발생
N->>N: e.Source로 발신원을 검사하고 type을 화이트리스트 대조
N->>N: 장비 제어 등 네이티브 처리를 async로 실행
N->>W: PostWebMessageAsJson으로 결과를 보낸다
W->>P: message 이벤트가 발생
P->>P: 화면의 상태 표시를 갱신
그림의 왼쪽 절반이 네이티브, 오른쪽 절반이 Web입니다. 검사는 네이티브 측의 수신 직후에 한 곳만 둔다는 것이 요점이며, 여기를 지난 뒤의 처리는 「허가된 type의 의뢰만 온다」고 가정하고 쓸 수 있습니다.
5.1 Web 메시지(기본형)
네이티브 측에서 PostWebMessageAsJson으로 JSON을 보내고, Web 측은 window.chrome.webview.addEventListener("message", ...)로 받습니다. 반대 방향은 window.chrome.webview.postMessage(...)와 WebMessageReceived 이벤트입니다. 느슨한 결합이며, 공개하는 조작을 한 곳에서 검사할 수 있으므로 우선 이쪽을 기본 연동 수단으로 합니다.
// 네이티브 → Web
webView.CoreWebView2.PostWebMessageAsJson(
JsonSerializer.Serialize(new { type = "deviceStatus", connected = true }));
// Web → 네이티브
webView.CoreWebView2.WebMessageReceived += (s, e) =>
{
// 예상 origin 이외(외부 사이트로 이동한 뒤 등)에서의 메시지는 처리하지 않는다
if (!e.Source.StartsWith("https://internal.example.co.jp/", StringComparison.Ordinal))
return;
AppMessage? msg;
try { msg = JsonSerializer.Deserialize<AppMessage>(e.WebMessageAsJson); }
catch (JsonException) { msg = null; }
if (msg?.Type is null)
return; // 형식이 잘못된 것은 여기서 버린다(필요하면 로그로)
// type마다 허가된 조작만 실행한다
};
Web 측(JavaScript)은 이렇게 받습니다. 특별한 라이브러리는 필요 없고, WebView2가 주입하는 window.chrome.webview 객체만 사용합니다.
// 네이티브에서의 메시지를 받는다
window.chrome.webview.addEventListener("message", (e) => {
if (e.data.type === "deviceStatus") {
updateStatusBadge(e.data.connected);
}
});
// 네이티브로 의뢰를 보낸다
document.getElementById("print-label").addEventListener("click", () => {
window.chrome.webview.postMessage({ type: "printLabel", copies: 2 });
});
수신 측에서는 위 코드처럼 e.Source(메시지를 보낸 페이지의 URI)를 먼저 검사하고, 그다음 「메시지의 type을 화이트리스트로 검사하고, 예상 밖은 무시하고 로그에 남긴다」를 철저히 합니다. Web 측은 링크 하나·리다이렉트 하나로 외부 사이트로 이동할 수 있으므로, 「지금 표시 중인 것은 자신의 페이지일 것」이라는 짐작으로 발신원 검사를 빼지 마십시오. 반대로 Web 측에서도 window.chrome.webview가 없는 경우(일반 브라우저에서 열린 경우)의 fallback을 넣어 두면, Web UI 부분을 단독으로 브라우저 디버그할 수 있어 개발 효율이 올라갑니다.
5.2 호스트 객체 공개(강력하지만 한정 사용)
AddHostObjectToScript를 쓰면 .NET/COM 객체를 JavaScript에서 직접 호출할 수 있게 됩니다. 내부적으로는 COM 메커니즘이며, 저희가 오래 다뤄 온 COM 기술이 이런 곳에서 현역인 점은 흥미롭지만, Web 콘텐츠에 네이티브 객체를 직접 쥐여 준다는 것은 그 페이지가 침해되었을 때의 영향도 그만큼 크다는 뜻입니다. 공개하는 것은 자사 관리 콘텐츠에 한정하고, 공개 메서드는 필요 최소한으로 줄이십시오. 신뢰할 수 없는 페이지를 표시할 가능성이 있는 WebView에는 등록하지 않는 것이 원칙입니다.
5.3 로컬 콘텐츠 로드
HTML/JS를 앱에 동봉해 표시하는 경우, file:// 직접 읽기가 아니라 SetVirtualHostNameToFolderMapping으로 가상 호스트 이름에 폴더를 매핑하는 것이 정석입니다. 콘텐츠가 https://appassets.example/ 같은 origin을 가지므로 localStorage 등 origin을 전제로 하는 Web API를 그대로 쓸 수 있고, cross-origin 액세스의 허용 수준도 지정할 수 있습니다. 호스트 이름에는 실재할 수 없는 예약 도메인(.example 등)을 쓰고, 액세스 종류는 필요 최소(우선 DenyCors)부터 시작합니다.9
6. IE모드 탈출과 WebView2 ── ActiveX는 동작하지 않는다
여기가 이 글에서 가장 중요한 절입니다. IE 모드가 연명할 수 있는 것은 Edge 안에서 실제 IE11(Trident 엔진)이 동작하며 ActiveX나 브라우저 헬퍼 객체가 그대로 동작하기 때문입니다.5 한편 WebView2는 Chromium이며 ActiveX를 호스트하는 메커니즘이 없습니다. 즉,
「IE 모드에서 동작하는 사내 시스템을 WebView2로 만든 셸에 옮긴다」는 ActiveX에 의존하지 않는 화면에 대해서만 성립한다.
이 제약에서 전환 계획을 짜야 합니다. 현실적인 전환 순서는 다음과 같습니다.
- 현황 파악: IE 모드 의존 페이지를 「ActiveX 등 IE 고유 기술을 쓰는 화면」과 「단지 오래된 구성일 뿐인 화면」으로 분류한다(IE 모드 기사의 현황 파악 절차를 그대로 쓸 수 있습니다. 요점을 한 줄로 말하면, Enterprise Site Discovery로 IE 모드 대상 URL을 기계적으로 나열하고, 각 URL의 의존을 「문서 모드」「ActiveX / BHO」「인증」「클라이언트 인증서」「파일·인쇄」「장비·COM」으로 분류한다는 것입니다).
- IE 고유가 아닌 화면: 모던 브라우저 대응으로 개수하고, Edge 자체로 표시하거나, 업무 단말 앱에 통합하고 싶으면 WebView2 셸에 올린다.
- ActiveX 의존 화면: ActiveX가 담당하던 기능(시리얼 통신, 파일 액세스, 전용 장비 제어 등)을 네이티브 측(WebView2의 호스트 앱)으로 옮기고, Web 메시지를 통해 호출하는 형태로 재설계한다. 「브라우저 안의 ActiveX」를 「앱 안의 Web UI +네이티브 처리」로 뒤집는 이미지입니다.
- ActiveX 자체를 남길지·랩할지·바꿀지의 판단은 「ActiveX/OCX 유지·랩·교체 판단표」의 기준이 그대로 적용됩니다.
이 3번의 재설계야말로 WebView2 도입의 실질적인 공수이며, 「WebView2를 넣으면 IE 모드에서 빠져나올 수 있다」는 단순한 이야기가 아니라는 기대치 조정이 계획 단계에서 필요합니다. 반대로 말하면, ActiveX 기능을 호스트 앱으로 옮기는 설계만 끝나면 UI는 Web 기술로 자체 개발·유지보수하기 쉬워지고, 배포는 데스크톱 앱으로 통제할 수 있다는 양쪽을 취할 수 있습니다.
7. 사내 시스템에서 반드시 나오는 구현 과제
WebView2 채택을 검토하면 업무 측에서 반드시 나오는 질문이 몇 가지 있습니다. 미리 정리해 둡니다.
7.1 인쇄와 장표
「IE 때는 인쇄 버튼으로 장표가 나왔다」는 요건은 WebView2에서는 두 계통으로 받을 수 있습니다.
- 화면을 그대로 인쇄:
CoreWebView2.ShowPrintUI()로 인쇄 대화상자를 띄우거나,PrintAsync로 무인 인쇄. 브라우저 인쇄와 동등하므로 CSS 인쇄 지정(@media print)이 그대로 적용됩니다. - PDF로 출력:
PrintToPdfAsync로 표시 중인 페이지를 PDF 파일로 저장할 수 있습니다. 「장표는 PDF로 저장해 공유 폴더로」라는 업무 흐름에는, 네이티브 측에서 파일 이름·저장 위치를 통제할 수 있는 이쪽이 맞습니다.1
픽셀 단위의 자릿수 맞춤이 요구되는 복사용 전표 같은 장표는, Web 인쇄로 몰아붙이기보다 네이티브 측 장표 출력(Excel 장표 만드는 법에서 정리한 방식)으로 옮기는 판단도 포함해 검토하십시오.
7.2 파일 다운로드와 업로드
다운로드는 기본값에서도 브라우저와 같이 동작하지만, 업무 앱에서는 DownloadStarting 이벤트로 개입하는 것이 정석입니다. 저장 위치를 고정하고, 확장자로 허용·거부를 판정하고, 기본 다운로드 UI를 끄고 앱 측 알림으로 바꾸는 식의 통제를 걸 수 있습니다.1 업로드(<input type="file">)는 특별한 구현 없이 OS의 파일 선택 대화상자가 열립니다.
7.3 인증과 SSO
사내 Web 시스템 측이 Windows 통합 인증(NTLM/Kerberos)이면, WebView2에서도 대체로 브라우저와 같이 통과합니다. Basic 인증을 쓰는 오래된 시스템에는 BasicAuthenticationRequested 이벤트로 credential을 공급할 수 있고, 로그인 화면을 띄우지 않고 끝낼 수도 있습니다──다만 그 credential을 어디에 저장할지는 바로 DPAPI 기사에서 쓴 이야기가 됩니다. Microsoft Entra ID(구 Azure AD)의 SSO를 OS 로그인 정보로 통과시키고 싶은 경우에는 환경 옵션 AllowSingleSignOnUsingOSPrimaryAccount 활성화를 검토합니다.
Cookie는 UDF에 저장되므로 앱을 다시 시작해도 로그인 상태는 유지됩니다. 「로그아웃 기능으로 세션을 확실히 지우고 싶다」면 CookieManager로 명시적으로 삭제하는 구현을 넣으십시오.
7.4 개발 시 디버그
WebView2의 내용은 Chromium이므로, 개발 중에는 F12의 DevTools를 그대로 쓸 수 있습니다(CoreWebView2Settings.AreDevToolsEnabled가 기본으로 유효). 여는 방법은 세 가지로, F12, Ctrl+Shift+I, 페이지를 오른쪽 클릭하고 「검사」입니다. 8장처럼 바로 가기나 오른쪽 클릭 메뉴를 프로덕션 빌드에서 막은 경우에도, 앱 측에서 OpenDevToolsWindow를 호출하면 프로그램에서 열 수 있습니다(사내용으로 「숨은 메뉴에서 개발자 도구」를 마련해 두면, 현장 단말 조사가 한결 편해집니다).10
연동 구현에 들어가기 전에 메시지가 왕복하는 것만 3분 만에 확인해 두면 재작업이 줄어듭니다. 5.1의 코드를 넣은 상태에서 다음 순서로 시험하십시오.
- 앱을 시작하고, WebView2 화면에서 DevTools를 연 뒤 「콘솔」 탭으로 옮긴다.
window.chrome.webview를 입력해 평가한다. 객체가 표시되면 WebView2 안에서 동작 중입니다.undefined이면 일반 브라우저에서 열고 있거나, 초기화가 끝나지 않은 등 전제가 어긋난 것을 의심합니다.- Web → 네이티브를 확인한다. 콘솔에서
window.chrome.webview.postMessage({ type: "printLabel", copies: 1 })를 실행하고, 네이티브 측WebMessageReceived핸들러에 중단점을 걸어 두면 거기서 멈춥니다.e.WebMessageAsJson에 같은 JSON이 들어 있는 것과,e.Source에 지금 페이지의 URI가 들어 있는 것을 확인합니다. - 네이티브 → Web을 확인한다. 콘솔에서
window.chrome.webview.addEventListener("message", e => console.log(e.data))를 등록한 뒤, 네이티브 측PostWebMessageAsJson을 호출하는 조작(메뉴, 장비 상태 변화 등)을 하면 콘솔에 JSON이 나옵니다.
이 4단계로 「보낼 수 있다·받을 수 있다·발신원이 기대대로」까지 확인되어 있으면, 나머지는 type별 처리를 더해 가는 작업이 됩니다. 나아가 앞에서 말한 대로 Web UI 측을 「브라우저 단독으로도 동작」하도록 만들어 두면, UI 개발·디버그는 보통의 Web 개발로 돌리고, 네이티브 연동만 WebView2 위에서 확인하는 분업이 됩니다. Web 자산을 앱에 가둬 두더라도 개발 경험은 Web 그대로 유지할 수 있다는 뜻입니다.
8. 보안 설계의 요점
WebView2 앱은 「브라우저를 내장한 앱」이므로 브라우저에 해당하는 위협 모델로 생각합니다.
- 표시하는 콘텐츠를 한정한다:
NavigationStarting에서 이동 대상을 사내 도메인 화이트리스트로 검사하고, 예상 밖 URL은 기본 브라우저로 보낸다(NewWindowRequested도 같이 처리한다). - 신뢰 경계를 넘는 기능을 줄인다: 호스트 객체의 공개 범위, Web 메시지에서 허가하는 조작은 최소한으로. 외부 사이트를 표시할 수 있는 WebView와 네이티브 연동을 가진 WebView를 나누는 것도 유효합니다.
- 이용자용 기능을 환경에 맞춰 조정한다:
CoreWebView2Settings로 「브라우저다움」을 필요한 만큼만 남길 수 있습니다. 키오스크 단말이나 현장 단말에서는 줄여 두면 사고가 줄어듭니다. - Fixed Version이면 업데이트 계획에 책임을 진다: 앞에서 말한 대로, 취약점 수정 배포는 앱 측 책무가 됩니다.8
CoreWebView2Settings에서 자주 조정하는 항목을 들어 둡니다. 프로덕션 빌드에서 어떻게 할지를 릴리스 전 체크리스트에 넣어 두는 것을 권합니다.
| 설정 | 기본값 | 현장 단말·프로덕션에서의 전형 |
|---|---|---|
AreDevToolsEnabled(F12 개발자 도구) |
유효 | 프로덕션에서는 무효화 |
AreDefaultContextMenusEnabled(오른쪽 클릭 메뉴) |
유효 | 「뒤로」「다시 로드」를 쓰게 하고 싶지 않은 화면에서는 무효화 |
AreBrowserAcceleratorKeysEnabled(Ctrl+F5 등의 바로 가기) |
유효 | 키오스크 용도에서는 무효화 |
IsStatusBarEnabled(링크 대상 표시) |
유효 | 취향에 따라 |
IsZoomControlEnabled(Ctrl+휠 확대/축소) |
유효 | 레이아웃이 깨지는 업무 화면에서는 무효화 |
AreHostObjectsAllowed(호스트 객체) |
유효 | 쓰지 않으면 무효화 |
어느 쪽이든 「무효화하면 안전」이라기보다 「앱으로서 의도한 조작 이외의 입구를 닫는」 도구입니다. Windows 앱 전반의 보안 밑바닥을 올리는 일은 「Windows 앱 보안 최소 체크리스트」도 함께 참조하십시오.
9. 채택 판단 정리
| 구성 | 맞는 장면 | 주의점 |
|---|---|---|
| Edge(브라우저)로 표시 | 보통의 사내 Web 시스템 | 앱 통합·네이티브 연동은 불가 |
| 기존 앱+WebView2로 일부 Web UI | 화면 단위 현대화, Web 자산 재사용 | UDF·런타임 배포·연동 설계(이 글) |
| WebView2 셸+네이티브 기능 이식 | ActiveX 의존 IE 모드 자산의 출구 | ActiveX 기능 재구현이 핵심 |
| Electron 등 | 크로스 플랫폼이 필수인 경우 | Windows 전용이면 무겁다. 배포물·메모리 증가 |
| 풀 네이티브(WPF 등)로 다시 만들기 | Web 자산이 없음·오프라인 전제 | 개발 비용과의 상담 |
「Windows 전용 사내 앱에서 Web 기술 UI를 쓰고 싶다」면 Electron보다 WebView2가 기본 선택지입니다. 런타임을 OS 측과 공유할 수 있는 만큼 배포가 가볍고, 기존 .NET 자산과의 통합도 수월합니다.
10. 정리
WebView2는 Chromium 기반 Web UI를 Windows 앱에 부품으로 넣을 수 있는, 사내 시스템 현대화와 궁합이 좋은 기술입니다. 도입 시 실무 포인트는 Evergreen 런타임의 존재 확인과 업데이트 추종, 사용자 데이터 폴더의 명시 지정, Web 메시지를 기본으로 한 연동 설계의 세 가지입니다. 그리고 계획 면에서는 ActiveX는 동작하지 않는다는 제약을 직시하고, ActiveX 기능을 네이티브 측으로 옮기는 재설계를 공수의 중심에 두는 것입니다.
IE 모드 기한을 앞에 두고 「이제 출구를」 생각하고 있다면, 우선 대상 시스템의 현황 파악과 ActiveX 의존 부분의 기능 분해부터 시작하는 것이 현실적입니다. 이 진행 방식은 실제 시스템 구성을 보면서가 아니면 판단하기 어려운 부분도 많으므로, 막히면 상담해 주십시오.
관련 기사
- IE모드 의존 사내 Web 시스템을 어떻게 연명하고, 어떻게 빠져나올 것인가
- ActiveX / OCX를 지금 어떻게 다룰 것인가 - 남기기·감싸기·바꾸기 판단표
- COM·ActiveX·OCX란 무엇인가
- WinForms/WPF/WinUI 고르는 법 - 실무 판단표
관련 상담 영역
合同会社小村ソフト에서는 IE모드·ActiveX 의존 사내 시스템의 출구 설계, WebView2를 쓴 단계적 현대화, 기존 Windows 앱에 Web UI를 통합하는 상담을 다룹니다.
참고 링크
-
Microsoft Learn, Overview of WebView2 APIs. 내비게이션 관리, 로컬 콘텐츠 로드, 호스트⇔Web 간 통신(Web 메시지, 호스트 객체) 등 WebView2 기능 전체상에 대해. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Distribute your app and the WebView2 Runtime. bootstrapper/독립 실행형 설치 프로그램에 의한 배포, 설치 여부 검출, NewBrowserVersionAvailable에 의한 업데이트 추종, Fixed Version 동봉 절차(250MB 초과)에 대해. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Evergreen vs. fixed version of the WebView2 Runtime. 런타임 두 가지 배포 모드의 차이, Windows 11 기본 탑재, Fixed Version의 장점과 단점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Manage user data folders. 사용자 데이터 폴더의 역할, 사용자 지정 UDF에 필요한 읽기/쓰기 권한, 네트워크 드라이브 위에 두면 속도 저하·크래시·데이터 손실의 원인이 되는 점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, What is Internet Explorer (IE) mode?. IE 모드가 Trident (MSHTML) 엔진으로 동작하며 ActiveX 컨트롤이나 브라우저 헬퍼 객체를 지원하는 점에 대해(=Chromium 기반 WebView2에는 이 지원이 없음). ↩ ↩2
-
Microsoft Learn, Introduction to Microsoft Edge WebView2. WebView2 앱이 동작하는 Windows 클라이언트(Windows 10 SAC 1709 이후, 각 LTSC / IoT Enterprise, Windows 11)와 Windows Server(2016 / 2019 / 2022의 LTSC, SAC), 지원하는 개발 환경(Win32 C/C++, .NET Framework 4.6.2 이후, .NET Core 3.1 이후, .NET 5 이후, WinUI 2.0 / 3.0), 및 Xbox·HoloLens 2에서도 이용할 수 있는 점에 대해. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Get started with WebView2 in WinForms apps. Visual Studio 2017 이후가 필요하고 Visual Studio Code는 튜토리얼 대상 밖인 점, NuGet으로 프로젝트마다
Microsoft.Web.WebView2SDK를 추가하는 점,EnsureCoreWebView2Async완료 후에WebMessageReceived를 구독하는 초기화 순서, 및window.chrome.webview.postMessage와PostWebMessageAsString/PostWebMessageAsJson에 의한 상호 통신에 대해. ↩ ↩2 -
Microsoft Learn, Development best practices for WebView2 apps. Evergreen 권장, 런타임 업데이트 취급, feature 검출, Fixed Version 이용 시 정기 업데이트의 필요성에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Using local content in WebView2 apps. 가상 호스트 이름 매핑에 의한 로컬 콘텐츠 로드, origin이 부여되는 이점, 액세스 종류(DenyCors 등) 지정에 대해. ↩
-
Microsoft Learn, Debug WebView2 apps with Microsoft Edge DevTools. DevTools를 여는 방법이 F12, Ctrl+Shift+I, 페이지를 오른쪽 클릭하고 「검사」의 세 가지인 점, 바로 가기나 오른쪽 클릭 메뉴를 삭제한 경우에는
OpenDevToolsWindowAPI로 프로그램에서 열 수 있는 점에 대해. ↩
관련 기사
같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.
Windows 프린터 드라이버 제공 종료 ── 업무 앱의 장표·라벨 인쇄는 어떻게 대비할 것인가
Microsoft는 v3/v4 프린터 드라이버의 제공 종료를 단계적으로 진행하고 있으며, 2026년 7월부터는 IPP 클래스 드라이버가 우선됩니다. Windows protected print mode에서 무엇이 사라지는지, 업무 앱의 장표·라벨 ...
WPF의 고DPI 대응 ── 「DPI에 강해야 하는데」 흐려지고 번지는 원인과 대처
WPF는 System DPI Aware이지만, DPI가 다른 모니터로 옮기면 전체가 번지고 비트맵은 흐려집니다. 원인 분리, Per-Monitor DPI 대응, UseLayoutRounding 등 정석 대처, WindowsFormsHost 혼재의...
Windows 앱 외주·수탁 개발을 의뢰하기 전에 정리할 점
Windows 앱 외주·수탁 개발을 의뢰하기 전에, 기존 소프트웨어 수정, 장치 연동, COM/ActiveX, 배포·업데이트, 유지보수를 정리하는 포인트를 설명합니다.
Time Travel Debugging ── 장기 가동에서 재현되지 않는 결함을 「녹화」해서 되감기
한 달에 한 번만 나오는 결함은 크래시 덤프로는 결과밖에 찍히지 않습니다. WinDbg의 Time Travel Debugging(TTD)으로 실행을 녹화해 되감는 방법을 TTD.exe의 녹화 설계, 링 버퍼, TTD.Calls 쿼리, 덤프와의 역...
Windows 앱의 작업 트레이 상주와 토스트 알림 ── NotifyIcon의 함정과 AppNotification 고르는 법
업무용 Windows 앱의 작업 트레이 상주와 토스트 알림 구현을 정리합니다. NotifyIcon의 올바른 사용법, Explorer 재시작 시 재등록, 토스트 API 3종의 선정 판단표, 알림이 도착하지 않는 경우까지 설명합니다.
관련 토픽
이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.
Windows 기술 토픽
Windows 개발, 장애 조사, 기존 자산 활용에 관한 KomuraSoft LLC 기사를 모은 토픽 허브입니다.
ActiveX 이관
COM / ActiveX / OCX 자산을 유지할지, 감쌀지, 교체할지의 단계적 판단을 정리한 토픽 페이지입니다.
UI 스레드 & 타이머
WPF / WinForms UI 스레드, async 흐름, Dispatcher 사용, 타이머 판단을 정리한 토픽 페이지입니다.
이 주제와 연결되는 서비스
이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.
Windows 앱 개발
상주 처리, 장비 연동, 운영 로그, 유지 보수 가능한 구조가 필요한 Windows 데스크톱 애플리케이션을 지원합니다.
기술 상담 & 설계 리뷰
설계 방향, 아키텍처 경계, 수명 관리, 기존 Windows 자산 처리 방법을 정리하는 데 도움을 드립니다.
자주 묻는 질문
이 기사 주제에 대해 상담 시 자주 나오는 질문을 모았습니다.
- WebView2에서 ActiveX는 동작합니까?
- 동작하지 않습니다. IE모드는 Edge 안에서 실제 IE11(Trident 엔진)이 동작하므로 ActiveX가 그대로 동작하지만, WebView2는 Chromium 기반이라 ActiveX를 호스트하는 메커니즘이 없습니다. 따라서 ActiveX에 의존하는 화면을 「WebView2로 바꾸면 끝」으로 처리할 수 없으며, ActiveX가 담당하던 시리얼 통신·파일 액세스·전용 장비 제어 등의 기능을 네이티브 측(호스트 앱)으로 옮기고 Web 메시지를 통해 호출하는 형태로 재설계해야 합니다. 이 재설계야말로 WebView2 도입의 실질적인 공수가 됩니다.
- WebView2 런타임은 Evergreen과 Fixed Version 중 어느 쪽을 선택해야 합니까?
- 원칙은 Evergreen(자동 업데이트되는 공유 런타임)이며, 보안 패치가 자동으로 적용되고 디스크 소비도 작기 때문에 공식에서 명확히 권장합니다. Windows 11에는 기본 탑재되어 있지만 미도입 단말도 있으므로 설치 프로그램에서 존재 확인과 bootstrap을 넣습니다. Fixed Version(앱 동봉)은 동봉물이 250MB를 넘고, 브라우저 엔진의 취약점 수정을 자신의 릴리스로 배포할 책임을 지게 되므로, 오프라인 제조 장치나 변경 관리가 엄격한 환경 등 한정적인 장면에서만 선택해야 합니다.
- WebView2 앱이 설치 후 시작되지 않는 이유는 무엇입니까?
- 처음에 빠지기 쉬운 전형이 사용자 데이터 폴더(UDF) 문제입니다. WebView2는 Cookie·캐시·권한을 UDF에 저장하지만, 위치를 지정하지 않으면 기본적으로 exe 옆에 만들려고 하므로 Program Files 아래에 설치한 앱에서는 쓰기에 실패하고 초기화 오류가 납니다. 개발 머신에서는 동작하는데 설치하는 순간 동작하지 않는, 전형적인 장애입니다. 대책은 CoreWebView2Environment 생성 시 %LOCALAPPDATA% 아래의 앱 전용 폴더를 항상 명시적으로 지정하는 것입니다. 네트워크 드라이브에 두는 것도 속도 저하·손상의 원인이 되므로 피합니다.
- WebView2에서 네이티브 코드와 Web 페이지는 어떻게 연동합니까?
- 기본은 Web 메시지에 의한 느슨한 결합 연동입니다. 네이티브 측에서 PostWebMessageAsJson으로 JSON을 보내고, Web 측은 window.chrome.webview의 message 이벤트로 받습니다. 반대 방향은 postMessage와 WebMessageReceived 이벤트입니다. 수신 측에서는 e.Source로 발신원 URI를 검사하고, 메시지의 type을 화이트리스트로 검사하는 것이 중요합니다. AddHostObjectToScript로 .NET/COM 객체를 직접 공개하는 방법도 있지만, 페이지가 침해되었을 때의 영향이 크므로 자사 관리 콘텐츠에 한정하고 공개 메서드를 최소한으로 줄여야 합니다.