멀티 webview / WebContentsView
This content is not available in your language yet.
한 OS 창 안에 여러 web 콘텐츠를 합성하는 패턴. 멀티탭 브라우저 / 사이드바 + 메인 (다른 origin) / OAuth 인-라인 / 위젯 임베드 같은 use case에 사용된다.
현 상태: macOS/Linux/Windows 기본 경로는 CEF Views 기반
windows.createView다. 한 창 안에 child WebContentsView를 합성하고, viewId는 windowId와 같은 id 풀을 공유해 기존windows.*webContents API를 그대로 사용할 수 있다. host와 child WebContentsView는 모두 CEF-managedCefWindow + CefBrowserView기반으로 동작한다. macOS child는 hostNSWindow에 attach되고, Linux/Windows child는 CEF overlay view로 붙는다. macOS/Linux/Windows 모두에서createView/bounds/visibility/destroy가 동작한다.
다른 프레임워크는 어떻게 하나
섹션 제목: “다른 프레임워크는 어떻게 하나”Electron
섹션 제목: “Electron”| API | 상태 |
|---|---|
<webview> tag | 별도 OS process 격리 — 강력하지만 복잡, deprecation 검토 |
BrowserView | 한 BrowserWindow에 합성 (deprecated, WebContentsView로 이행) |
WebContentsView (Electron 30+) | 한 BrowserWindow에 여러 web content 합성, 현재 권장 |
Tauri v2
섹션 제목: “Tauri v2”v1까지는 WebviewWindow 한 묶음만 있었음 (별도 창만). v2부터 Window와 Webview가 분리:
let window = tauri::WindowBuilder::new(app, "main").build()?;
let webview = tauri::WebviewBuilder::new("child", WebviewUrl::App("page.html".into())) .build()?;window.add_child( webview, LogicalPosition::new(0, 100), // 부모 창 안 절대 좌표 LogicalSize::new(800, 500),)?;JS:
import { Webview } from '@tauri-apps/api/webview';import { Window } from '@tauri-apps/api/window';
const win = Window.getCurrent();const webview = new Webview(win, 'child', { url: 'page.html' });await webview.setSize({ width: 800, height: 500 });await webview.setPosition({ x: 0, y: 100 });격리: WKWebView (macOS) / WebView2 (Windows) / WebKitGTK (Linux) — 각 webview가 OS-level 별도 process. 각자 history/cookies/JS context 분리.
한계: 절대 좌표 기반 (CSS layout 아님). 부모 창 resize 시 사용자가 좌표 갱신 필요.
Suji 구현 상태
섹션 제목: “Suji 구현 상태”API
섹션 제목: “API”import { windows } from '@suji/api';
const { viewId } = await windows.createView({ hostId: parentWindowId, url: 'page.html', bounds: { x: 0, y: 100, width: 800, height: 500 },});
await windows.setViewBounds(viewId, { x: 0, y: 100, width: 1024, height: 600 });await windows.setViewVisible(viewId, false); // 탭 전환에 활용await windows.addChildView(parentWindowId, viewId);await windows.setTopView(parentWindowId, viewId);const { viewIds } = await windows.getChildViews(parentWindowId);await windows.loadURL(viewId, 'https://example.com'); // 기존 windows.* 동일await windows.executeJavaScript(viewId, "document.title");
await windows.destroyView(viewId); // child target 정리, host/남은 view 생존구현 — CEF Views 기반
섹션 제목: “구현 — CEF Views 기반”현재 구현은 host와 child WebContentsView를 모두 CEF-managed CefWindow + CefBrowserView
기반으로 만든다.
| 단계 | 동작 |
|---|---|
| 1 | host 창은 CefWindow + CefBrowserView로 생성 |
| 2 | macOS child view는 별도 CefWindow + CefBrowserView로 생성 후 host NSWindow에 attach |
| 3 | Linux/Windows child view는 CefWindow.add_overlay_view(..., CEF_DOCKING_MODE_CUSTOM)로 attach |
| 4 | viewId 발급 — windowId namespace에 통합 (windows.* 모든 webContents API가 windowId 또는 viewId 받음) |
| 5 | setViewBounds는 child frame/bounds를 host content 좌표계 기준으로 변경 |
| 6 | z-order는 addChildView / setTopView / removeChildView로 관리 |
| 7 | destroyView는 대상 child window만 닫고, host 창 close 시 남은 child view 자동 정리 |
알려진 한계
섹션 제목: “알려진 한계”- CEF Views 기반 구현: CEF Views API(
CefWindow+CefBrowserView)를 사용해 multi-WebContentsView lifecycle을 구현했다.destroyView후 child target 제거, host 생존, 남은 view 생존, recreate가 macOS/Linux/Windows에서 동작한다.
격리 강도
섹션 제목: “격리 강도”| 격리 단위 | history/cookies | JS context | |
|---|---|---|---|
| Electron BrowserView | webContents | 별도 (또는 공유 — partition 옵션) | 별도 |
| Tauri v2 Webview | OS process (WKWebView/WV2) | 별도 | 별도 |
| Suji | CEF browser / CefBrowserView | 별도 (each browser has own request context) | 별도 |
CEF는 default가 single process로 multiple browser 운영. 격리는 webContents 단위 — Electron WebContentsView와 유사하다. Tauri의 OS process 격리보단 약간 약하지만 일반 데스크톱 앱에는 충분하다.
Use case 판단 기준
섹션 제목: “Use case 판단 기준”| Use case | 권장 |
|---|---|
| 자체 frontend만 + multi-window UI | windows.create({url}) 충분 (이미 됨) |
| 한 창에 사이드바 + 메인 (같은 origin) | iframe (표준 HTML, 격리 약하지만 same-origin이라 OK) |
| 한 창에 사이드바 + 메인 (다른 origin) | windows.createView 필요 (또는 별도 창) |
| 멀티탭 브라우저 앱 | windows.createView 필요 (각 탭이 view) |
| OAuth 인-라인 로그인 페이지 | 별도 창 OR windows.createView |
| 광고/위젯 임베드 (격리 강함) | windows.createView |
| 외부 untrusted iframe | iframe + sandbox 속성 |
대부분의 데스크톱 앱은 multi-window로 충분하다. windows.createView는 한 창 안에서
dynamic destroy가 필요한 멀티탭/브라우저형 앱을 포함해 macOS/Linux/Windows에서 사용할 수 있다.