CEF 베팅: Deno Desktop의 중용

CEF 베팅: Deno Desktop의 중용

DenoDesktopCEFElectronTauri

데이터 소스:HN + Lobsters · HN

2026년 6월, Deno는 v2.9.0에서 deno desktop을 공식 발표했다 — 한 줄의 명령어로 모든 TypeScript 프로젝트(단일 파일 스크립트, Next.js 앱, 심지어 HTTP 서버까지)를 macOS .app, Windows .exe, Linux AppImage로 패키징한다. HN에서 997점, 365개 댓글, Lobsters △34를 기록했다. 점수가 높은 것은 Deno의 명성 때문만이 아니다 — 댓글에서 가장 격렬한 논의는 Deno가 내린 하나의 기술적 선택에 집중되었다: Tauri처럼 시스템 WebView에 의존하는 대신, 기본적으로 CEF(Chromium Embedded Framework)를 번들링하기로 한 결정.

이 선택은 커뮤니티에서 갈채와 의문을 동시에 받았다. 갈채는 Linux에서 webkitgtk로 고생한 개발자들로부터 나왔고, 의문은 “시스템에 내장된 브라우저 엔진을 왜 사용하지 않는가”라고 생각하는 사람들로부터 나왔다. 두 목소리 모두 타당하며, Deno의 선택은 정확히 그 중간에 서 있다.

Electron의 200MB 저주

Electron이 데스크톱 애플리케이션 개발을 지배하는 이유는 간단하다: HTML/CSS/JS로 UI를 작성하고, Node.js로 시스템 API를 호출하며, 하나의 코드베이스로 Windows/macOS/Linux에서 실행된다. 대가도 간단하다: 각 Electron 애플리케이션은 독립적으로 배포되는 Chromium 브라우저 복사본에 Node.js 런타임을 더한 것으로, 기본 150MB에서 최대 250MB까지 올라간다. Slack, VS Code, Discord, Figma — 당신의 하드디스크에 다섯 개의 Electron 앱이 있다면, 다섯 개의 Chromium을 저장하고 있는 셈이다.

이것은 단순한 디스크 공간 낭비가 아니다. 각 Electron 앱은 각자 브라우저 프로세스 세트 — GPU 프로세스, 렌더러 프로세스, 네트워크 프로세스 — 를 시작하므로 메모리 사용량이 선형으로 누적된다. 하나의 Chrome 탭이 약 100MB의 메모리를 사용하는데, 세 개의 Electron 앱이 동시에 실행되면 1.5GB 이상을 쉽게 소모한다. 사용자는 “왜 내 노트 앱이 IDE보다 더 많은 메모리를 먹는 거지?”라고 느끼지만, 진실은 노트 앱이 IDE 수준의 브라우저 호스트이며, 단지 <textarea>를 실행하고 있을 뿐이라는 것이다.

Electron 팀이 이 문제를 모르는 것은 아니다. 그들은 여러 Electron 앱이 하나의 Chromium 동적 라이브러리를 공유하도록 하는 electron-shared-library 실험을 했지만, 결국 실현되지 않았다. 근본적인 장벽은 기술이 아니라 — 각 앱의 버전 의존성 지옥에 있다. 앱 A는 Electron 28에 의존하고, 앱 B는 Electron 31에 의존한다면, Chromium의 업데이트 주기(4주마다 메이저 버전)에서 공유 라이브러리의 ABI 호환성은 유지가 거의 불가능하다. Linux 배포판의 패키지 관리자는 “전체 배포판을 하나의 버전 스냅샷에 고정”하는 방식으로 이 문제를 해결하지만, 데스크톱 앱에는 이런 사치가 없다 — 사용자가 Discord 업데이트 때문에 VS Code도 강제 업그레이드하도록 요구할 수는 없다.

Tauri의 시스템 WebView 접근법: 이념은 옳았지만, 현실은 잔혹했다

Tauri는 다른 길을 갔다. 핵심 통찰은: 운영체제에 이미 브라우저 엔진이 내장되어 있는데, 왜 다시 배포하는가? macOS에는 WKWebView, Windows에는 WebView2, Linux에는 webkit2gtk가 있다. Tauri의 바이너리 크기는 극히 작다 — 기본 10MB 미만 — 렌더링 엔진이 전적으로 운영체제에 위임되기 때문이다. 백엔드는 Rust로 작성되고, 프론트엔드는 모든 JS 프레임워크가 가능하며, IPC는 Tauri의 커스텀 브릿지를 통해 이루어진다.

