Appearance
Guards
Guard는 IPC 요청의 유효성을 검증하는 파이프라인이다. 모든 Guard가 통과해야 핸들러가 실행된다.
파이프라인 흐름
요청 → Guard(canActivate) → Pipe(transform) → Handler → 응답
↓ (실패) ↓ (에러) ↓ (에러)
ExceptionHandler ExceptionHandler ExceptionHandler
↓ ↓ ↓
응답 응답 응답- 모든 Guard의
canActivate()를 순서대로 실행한다 - Guard가
false를 반환하면 ExceptionHandler의catch()에 에러를 전달한다 - Guard 통과 후 Pipe를 실행한다
- Pipe 통과 후 핸들러를 실행한다
IpcContext
Guard와 ExceptionHandler에 전달되는 컨텍스트 객체:
ts
interface IpcContext {
event: IpcMainInvokeEvent; // Electron IPC 이벤트
channel: string; // IPC 채널 이름
window: BrowserWindow; // 요청을 보낸 윈도우 (미상 시 메인 폴백)
args: unknown[]; // 핸들러 인자
}IpcGuard 인터페이스
ts
interface IpcGuard {
canActivate(ctx: IpcContext): boolean | Promise<boolean>;
}커스텀 Guard 작성
ts
import type { IpcGuard, IpcContext } from '@repo/electron-ipc';
class AuthGuard implements IpcGuard {
canActivate(ctx: IpcContext): boolean {
// 인증된 요청만 허용
const token = ctx.args[0];
return typeof token === 'string' && isValidToken(token);
}
}SenderGuard
패키지에 내장된 Guard. IPC 메시지가 등록된 윈도우의 webContents에서 온 것인지 검증한다.
ts
import { SenderGuard } from '@repo/electron-ipc';
createApp({
guards: [new SenderGuard()],
// ...
});외부 웹 페이지를 최상위로 띄운 창(OAuth 팝업 등)도 BrowserWindow라 기본으로는 통과한다. 그런 창이 있으면 isAppWindow로 걸러낸다.
ts
createApp({
guards: [new SenderGuard({ isAppWindow: (win) => !isPopup(win) })],
// ...
});내부 구현:
ts
class SenderGuard implements IpcGuard {
canActivate(ctx: IpcContext): boolean {
const window = BrowserWindow.fromWebContents(ctx.event.sender);
// 본 앱 윈도우(메인 + 서브)의 최상위 webContents만 허용한다.
// 창에 얹힌 자식 뷰(WebContentsView 등)는 외부 웹 컨텐츠일 수 있어 거부한다.
if (window === null || window.webContents !== ctx.event.sender) return false;
return this.isAppWindow(window); // 기본은 모든 창 허용
}
}GuestViewGuard
SenderGuard의 대칭인 내장 Guard. 발신자가 본 앱 윈도우에 얹힌 자식 뷰(WebContentsView 등)인지 검증한다 — send 채널(게스트 → 메인 단방향)의 발신자 정책으로 sendGuards에 쓴다.
ts
import { GuestViewGuard } from '@repo/electron-ipc';
createApp({
guards: [new SenderGuard()], // handle: 앱 창만
sendGuards: [new GuestViewGuard()], // send: 게스트 뷰만
// ...
});내부 구현:
ts
class GuestViewGuard implements IpcGuard {
canActivate(ctx: IpcContext): boolean {
const window = BrowserWindow.fromWebContents(ctx.event.sender);
// 앱 창에 얹힌 자식 뷰만 허용 — 최상위 webContents(앱 UI)와
// 어느 창에도 속하지 않은 발신자는 거부한다.
return window !== null && window.webContents !== ctx.event.sender;
}
}contract에 sends가 있는데 sendGuards를 지정하지 않으면 부트스트랩 에러다 (기본 거부).
적용
Guard는 createApp()의 guards 배열로 전달한다. 배열 순서대로 실행되며, 하나라도 false면 즉시 중단한다.
ts
createApp({
guards: [new SenderGuard(), new AuthGuard()],
modules: [WindowModule, MyModule],
});다음 단계
- Pipes — Guard 이후 인자 변환과 검증
- Exception Handlers — Guard 실패와 핸들러 에러 처리
- API Reference — IpcGuard 전체 시그니처