electron 에서 preload.js 를 올바로 사용해야 하는 이유는 보안 때문 입니다.

renderer 에서 require 를 사용해서 시스템에 직접 접근하는 것은 보안상 매우 위험해 질 수 있습니다.

IPC(프로세스간통신) 을 통해 renderer 와 main process 를 분리하고, main 에서는 검증된 요청만 처리해야 더욱 안전한 프로그래밍이 가능 해 집니다.

renderer 에서 main 에 직접 접근하면 보안상 좋지 않다

 

renderer 에서는 preload.js 를 통해 IPC통신을 해야 통제하기 쉽다

 

 

 

main.js

const {app, BrowserWindow, ipcMain } = require("electron");

let win;

async function createWindow() {

  // Create the browser window.
  win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false, // is default value after Electron v5
      contextIsolation: true, // protect against prototype pollution
      enableRemoteModule: false, // turn off remote
      preload: app.getAppPath()+"/preload.js" // use a preload script
    }
  });
  win.webContents.openDevTools()  //랜더러에서 console창 보여주기
  win.loadFile(app.getAppPath()+"/index.html");

}
app.on("ready", createWindow);


ipcMain.on("toMain", (event, data) => {
  console.log(`Received [${data}] from renderer browser`);
  win.webContents.send("fromMain", ' here is main! ');
});

 

preload.js

const { contextBridge, ipcRenderer } = require("electron");

contextBridge.exposeInMainWorld(
  "api", {
      send: (channel, data) => {
          let validChannels = ["toMain"]; // IPC채널들 추가
          if (validChannels.includes(channel)) {
              ipcRenderer.send(channel, data);
          }
      },
      receive: (channel, func) => {
          let validChannels = ["fromMain"]; // IPC채널들 추가
          if (validChannels.includes(channel)) {
              ipcRenderer.on(channel, (event, ...args) => func(...args));
          }
      }
  }
);

 

index.html

<!doctype html>
<html lang="en-US">
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta charset="utf-8"/>
    <title>Title</title>
</head>
  check browser console and terminal console
<body>
    <script>
        window.api.receive("fromMain", (data) => {
            console.log(`Received [${data}] from main process`);
        });
        window.api.send("toMain", "here is renderer");
    </script>
</body>
</html>

 

설명

브라우저에서  window.api.receive() 에서 나중에 받을 준비를 해 놓는다.
브라우저에서 window.api.send() 에서 preload의 contextBridge 속 api.send 함수를 호출한다.
contextBridge.api.send 에서는 IPC 통신을 통해 main 으로 호출을 전달한다.
main 의 ipcMain.on("toMain",..) 에서 값을 받아 처리한 뒤 win.webContents.send() 를 사용해서 브라우저로 결과를 반환한다.
preload의 contextBridge 속 api.receive 함수에서는 main 에서 받은 값을 브라우저로 전달한다.
브라우저의 api.receive 함수가 호출되어 결과값을 console에 출력한다.

 

결과화면

 

 

 

 

출처 : github.com/electron/electron/issues/9920#issuecomment-575839738

출처 : www.javaer101.com/ko/article/2206718.htmlgithub.com/reZach/secure-electron-template/blob/master/docs/secureapps.md

 

 

+ Recent posts