이 이념은 Windows에서 잘 작동한다. WebView2는 Edge Chromium 기반이며, Microsoft가 Windows Update를 통해 업데이트를 푸시하므로 버전이 비교적 최신이고 호환성이 좋다. 문제는 macOS와 Linux에서 발생한다.

macOS의 WKWebView는 운영체제 버전에 결합되어 있다. 즉, 사용자가 여전히 macOS 13에 머물러 있다면, Tauri 앱은 macOS 13에 해당하는 WebKit 버전으로 실행된다 — 이 버전은 최신 Safari보다 두세 개의 메이저 버전 뒤쳐질 수 있다. 새로운 CSS 기능이 지원되지 않고, 새로운 Web API가 노출되지 않으며, 일부 Canvas/WebGL 동작이 Chrome과 일치하지 않는다. Tauri 개발자는 이에 대해 아무것도 할 수 없다 — 사용자 머신의 시스템 WebKit을 교체할 능력도 없고 그렇게 해서도 안 된다. Apple의 WKWebView 업데이트 주기는 전적으로 앱 개발자의 통제 밖에 있다.

Linux 상황은 더 나쁘다. Linux에는 “시스템 브라우저 엔진”이라는 개념이 없다 — 서로 다른 데스크톱 환경, 다른 GTK 버전, 다른 배포판이 패키징한 webkit2gtk 버전이 각기 다르다. HN의 Deno Desktop 댓글에서, Tauri 장기 사용자인 echelon은 자주 인용되는 평가를 남겼다: webkitgtk는 “느리고 메모리를 많이 먹는다”. 이것은 개인적인 불만이 아니다 — Tauri의 GitHub Issue #3988과 #7021은 Linux에서 webkit2gtk가 많은 DOM 요소 시나리오에서 심각한 성능 저하를 겪고 있음을 기록하고 있다. 여기에는 스크롤 끊김, 렌더링 프레임 드롭, WebKit 2.40에서 도입된 알려진 성능 회귀가 포함된다.

Tauri가 Linux에서 직면하는 진짜 문제는: 의존할 만한 렌더링 엔진이 아예 없다는 것이다. webkit2gtk는 WebKitGTK 커뮤니티가 유지 관리하며, 개발 리소스는 Chromium 팀에 비해 훨씬 부족하다 — Chromium은 Google의 전임 엔지니어 팀과 보안 연구원이 있지만, WebKitGTK의 핵심 유지 관리자는 한 손으로 셀 수 있다. 이것은 WebKitGTK 개발자의 능력을 폄하하는 것이 아니다 — 그들은 존경할 만한 일을 하고 있다 — 하지만 병력 비교는 객관적인 사실이다.

Deno의 선택: CEF 번들링, 그러나 독점은 아니다

Deno Desktop은 세 번째 길을 선택했다. 기본적으로 CEF(Chromium Embedded Framework)를 사용한다 — Electron과 마찬가지로 Chromium 기반이지만, 두 가지 중요한 차이점이 있다.

첫째, CEF는 순수 브라우저 엔진이며 Node.js를 포함하지 않는다. Electron의 번들은 Chromium 렌더링 엔진과 Node.js 런타임을 모두 포함하며, 둘은 libnode를 통해 깊이 결합되어 있다. Deno Desktop의 아키텍처는 다르다: Deno 자체가 JS/TS 런타임(V8 기반)이고, CEF는 HTML/CSS/JS 프론트엔드 페이지 렌더링만 담당한다. Deno 프로세스는 CEF 내부에서 실행되지 않는다 — 독립 프로세스로 로컬 HTTP 서버를 시작하고, CEF 창이 http://localhost:<port>를 로드하여 UI를 렌더링한다. 프론트엔드-백엔드 통신은 일반 HTTP/WebSocket을 통해 이루어지며, Electron의 ipcMain/ipcRenderer와 같은 프로세스 내 브릿지가 아니다.

