몇년에 걸쳐 많은 시행차 끝에 구현한 일렉트론 IPC/이벤트 구조 소스

 

메인프로세스의 컨트롤러

/**
 * 애플리케이션의 핵심 컨트롤러
 *
 * @description
 * 메인 프로세스에서 앱의 전반적인 기능을 제어하는 컨트롤러입니다.
 * 윈도우 관리, 다크모드 설정, 앱 종료 등 핵심 기능들을 처리합니다.
 */
@ClassName('AppController', 'main')
@IPCHelper.Class()
export class AppController extends Controller {
    /**
     * 컨트롤러 초기화 메서드
     *
     * @description
     * 컨트롤러가 시작될 때 자동으로 실행되는 생명주기 메서드입니다.
     * 앱에 필요한 초기 설정과 리소스 할당을 처리합니다.
     *
     * @returns 초기화 완료 시 resolve되는 Promise
     */
    @Log('silly', '_onServiceStart')
    protected async _onServiceStart(): Promise<void> {
		//
    }

    /**
     * 컨트롤러 종료 메서드
     *
     * @description
     * 컨트롤러가 종료될 때 자동으로 실행되는 생명주기 메서드입니다.
     * 할당된 리소스 해제 및 정리 작업을 수행합니다.
     *
     * @returns 종료 처리 완료 시 resolve되는 Promise
     */
    @Log('silly', '_onServiceStop')
    protected async _onServiceStop(): Promise<void> {
		//
    }

    /**
     * 다크모드 상태 업데이트
     *
     * @description
     * 다크모드 상태 변경을 처리하고 관련 이벤트를 발생시킵니다.
     *
     * @param _sender IPC 이벤트 발신자
     * @param args 다크모드 설정값
     * @returns 업데이트된 다크모드 설정 객체
     */
    @Log('silly', 'onUpdateDarkMode')
    @EventHelper.Emit()
    @IPCHelper.Send()
    public async onUpdateDarkMode(_sender: Electron.WebContents | null, args: any): Promise<any> {
        // 전달받은 다크모드 설정을 이벤트로 전파
        return args;
    }
}

 

메인 프로세스의 서비스

/**
 * 앱 설정 관리 서비스
 *
 * @description
 * 앱의 전반적인 설정을 관리하는 핵심 서비스입니다.
 * YAML 형식의 설정 파일을 통해 앱의 상태를 영구적으로 저장하고 관리합니다.
 *
 * 주요 기능:
 * - 설정 파일 YAML 형식으로 저장/로드
 * - 다크모드/라이트모드 테마 전환 및 관리
 * - 윈도우 위치 및 크기 상태 관리
 */
@ClassName('AppConfigService', 'core')
@IPCHelper.Class()
export class AppConfigService extends Service {
    /**
     * 서비스 초기화
     *
     * @description
     * 앱 실행 시 최초로 호출되어 설정을 초기화합니다.
     * 설정 파일을 읽어 UI 테마와 상태를 설정하고 전역 상태 저장소에 적용합니다.
     *
     * @returns 초기화 완료 Promise
     */
    @Log('silly', '_onServiceStart')
    protected async _onServiceStart(): Promise<void> {
        //
    }

    /**
     * 서비스 종료
     *
     * @description
     * 서비스 종료 시 현재 앱 설정을 저장합니다.
     *
     * @returns 서비스 종료 완료 Promise
     */
    @Log('silly', '_onServiceStop')
    protected async _onServiceStop(): Promise<void> {
        //
    }

    /**
     * 다크모드 상태 확인
     *
     * @description
     * 현재 앱의 다크모드 상태를 반환합니다.
     *
     * @returns 다크모드 여부
     */
    public isDarkMode(): boolean {
        return nativeTheme.themeSource === 'dark';
    }

