프리로드 스크립트
Electron.js의 프리로드 스크립트는 메인 프로세스와 렌더러 프로세스 간의 통신을 위해 설계된 보안 영역입니다. 일반적으로 **IPC 통신**에 사용됩니다.
자세한 내용은 다음 문서를 참고하세요: https://www.electronjs.org/docs/latest/tutorial/tutorial-preload
최신 버전의 Electron과의 호환성 및 보안을 위해 이전 버전의 electron/remote 모듈은 사용하지 않는 것이 좋습니다. 시스템 이벤트나 노드 스크립트를 활용하려면 렌더러가 아닌 메인 프로세스에서 사용하는 것이 좋습니다.
Vutron의 프리로드 스크립트는 src/preload 폴더에 있습니다. 새 IPC 통신 채널을 생성하려면 다음 변수에 채널 이름을 추가하여 통신을 허용하도록 화이트리스트에 추가합니다.
mainSendChannels: 렌더러에서 메인으로 응답을 기다리지 않고 이벤트를 전송합니다. 메인 프로세스에서는ipcMain.on으로 처리합니다. (window.mainApi.send('channelName'))mainInvokeChannels: 렌더러에서 메인으로 이벤트를 전송하고 결과를 기다립니다. 메인 프로세스에서는ipcMain.handle로 처리합니다. (window.mainApi.invoke('channelName'))rendererAvailChannels: 메인에서 렌더러로 이벤트를 전송합니다. (mainWindow.webContents.send('channelName'))
send와 invoke의 화이트리스트를 분리해 두었기 때문에, 각 채널은 핸들러가 작성된 방식으로만 사용할 수 있습니다.
채널을 추가할 때는 src/common/ipc.ts의 MainSendPayloads, MainInvokeContracts, RendererEventPayloads에도 그 채널이 무엇을 주고받는지 적습니다. 이름만 추가하면 빌드가 실패합니다. 메인 프로세스에서는 ipcMain을 직접 부르는 대신 src/main/utils/ipc.ts의 handleInvoke, handleSend, sendToWindow를 사용하세요. 이 계약이 렌더러의 호출부와 메인 프로세스의 핸들러 양쪽에 적용됩니다.
// src/common/ipc.ts
export interface MainInvokeContracts {
[MAIN_INVOKE_CHANNELS.openFile]: {
args: [filter: string]
result: OpenFileResult
}
}렌더러에서 메인으로 이벤트를 전송할 때는 ipcRenderer.send 대신 window.mainApi 객체에 액세스합니다. mainApi는 Vutron 템플릿에서 설정한 이름이며 변경할 수 있습니다.
다음은 mainApi에서 지원되는 함수입니다:
send: 메인으로 이벤트를 보냅니다.on: 메인에서 보낸 이벤트를 수신할 리스너입니다.once: 메인에서 보낸 이벤트를 수신할 리스너입니다. (하나의 호출만 처리)off: 이벤트 리스너를 제거합니다.invoke: 메인에 이벤트를 보내고 비동기적으로 데이터를 수신할 수 있는 함수입니다.
on과 once의 리스너는 webContents.send로 넘긴 값만 받습니다. Electron의 IpcRendererEvent는 프리로드 스크립트에 남습니다. 이 객체의 sender가 ipcRenderer 전체라서, 렌더러에 그대로 넘기면 위의 화이트리스트를 지나쳐 아무 채널이나 사용할 수 있게 되기 때문입니다.
const unsubscribe = window.mainApi.on('msgWindowsUpdated', (windowIds) => {
console.log(windowIds)
})
// 리스너가 더 필요 없어지면 호출합니다
unsubscribe()on과 once는 리스너를 해제하는 함수를 돌려줍니다. 컴포넌트에서 등록했다면 onUnmounted에서 이 함수를 호출하세요. 리스너는 메인 프로세스에 남아 있어서, 화면이 사라져도 저절로 정리되지 않습니다. 같은 리스너를 off에 넘겨도 됩니다.
이를 변경하고 수정하려면 src/preload/index.ts에서 exposeInMainWorld를 수정해야 합니다.