[Electron] Preload 스크립트 사용하기

abi hong·2023년 12월 26일

Electron

목록 보기
2/5

Electron 공식문서를 정리한 글입니다.

Preload 스크립트

  • Main process
    Electron의 main 프로세스는 전체 운영체제 접근 권한을 가진 Node.js 환경이다. Electron 모듈 뿐만 아니라 Node.js 내장 모듈과 npm을 통한 설치된 패키지에도 접근할 수 있다. 반면, 보안상의 이유로 renderer 프로세스는 기본적으로 Node.js를 실행하지 않고 웹 페이지를 실행한다.

Electron의 서로 다른 프로세스 유형을 연결하기 위해서, preload 스크립트를 사용해야 한다.

  • preload 스크립트는 HTML DOM 및 제한된 Node.js 및 Electron API에 접근할 수 있는 컨텍스트에서 실행된다.
    preload 스크립트는 renderer에서 웹 페이지가 로드되기 전에 주입되며, 크롬 확장 프로그램의 content 스크립트와 유사하다. 접근이 필요한 renderer에 기능을 추가하기 위해, contextBridge API를 통해 전역 객체를 정의할 수 있다.
const { contextBridge } = require('electron')
    
contextBridge.exposeInMainWorld('versions', {
  node: () => process.versions.node,
  chrome: () => process.versions.chrome,
  electron: () => process.versions.electron
      // we can also expose variables, not just functions
})
const path = require('node:path')

const createWindow = () => {
  const win = new BrowserWindow({
	...
	webPreferences: {
	  preload: path.join(__dirname, 'preload.js')
	}
  })
}

renderer 프로세스에서 versions 전역변수에 접근할 수 있다.

const information = document.getElementById('info')
information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})`

info라는 id 속성을 가진 새 요소를 추가하고 renderer.js 스크립트를 첨부한 index.html

<!DOCTYPE html>
<html>
  <head>
    ...
  </head>
  <body>
    ...
    <p id="info"></p>
  </body>
  <script src="./renderer.js"></script>
</html>

프로세스 사이의 communication

  • Electron의 main 프로세스와 renderer 프로세스는 구별된 책임을 가지고 있고 서로 교환할 수 없다. 이는 renderer 프로세스에서 직접적으로 Node.js API에 접근하거나, main 프로세스에서 HTML DOM에 직접적으로 접근하는 것이 불가능하다.
    이 문제를 해결하기 위해서는 Electron의 ipcMainipcRenderer 모듈을 사용해 IPC(Inter-Process Communication)를 하면된다. 웹 페이지에서 main 프로세스로 메세지를 보내려면, ipcMain.handlemain 프로세스 핸들러를 설정하고 preload 스크립트에서 이 핸들러를 트리거하는 ipcRenderer.invoke를 호출하는 함수를 노출하면 된다.
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('versions', {
  ...
  ping: () => ipcRenderer.invoke('ping')
})
const { app, BrowserWindow, ipcMain } = require('electron')

const createWindow = () => {
  ...
}

app.whenReady().then(() => {
  ipcMain.handle('ping', () => 'pong')
  createWindow()
})

한 번 senderreceiver를 설정하면, 아까 정의한 ‘ping’ 채널을 통해 renderer에서 main 프로세스로 메세지를 보낼 수 있다.

const func = async () => {
  const response = await window.versions.ping()
  console.log(response) // prints out 'pong'
}
    
func()

0개의 댓글