    /**
     * 다크모드 상태 변경
     *
     * @description
     * 앱의 테마를 다크모드 또는 라이트모드로 전환합니다.
     * 변경된 설정은 전역 상태 저장소에 저장되고 UI에 즉시 반영됩니다.
     *
     * @param _sender - 이벤트를 발생시킨 웹 컨텐츠 객체
     * @param isDarkMode - 다크모드 활성화 여부
     * @returns 변경된 다크모드 상태 객체 {isDarkMode: boolean}
     */
    @Log('silly', 'setDarkMode')
    @CtrlHelper.Method(AppController, 'onUpdateDarkMode')
    public setDarkMode(_sender: Electron.WebContents | null, isDarkMode: boolean): any {
        // 전역 상태 저장소에 다크모드 상태 업데이트
        useAppConfigStore.getState().appConfig.UI.isDarkMode = isDarkMode;

        // 시스템 테마 변경
        nativeTheme.themeSource = isDarkMode ? 'dark' : 'light';

        return { isDarkMode };
    }
}

 

 

렌더러에서의 호출

const isDarkMode = await window.APIv2.appConfigService('isDarkMode', {});

 

렌더러에서의 이벤트 수신

window.ipcRenderer.on(channel,  (_event: unknown, method: string, args: Record<string, unknown>) => {
    if (method === 'onUpdateDarkMode' && typeof args.isDarkMode === 'boolean') {
        setDarkMode(args.isDarkMode);
    }
});

 

 

이전에는 렌더러에서 호출하기 위해서 별도로 IPC 핸들러에 메서드를 등록하였지만,

이번에 수정한 버젼에서는 @IPCHelper.Class() 가 정의된 클래스 별다른 등록없이 바로 메서드 명으로 IPC통신을 할수 있음.

 

특히 렌더러에서 setDarkMode 를 호출한 경우 메인에서 setDarkMode 함수가 실행된 후 결과를

@CtrlHelper.Method(AppController, 'onUpdateDarkMode') 로 전달 AppController 클래스에 onUpdateDarkMode 메서드가 실행됨.

 

그러면, AppController 클래스에 onUpdateDarkMode 메서드가 실행된 후 @IPCHelper.Send('main') 에 의해 결과를 특정 윈도우나 @IPCHelper.Send() 원래 호출 했던 윈도우로 메세지를 발생시켜 되돌려 보낼수 있음.

또한 @EventHelper.Emit() 데코레이터에 의해 AppController 이 클래스의 이벤트를 구독하는 서비스나 컨트롤이 있다면 onUpdateDarkMode 이벤트를 수신할수 있음.

 

예제) 메인 윈도우

/**
 * 메인 윈도우 클래스
 *
 * @description
 * 애플리케이션의 주 윈도우를 관리하는 클래스입니다.
 * 윈도우 생성, 이벤트 처리, 렌더러 로딩 등을 담당하며
 * 앱의 메인 인터페이스를 제공합니다.
 */
@ClassName('MainWindow')
@CtrlHelper.Clsss(AppController)
export class MainWindow extends BaseWindow {
    /**
     * MainWindow 인스턴스를 생성합니다.
     *
     * @description
     * 기본 윈도우 설정을 초기화하고 공통 이벤트 핸들러를 등록합니다.
     * 생성된 윈도우는 초기에 숨김 상태이며, ready-to-show 이벤트 발생 시 표시됩니다.
     */
    constructor() {
        super({
            center: false,
            frame: false,
            titleBarStyle: 'hidden',
            show: false,
            icon: nativeImage.createFromPath(APP_CONSTANTS.RESOURCES.APP_ICON),
            width: 800,
            height: 600,
            title: 'Main Window'
        });
    }

    /**
     * 다크모드 상태 업데이트
     *
     * @description
     * 현재 테마에 맞춰 윈도우의 배경색을 업데이트합니다.
     *
     * @param _args - 다크모드 설정 정보
     * @param _args.isDarkMode - 다크모드 활성화 여부
     */
    @Log('silly', 'onUpdateDarkMode')
    public onUpdateDarkMode(_args?: { isDarkMode: boolean }): void {
        const appConfigService = ServiceManager.getInstance().get(AppConfigService);
        this.setBackgroundColor(appConfigService.getBackgroundColor());
    }
}