이 아키텍처 선택의 직접적인 결과는: Deno Desktop 애플리케이션이 다른 렌더링 백엔드로 전환할 수 있다는 것이다. Deno는 세 가지 backend를 지원한다: cef(기본값), webview(시스템 WebView), winit(순수 Rust 창, 게임/그래픽 앱에 적합). CEF는 공식 권장 기본값이지만, 호환성이 중요하지 않다면 더 작은 바이너리 크기를 위해 webview로 전환할 수 있다. 이러한 유연성은 Electron에는 없다 — Electron의 Chromium 바인딩이 너무 깊어서 “전환”이 불가능하다.

둘째, Deno의 공개 로드맵에는 명확히 쓰여 있다: 공유 CEF runtime. 현재 각 Deno Desktop 앱은 여전히 자체적으로 CEF 동적 라이브러리를 번들링하지만, Deno 팀은 미래에 “호스팅된 공유 runtime”을 구현할 계획이다 — 여러 Deno Desktop 앱이 머신 상의 하나의 CEF 설치를 공유하는 방식이다. 이 방향은 Electron이 시도했지만 포기한 shared-library 실험과 같지만, Deno에는 Electron이 없는 이점이 있다: 모든 Deno Desktop 앱이 동일한 runtime 버전 관리 프레임워크 아래에서 실행된다. Deno의 버전 업데이트 메커니즘은 “당신의 머신에 두 개의 Deno Desktop 앱이 설치되어 있다면, 그것들이 사용하는 CEF 버전이 Deno에 의해 통일적으로 관리된다”는 것을 보장할 수 있다 — 마치 시스템 수준의 패키지 관리자가 공유 라이브러리 버전을 관리하는 것처럼. 이것은 아직 해결된 문제가 아니다 — 로드맵의 항목이 인도물과 같은 것은 아니다 — 하지만 방향은 옳다.

CEF의 기술적 특징

CEF 자체는 매우 성숙도가 높은 프로젝트다. Spotify 데스크톱 클라이언트, Adobe Creative Cloud의 일부 구성 요소, Epic Games Launcher, OBS Studio의 브라우저 소스 — 이들 모두 CEF를 사용하여 Chromium을 내장하고 있다. 멀티 프로세스 아키텍처는 Chrome과 동일하다: 하나의 browser 프로세스가 창과 네트워크를 관리하고, 각 페이지 인스턴스는 독립적인 renderer 프로세스에서 실행되며, GPU 프로세스가 합성과 하드웨어 가속을 담당한다. 이러한 아키텍처로 인한 격리성은 Deno의 보안 모델과 상호 보완적이다 — Deno는 기본적으로 파일 시스템/네트워크/환경 변수 접근을 금지하며, CEF의 샌드박스 renderer 프로세스는 프론트엔드 코드의 탈출 표면을 더욱 제한한다.

CEF는 오프스크린 렌더링(OSR)도 지원한다. 일반 모드에서 CEF는 네이티브 창을 생성하고 그 안에서 렌더링한다. OSR 모드에서는 렌더링 결과가 메모리 버퍼로 출력되고, 호스트 애플리케이션이 표시 방법을 결정한다. 이 기능은 Deno Desktop의 winit backend에 중요하다 — 미래에 Deno가 완전히 커스터마이즈 가능한 UI 프레임워크(GPU 기반 UI 등)를 지원하려면, CEF의 OSR 모드가 웹 콘텐츠를 텍스처로 렌더링 파이프라인에 직접 입력할 수 있기 때문이다.

하지만 CEF에도 대가가 있다. CEF 동적 라이브러리(libcef.so)의 크기는 약 150MB이며, Chromium 리소스 파일(.pak, icudtl.dat, locales)을 더하면 총 디스크 사용량은 약 200MB다. Electron과 비슷하다. 바이너리 크기만 보면 Deno Desktop + CEF는 Electron보다 가볍지 않다 — 여기에 장점이 있는 것이 아니다. 장점은 두 가지다: 첫째, CEF는 공유될 수 있지만 Electron의 Node.js+Chromium 결합체는 공유하기 어렵다. 둘째, Deno는 극한의 작은 크기를 위해 webview backend로 낮출 수 있지만, Electron에는 이 옵션이 없다.

세 방식 비교

