일렉트론에서 메인 프로세스와 렌더러 프로세스가 ipc 통신을 preload에서 contextBridge를 이용하는 방법을 권장하고 있습니다.
preload는 웹 콘텐츠가 로드되기 전 렌더러 프로세스에서 실행됩니다. 이 스크립트는 node.js api에 접근이 가능합니다.
preload script와 renderer process는 같은 window 전역 객체를 공유하지만 기본적으로 contextIsolation이 활성화 되어 있기에 preload script에서 window 객체에 변수가 api를 추가 할 수 없습니다.
contextIsolation은 preload script와 renderer를 분리해 안전하게 통신 할 수 있습니다.
(참고 링크) => https://www.electronjs.org/docs/latest/tutorial/context-isolation
preload에서 contextBridge를 통해 이를 안전하게 수행이 가능합니다.
그렇다면 메인 프로세스에서 렌더러 프로세스로 메시지를 보내고 렌더러 프로세스에서 이를 받는 테스트 코드를 먼저 살펴보겠습니다.
저는 이벤트 발생 시점을 기존 메인 window (메인 프로세스) 에서 만일 새로운 창이 열렸다면 그 때 메시지를 보내도록 하는 상황으로 가정하겠습니다.
win = new BrowserWindow({
width: 1000,
height: 800,
webPreferences: {
preload: path.join(__dirname, "preload.js"),
nodeIntegration: true
}
})
win.webContents.on('did-create-window', (window: BrowserWindow, details: DidCreateWindowDetails) => {
win.webContents.send('ping', 'main에서 renderer로 ping 보낸다')
})
// preload
import { contextBridge, ipcRenderer } from "electron"
contextBridge.exposeInMainWorld('electron', {
ping: (callback) => ipcRenderer.on('ping', (event, value) => callback(value))
})
// react
useEffect(() => {
window.electron.ping((value) => {
console.log('Received : ', value)
})
})
결과

코드는 매우 간단합니다.
만일 기존 win 창에서 'did-create-window' 이벤트가 발생했다면 win 메인 프로세스에서 메시지를 보내도록 합니다. (만약 새로운 창 window에서 보내고 싶다면 window.webContents...)
preload 스크립트에서 ipcRenderer.on 을 이용해 메시지를 받습니다.
React에서 window.electron.ping 을 이용해 접근하여 함수를 수행합니다.
다만, 저희는 타입스크립트로 구성하였기 때문에 React에서 window.electron을 하려면 에러가 발생합니다.
그렇다면 React 프로젝트에서 기본으로 생성된 react-app-env.d.ts에서 interface만 정의하면 쉽게 접근이 가능합니다.
interface Window {
electron: {
ping: (callback:(...arg) => void) => void; // 타입은 알아서 정의하시면 됩니다.
}
}
이것 말고도 렌더러에서 메인으로, 렌더러 -> 메인 -> 렌더러 와 같이 다양한 방식으로 통신이 가능하므로 이 부분은 공식문서에 자세하게 잘 나와 있습니다.
https://www.electronjs.org/docs/latest/tutorial/ipc#ipc-channels