Webview vs BrowserView — 외부 콘텐츠 임베딩
"앱 안에 웹 페이지를 띄워야 할 때, iframe 대신 webview나 BrowserView를 쓴다" — 보안과 성능 면에서 차이가 있습니다.
세 가지 임베딩 방식 비교
| 방식 | 프로세스 | 보안 | 유연성 | 상태 |
|---|---|---|---|---|
<iframe> | 렌더러와 공유 | 낮음 | 제한적 | 사용 가능 |
<webview> | 별도 프로세스 | 높음 | 높음 | 비권장 (deprecated) |
BrowserView | 별도 프로세스 | 높음 | 보통 | Electron 30에서 제거 |
WebContentsView | 별도 프로세스 | 높음 | 높음 | Electron 30+ 권장 |
webview 태그
<!-- 렌더러 HTML에서 사용 -->
<webview
src="https://example.com"
style="width: 100%; height: 500px;"
preload="./webview-preload.js"
partition="persist:external"
webpreferences="contextIsolation=yes">
</webview>
// main.js — webview 활성화 필요
const win = new BrowserWindow({
webPreferences: {
webviewTag: true, // webview 태그 사용 허용
preload: path.join(__dirname, 'preload.js'),
},
});
webview 이벤트
const webview = document.querySelector('webview');
webview.addEventListener('did-start-loading', () => {
console.log('로딩 시작');
});
webview.addEventListener('did-finish-load', () => {
console.log('로딩 완료');
});
webview.addEventListener('did-fail-load', (event) => {
console.error('로딩 실패:', event.errorDescription);
});
// JavaScript 실행
const title = await webview.executeJavaScript('document.title');
// 네비게이션
webview.loadURL('https://example.com');
webview.goBack();
webview.goForward();
webview.reload();
WebContentsView (Electron 30+ 권장)
const { app, BaseWindow, WebContentsView } = require('electron');
app.whenReady().then(() => {
const win = new BaseWindow({ width: 1200, height: 800 });
// 메인 UI 뷰
const mainView = new WebContentsView({
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
});
win.contentView.addChildView(mainView);
mainView.setBounds({ x: 0, y: 0, width: 800, height: 800 });
mainView.webContents.loadFile('index.html');
// 외부 콘텐츠 뷰
const externalView = new WebContentsView({
webPreferences: {
// 외부 콘텐츠에는 제한된 권한
preload: path.join(__dirname, 'external-preload.js'),
sandbox: true,
},
});
win.contentView.addChildView(externalView);
externalView.setBounds({ x: 800, y: 0, width: 400, height: 800 });
externalView.webContents.loadURL('https://example.com');
// 윈도우 리사이즈 시 뷰 크기 조정
win.on('resized', () => {
const [width, height] = win.getSize();
mainView.setBounds({ x: 0, y: 0, width: width - 400, height });
externalView.setBounds({ x: width - 400, y: 0, width: 400, height });
});
});
보안 고려사항
// 외부 콘텐츠는 반드시 별도 세션 + 제한된 권한으로
const externalView = new WebContentsView({
webPreferences: {
sandbox: true,
contextIsolation: true,
nodeIntegration: false,
partition: 'persist:external', // 별도 세션
},
});
// 네비게이션 제한
externalView.webContents.on('will-navigate', (event, url) => {
const allowed = ['https://example.com'];
if (!allowed.some(a => url.startsWith(a))) {
event.preventDefault();
}
});
// 새 창 열기 차단
externalView.webContents.setWindowOpenHandler(() => {
return { action: 'deny' };
});
면접 포인트 정리
<webview>태그는 deprecated,WebContentsView로 마이그레이션 권장- 외부 콘텐츠는 반드시 별도 세션과 샌드박스로 격리
WebContentsView로 분할 화면(Split View) 구현 가능- 네비게이션 제한, 새 창 차단 등 보안 설정 필수
Webview 비교를 다뤘으면, 다음은 Electron 마이그레이션을 알아봅시다.
댓글 로딩 중...