세 가지 방식을 하나의 표로 비교하면 각각의 트레이드오프가 더 명확해진다.

차원ElectronTauriDeno Desktop (CEF)
렌더링 엔진Chromium 번들시스템 WebViewCEF 번들 (시스템 WebView로 전환 가능)
백엔드 언어Node.js (JS)RustDeno (JS/TS)
바이너리 크기150-250 MB3-15 MB200 MB (CEF 모드) / 15 MB (webview 모드)
macOS 호환성최신 Chromium, OS 제약 없음시스템 WKWebView 버전에 제약됨최신 CEF, OS 제약 없음
Linux 호환성일관됨webkit2gtk 의존, 성능/호환성 변동 심함일관됨 (자체 CEF)
프로세스 모델Main + Renderer (Node.js와 Chromium 깊이 결합)Rust 메인 프로세스 + 시스템 WebView 프로세스Deno HTTP 서버 프로세스 + CEF browser/renderer 프로세스
공유 엔진 잠재력낮음 (버전 파편화 심각)자연 공유 (시스템 엔진 사용)중간 (로드맵에 공유 runtime 계획 있음)
프론트엔드 프레임워크 지원모든 JS 프레임워크모든 JS 프레임워크모든 JS 프레임워크 (Next.js 등 풀스택 포함)
업데이트 메커니즘자체 구축 필요자체 구축 필요내장 (Deno Deploy 스타일 핫 업데이트)

이 표에서 가장 오해하기 쉬운 것은 “바이너리 크기” 행이다. Deno Desktop이 CEF 모드에서 200MB인 것은 Electron만큼 나빠 보이지만, 핵심 차이는 이 200MB 중 어느 부분이 “변경 가능한 코드”이고 어느 부분이 “공유 가능한 엔진”인지에 있다. Electron의 200MB 중 Chromium + Node.js가 약 180MB를 차지하며, 각 앱이 독립적으로 패키징된다. Deno Desktop의 200MB 중 CEF도 약 150MB이지만, Deno의 공유 runtime 로드맵은 이 부분이 미래에는 하나만 저장하면 된다는 것을 의미한다. 공유 runtime이 실현되기 전까지, Deno Desktop은 크기 면에서 Electron을 이기지 못한다. 공유 runtime이 실현된 후에는, 각 앱의 증분 크기를 수 MB로 압축할 잠재력이 있다 — Tauri가 오늘날 이미 하고 있는 것처럼, 그러나 렌더링 엔진의 일관성을 희생하지 않으면서.

공유 의존성: 데스크톱 앱이 잊어버린 Linux의 지혜

Linux 배포판은 패키지 관리자로 공유 의존성 문제를 30년 동안 해결해왔다. libssl.so, libgtk.so, libc.so — 시스템에는 항상 하나의 복사본만 있고, 모든 앱이 동일한 복사본에 링크된다. 버전 업그레이드는 패키지 관리자가 조정하고, ABI 호환성은 배포판 수준에서 보장된다. 이 시스템은 너무나 잘 작동해서, Linux 사용자는 “각 앱이 자체 OpenSSL을 가지고 오는” 것에 본능적인 거부감을 느낀다.

왜 데스크톱 앱이 이 바퀴를 다시 발명해야 하는가? 근본 원인은 기술적 미숙함이 아니라 신뢰 모델의 차이에 있다. Linux 패키지 관리자가 작동할 수 있는 전제는 모든 패키지의 버전 일관성을 책임지는 중앙 권위(배포판 유지 관리자)가 있다는 것이다. 데스크톱 앱 생태계에는 이 중앙 권위가 없다 — VS Code는 Microsoft가, Discord는 Discord 회사가, Figma는 Figma 회사가 발행하며, 그들 사이에는 어떤 조정 메커니즘도 없다. 각 앱 개발자는 “사용자 머신에 무엇이 있는지 나는 모른다”고 가정할 수밖에 없으며, 따라서 가장 보수적인 전략을 선택한다: 필요한 모든 것을 패키징한다.

