1. Electron(React, Typescript) 프로젝트 생성
git clone --depth 1 --branch main https://github.com/electron-react-boilerplate/electron-react-boilerplate.git {PROJECT_NAME}
cd {PROJECT_NAME}
npm install
npm start
2. nodeIntegration 활성화한다.
- BrowserWindow의 속성 중 webPreferences > nodeIntegration을 true로 설정해준다.
mainWindow = new BrowserWindow({ show: false, width: 1024, height: 728, icon: getAssetPath('icon.png'), webPreferences: { nodeIntegration: true, preload: app.isPackaged ? path.join(__dirname, 'preload.js') : path.join(__dirname, '../../.erb/dll/preload.js'), }, });
3. preload.d.ts에 메소드 타입을 정의한다.
- 파일은 src/renderer/preload.d.ts에 있다.
import { Channels } from 'main/preload'; declare global { interface Window { electron: { ipcRenderer: { sendMessage(channel: Channels, args: unknown[]): void; on( channel: Channels, func: (...args: unknown[]) => void ): (() => void) | undefined; once(channel: Channels, func: (...args: unknown[]) => void): void; output(args: any[], func: (data: string) => void): void; input(args: any[], func: (data: string) => void): void; state(args: any[], func: (data: string) => void): void; }; }; } } export {};
4. preload.ts에 메소드 내용을 구현한다.
- 파일은 src/main/preload.ts에 있다.
- assets 경로 하위에 scripts/state.py 파일을 실행하는 내용으로 구현하였다.
- assets 내부의 스크립트를 실행하면 경로를 유의해야 한다. (getScriptPath 함수 참고)
- 디버깅 상태에서는 assets 경로 하위로 설정하면 된다.
- 빌드 상태에서는 process.resourcesPath 경로 하위로 설정하면 된다.
import { exec, spawn } from 'child_process'; import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron'; import path from 'path'; import process, { electron } from 'process'; import { dlog, isDebug } from 'utils/dev'; export type Channels = 'ipc-example'; const getScriptPath = (file_name: string) => { if (isDebug()) return `assets/scripts/${file_name}`; else { return path.join(process.resourcesPath, `assets/scripts/${file_name}`); } }; contextBridge.exposeInMainWorld('electron', { ipcRenderer: { ... state(args: any[], func: (data: string) => void) { const scriptPath = getScriptPath('state.py'); dlog(args[0], args[1]); exec( `python3 ${scriptPath} ${args[0]} ${args[1]}`, (err: any, stdout: any, stderr: any) => { dlog(err, stdout, stderr); func(stdout); } ); }, }, });
- assets 내부의 스크립트를 실행하면 경로를 유의해야 한다. (getScriptPath 함수 참고)
5. 렌더링 부분에서 명령을 호출한다.
window.electron.ipcRenderer
로 해당 함수를 불러올 수 있다.window.electron.ipcRenderer.state( [pin['fan'], pin['pump']], (data: string) => { const json = JSON.parse(data); dlog(json, json['data']); const success = json['result'] == true; if ((success && !isDebug()) || (!success && isDebug())) { setOutput({ fan: { ...output['fan'], value: json['data'][0] == 1, }, pump: { ...output['pump'], value: json['data'][1] == 1, }, }); } } ); }, []);