이벤트 & Electron 대응
This content is not available in your language yet.
이벤트 종류
섹션 제목: “이벤트 종류”창 라이프사이클 (WM이 발화)
섹션 제목: “창 라이프사이클 (WM이 발화)”| 채널 | payload | 발화 시점 |
|---|---|---|
window:created | {windowId, name?} | 창 생성 직후 |
window:close | {windowId, name?} | 창이 닫히기 직전 (cancelable 예정) |
window:closed | {windowId, name?} | 창이 실제로 파괴된 직후 |
window:all-closed | {} | 마지막 창이 닫힌 직후 (Electron canonical) |
created/close/closed 모두 {windowId, name?} 일관 포맷.
windowId는 항상 포함.name은 명명된 창에서만 (익명은 생략). JSON-unsafe 문자가 있으면 안전을 위해 생략.close/closed도 destroy 전에 name을 캡처해서 emit — 리스너가wm.get()조회 없이 분기 가능.
플러그인 예: state 플러그인이 window:closed 수신 → 해당 scope 정리:
suji.on('window:closed', ({ windowId }) => { state.clear({ scope: `window:${windowId}` });});Electron 패턴: all-closed → quit
섹션 제목: “Electron 패턴: all-closed → quit”// Frontendsuji.on('window:all-closed', () => { if (suji.platform !== 'macos') suji.quit();});// Zig backendfn onAllClosed(_: suji.Event) void { if (!std.mem.eql(u8, suji.platform(), suji.PLATFORM_MACOS)) suji.quit();}macOS는 창이 모두 닫혀도 앱은 dock에 유지 (Electron과 동일). 나머지 플랫폼은 종료.
Electron API 대응표
섹션 제목: “Electron API 대응표”| Electron | Suji |
|---|---|
ipcRenderer.invoke(ch, ...args) | suji.invoke(ch, data, options) — data는 단일 객체 |
ipcRenderer.send(ch, data) | suji.send(ch, data) |
ipcRenderer.on(ch, fn) | suji.on(ch, fn) |
ipcMain.handle(ch, (event, ...args) => {}) | 백엔드 handle(ch, (req, event) => {}) |
ipcMain.on(ch, fn) | 백엔드 on(ch, fn) |
event.sender / BrowserWindow.fromWebContents(e.sender) | event.window rich 객체 ({id, name}) |
win.webContents.send(ch, data) | suji.send(ch, data, {to: winId}) / Zig suji.sendTo(id, ch, data) |
BrowserWindow.getAllWindows() | (roadmap) suji.windows.all() |
app.quit() | suji.quit() |
process.platform | suji.platform — “macos” (not “darwin”) |
MessageChannelMain | 미지원 (V1) |
remote 모듈 | 미지원 (Electron도 deprecated) |
preload.js | 미지원 — Suji 렌더러는 Node 노출 자체가 없음 |
contextBridge | 미제공 — window.__suji__는 메인 월드 frozen bridge로 하드닝, 진짜 isolated-world는 roadmap |
Electron과의 차이 (주요)
섹션 제목: “Electron과의 차이 (주요)”1. invoke 인자 스타일: variadic → 단일 객체
섹션 제목: “1. invoke 인자 스타일: variadic → 단일 객체”// ElectronipcRenderer.invoke('save', filename, content, options)
// Sujisuji.invoke('save', { filename, content, options })이유: 크로스-언어 JSON 직렬화. Zig/Rust/Go/Node 백엔드가 같은 wire 포맷을 쓰려면 positional varargs보다 named 필드 객체가 자연스러움.
2. 핸들러 시그니처: (event, ...args) → (req, event)
섹션 제목: “2. 핸들러 시그니처: (event, ...args) → (req, event)”// ElectronipcMain.handle('save', (event, filename, content) => { const sender = event.sender;})// Suji (Zig)fn save(req: Request, event: InvokeEvent) Response { const filename = req.string("filename"); const sender_id = event.window.id;}- Suji는
req먼저 (주 데이터 우선),event둘째 (메타데이터) - Electron은
event먼저 (sender 강조) - 이유: Rust
#[handle]매크로 / Go 메서드 바인딩은 고정 arity가 단순
3. Wire 레벨 __window 자동 태깅
섹션 제목: “3. Wire 레벨 __window 자동 태깅”Electron은 프레임 ID를 V8 IPC에 암묵 전달 → handler 호출 시 event.sender로 풀음.
Suji는 JSON payload에 __window, __window_name 필드 자동 주입. event.window는
이 필드에서 파생된 편의 객체.
이점:
- 저수준 접근 필요한 플러그인은 wire 필드 직접 읽음 (JSON에 박혀있음)
- 크로스-언어에서 context 전파가 자연스러움 (V8 hidden context 같은 것 불필요)
- 로그/감사에서 “어느 창이 호출했는지” wire 레벨에서 확인 가능
4. 플랫폼 문자열: darwin → macos
섹션 제목: “4. 플랫폼 문자열: darwin → macos”Electron: "darwin" / "linux" / "win32"
Suji: "macos" / "linux" / "windows" — BSD 커널 이름이 아닌 사용자 친화적 OS 이름