Skip to content

EventSource

EventSource는 메인 프로세스에서 렌더러로 이벤트를 push하는 경량 이벤트 버스다. contract의 forwards에 정의된 채널과 controller의 동명 메서드를 통해 프레임워크가 자동으로 webContents.send()를 호출한다.

EventSource<T>

Service가 도메인 이벤트를 발행하는 경량 이벤트 버스다.

ts
import { Injectable, EventSource } from '@repo/electron-ipc';

@Injectable()
class ThemeService {
  readonly themeChanged = new EventSource<ThemeInfo>();

  setTheme(theme: Theme) {
    // ... 테마 적용 로직
    this.themeChanged.emit(newThemeInfo);
  }
}
메서드설명
emit(data)이벤트를 발행한다. 등록된 모든 리스너에 데이터를 전달한다
subscribe(listener)리스너를 등록하고 해제 함수를 반환한다

Controller 연결

contract에서 forward를 정의하고, controller에서 같은 이름의 메서드가 EventSource<T>를 반환하면 프레임워크가 자동으로 구독한다.

ts
// 1. Contract에 forward 선언
const appContract = contract({
  handles: {},
  forwards: {
    onThemeChanged: forward<ThemeInfo>('theme:changed'),
  },
});

// 2. Controller에서 동명 메서드로 EventSource 반환
@Controller(appContract)
class ThemeController {
  private readonly theme = inject(ThemeService);

  onThemeChanged() {
    return this.theme.themeChanged; // EventSource<ThemeInfo>
  }
}

ControllerOf<typeof appContract>onThemeChanged()의 반환 타입을 EventSource<ThemeInfo>로 강제하므로 시그니처 mismatch는 IDE에서 잡힌다.

동작 흐름

  1. onWindowAttach 시점에 프레임워크가 contract.forwards를 순회하며 controller의 동명 메서드를 호출해 EventSource를 얻는다
  2. EventSource를 subscribe()하여 이벤트 발생 시 webContents.send(channel, data)를 호출한다
  3. 윈도우 closed 이벤트 시 구독이 자동 해제된다

이 패턴은 Service에서 OnWindowAttach 구현 + window 필드 + webContents.send() 직접 호출을 제거한다.

다음 단계