Deno Desktop의 공유 CEF runtime 계획은 이 두 극단 사이에서 중간 지점을 찾으려 한다: 시스템 수준의 전역 공유(운영체제 수준의 조정 필요)를 하지 않고, Deno 생태계 내의 호스팅된 공유만 수행한다. deno desktop을 통해 빌드되고 배포되는 모든 앱의 CEF 버전은 Deno의 통합 버전 관리자에 의해 제어된다. 이것은 Flatpak의 runtime 메커니즘(여러 Flatpak 앱이 하나의 KDE/GNOME runtime을 공유)과 비슷하지만, 더 세분화되어 브라우저 엔진만 공유한다.

이 길이 성공할 수 있을지는 두 가지 변수에 달려 있다: 첫째, Deno Desktop 생태계가 공유가 의미 있을 만큼 충분히 많은 앱을 키울 수 있는지(단 세 개의 Deno Desktop 앱만 있다면 공유 runtime의 이점은 미미하다). 둘째, CEF의 ABI 안정성이 “여러 앱이 동일한 CEF에 의존하지만 업데이트 주기가 다른” 상황을 견딜 수 있는지. CEF의 API 안정성은 Chromium 자체보다 낫다 — CEF의 API wrapper 계층이 많은 버퍼링을 제공한다 — 하지만 절대적인 것은 아니다. CEF 메이저 버전 업그레이드 시, 공유 runtime 관리자가 “앱 A는 새 버전과 호환되지만 앱 B는 구 버전만 호환되는” 상황을 어떻게 처리할지, 현재 Deno 팀은 공개된 기술方案이 없다.

이 베팅의 승패

echelon의 HN 댓글은 Deno가 CEF를 선택한 것이 왜 올바른 방향인지 지적했다: Tauri의 macOS와 Linux 시스템 WebView 경험이 너무 고통스럽기 때문이다. Tauri의 이념은 깔끔하다 — 시스템 네이티브를 사용하고 중복 바이너리를 배포하지 않는다 — 하지만 현실은 macOS의 WKWebView 업데이트 주기는 Apple이 결정하고, Linux의 webkit2gtk 품질은 소규모 오픈소스 커뮤니티가 보장한다. 이념의 깔끔함이 구현의 거칠기를 보상하지는 못한다 — 사용자는 “이 앱이 Linux에서 너무 느려서 쓸 수 없어”만 기억할 뿐, “이 앱이 시스템 WebView를 사용해서 공간을 절약했어”에는 신경 쓰지 않는다.

Deno의 CEF 접근법은 이념의 순수성을 포기하고 구현의 제어 가능성을 얻었다. 그것은 당혹스럽지만 실제적인 공학적 사실을 인정했다: 크로스플랫폼 데스크톱 앱 영역에서, 제어 가능성이 크기보다 더 중요하다. 당신이 제어할 수 없는 플랫폼에서 렌더링 엔진이 일관되게 작동하지 않는다면, 절약한 디스크 공간은 호환성 문제를 해결하는 데 소모되는 개발 시간에 배로 상쇄된다.

하지만 Deno도 크기 최적화를 포기한 것은 아니다 — 공유 runtime 로드맵이 Electron과의 근본적인 차이점이다. 공유 CEF runtime이 성공적으로 실현된다면, Deno Desktop은 “렌더링 엔진 일관성”(CEF 번들링에서)과 “작은 증분 크기”(공유 아키텍처에서)를 동시에 가질 수 있다. 이것은 Electron(일관성만 있고 작은 크기는 없음)과 Tauri(Windows에서는 작은 크기만 있고 macOS/Linux에서는 일관성 없음)가 각각 달성하지 못한 것이다.

물론, 로드맵 상의 것은 이미 인도된 것으로 평가할 수 없다. Deno Desktop은 현재 여전히 canary 버전이며, API가 안정화되지 않았고, 공유 runtime은 더욱 “미래 계획”이다. 이 분야에는 아름다운 아키텍처 그림이 항상 넘쳐난다 — 부족한 것은 공유 엔진 버전 관리라는 겉보기에는 간단해 보이지만 실제로는 지옥처럼 어려운 문제를 진정으로 공학적으로 실현할 수 있는 팀이다. Deno 팀은 이 능력을 갖추고 있다(Deno 자체의 버전 관리와 원격 모듈 캐싱 시스템은 참조할 수 있는 인프라다). 하지만 능력과 인도물 사이의 거리가 바로 베팅 그 자체다.