01 — 프로세스 모델 (Process Model)
한 줄 답: Electron 앱 하나는 항상 Main 프로세스 1개 + Renderer 프로세스 N개 + Preload 컨텍스트 N개 + Utility/GPU 등 보조 프로세스 몇 개의 트리다. 각 프로세스는 권한이 다르고, 통신은 IPC로만 한다 — Chromium의 사이트 격리를 데스크톱 OS 권한 경계로 확장한 모델이다.
웹 브라우저도 내부적으로 멀티프로세스다. 하지만 개발자는 그 사실을 모른다 — 탭 하나가 하나의 origin 안에서 동작하고, 프로세스 분리는 브라우저가 알아서 한다. Electron의 본질적 차이는 — 그 분리를 개발자가 직접 설계해야 한다는 것이다. 어떤 코드가 어디 살지, 어떤 권한을 가질지, 어떤 채널로 대화할지를 내가 결정한다.
이 챕터는 그 결정을 위한 프로세스별 책임 지도다.
챕터 지도
Why — 왜 멀티프로세스가 별도 챕터인가
세 가지 이유.
- 권한이 프로세스 경계로 갈린다. Renderer에서
require('fs')가 막혀 있는 것은 문법 규칙이 아니라 프로세스 sandbox다. 어떤 프로세스에 있는지가 그 코드가 할 수 있는 일을 정한다. - 이 모델을 모르고 짜면 모든 챕터가 무너진다. IPC(03)도 보안(05)도 패키징(06)도 Main/Renderer/Preload의 역할 분담을 전제한다.
- 웹과 가장 다른 지점이다. SPA를 그대로 옮기는 사람이 가장 자주 트는 곳이 여기다 — “왜
window.fs가 없죠?”, “왜 한 창에서 다른 창 함수를 못 부르죠?”
이 챕터를 끝내면 “내 코드는 어느 프로세스에 살아야 하는가?” 라는 질문을 자동으로 던지게 된다. 그게 Electron 멘탈 모델의 시작이다.
6개 본문 — 인덱스
| # | 문서 | 한 줄 답 | 핵심 키워드 |
|---|---|---|---|
| 01 | 왜 멀티프로세스인가 | 브라우저는 몰래 멀티프로세스지만 Electron은 드러난 멀티프로세스다 — Chromium의 사이트 격리를 OS 권한 경계로 확장했다. | Chromium · site isolation · process per site · 보안·안정성 트레이드오프 |
| 02 | Main 프로세스 | Main은 Node 전권을 가진 단 하나의 오케스트레이터 — app 인스턴스·BrowserWindow·OS 이벤트·시스템 트레이를 모두 책임진다. | app · BrowserWindow · requestSingleInstanceLock · ready · before-quit |
| 03 | Renderer 프로세스 | Renderer는 Chromium 탭 한 개다 — V8로 격리되고 sandbox가 기본 ON이며 fs도 process도 직접 못 본다. | webContents · V8 isolate · sandbox · contextIsolation · DOM |
| 04 | Preload 스크립트 | preload는 Renderer 시작 직전에 한 번 뛰는 특권 컨텍스트 — contextBridge로 좁은 API만 메인 월드에 노출하는 유일한 안전 통로. | contextBridge · isolated world · exposeInMainWorld · ESM preload |
| 05 | Utility & GPU 프로세스 | 무거운 Node 작업은 UtilityProcess로 분리하고, GPU·zygote는 Chromium이 알아서 띄운다 — Main을 가볍게 유지하는 방법. | UtilityProcess · MessageChannel · GPU process · zygote · child_process |
| 06 | 프로세스 관계 & crash 격리 | Main이 죽으면 앱이 죽는다, Renderer가 죽으면 그 창만 죽는다 — render-process-gone 이벤트로 복구할 수 있다. | process tree · child-parent · render-process-gone · child-process-gone · crash 격리 |
What-if — 이 모델을 모르고 쓰면
| 실수 | 결과 | 어디서 다루나 |
|---|---|---|
Renderer에서 require('fs') 시도 | 동작 안 함(Cannot find module 'fs') → 검색해서 nodeIntegration: true 켬 → XSS = RCE 위험 | 03, 05 |
| 무거운 zip 압축을 Main에서 동기 실행 | OS 이벤트 루프 막힘 → 전체 앱 freeze (모든 창이 멈춤) | 02, 05 |
| 창마다 다른 preload 만들고 동기화 안 함 | 어떤 창은 API 있고 어떤 창은 없음 → 디버깅 지옥 | 04 |
app.requestSingleInstanceLock() 빼먹음 | 사용자가 더블클릭 두 번 → 인스턴스 두 개 → DB 파일 락 충돌 | 02 |
| Renderer crash 처리 안 함 | 흰 화면만 보이고 사용자가 앱 자체를 강제 종료 | 06 |
How — 어떻게 읽나
- 처음 Electron을 보는 사람: 01 → 02 → 03 → 04 순서대로. 왜 셋이 분리되었는지가 핵심.
- 이미 쓰고 있는데 구조가 어수선한 사람: 02·03을 다시 읽고 내 코드가 잘못된 프로세스에 살고 있지 않은지 점검.
- 무거운 작업 때문에 UI가 멈추는 사람: 02 끝 → 05.
- 앱이 가끔 흰 화면 되는 사람: 06.
다음 챕터로: 이 챕터가 프로세스를 분리한 이유를 다뤘다면, 02 — 창과 라이프사이클은 그 분리된 프로세스를 OS 창에 어떻게 묶는지를 본다. 그리고 03 — IPC & Bridge에서 프로세스 간 대화의 문법이 등장한다.
한 단락 요약
Electron 프로세스 모델은 Chromium의 멀티프로세스 모델을 데스크톱 OS 권한 경계로 확장한 것이다. Main은 OS 전권을, Renderer는 Chromium 탭의 격리를, Preload는 그 둘 사이의 좁은 통로를 책임진다. 어떤 코드를 어느 프로세스에 둘 것인가가 Electron 설계의 첫 번째이자 가장 큰 결정이다 — 이 결정을 미루면 보안·성능·안정성 셋이 동시에 무너진다.