TIL/Electron

[Electron] Electron 시작하기

oraange 2023. 5. 24. 17:11

Electron이란


Electron은 JavaScript, HTML, CSS를 사용하여 데스크톱 앱을 구현하기 위한 프레임워크이다. Electron은 Chromium과 Node.js를 사용하여 하나의 JavaScript 코드베이스를 유지하고 Windows, macOS 및 Linux에서 작동하는 크로스 플랫폼 앱을 만들 수 있다.

Electron 시작하기


Electron을 시작하기 전에, nodenpm이 깔려있는지 확인해야 한다.

$ node -v
$ npm -v

위 명령어로 버전 정보를 확인해 보고 버전 정보가 잘 출력되면 깔려있는 것이다. node가 설치되지 않았다면, macOS를 기준으로, homebrew를 설치하고 homebrew를 이용하여 nvm을 설치, 그리고 nvm을 이용하여 node를 설치하면 된다.

자세한 설치 방법은 https://memostack.tistory.com/274 여기 블로그에 설명이 잘 되어있으니 참고 바란다. npmnode를 설치하면 설치가 될 것이다.

Application 생성하기

$ mkdir my-electron-app && cd my-electron-app
$ npm init

electron을 시작할 디렉토리를 생성하고 해당 디렉토리에 들어가서 npm init 명령어를 쳐보자. 그러면 명령어 프롬프트에 설정을 작성하는 부분이 뜰텐데, 꼭 작성해야 하는 파트가 있다.

  • entry pointmain.js 라고 작성한다.

나머지는 기본값으로 설정해도 무방하다.

그 다음, Electron 패키지를 의존성 추가를 위해 다음과 같이 명령어를 입력한다.

$ npm install --save-dev electron

그 다음 package.json 설정 파일의 scripts 필드에 다음과 같이 추가해 준다.

{
  "scripts": {
    "start": "electron ."
  }
}

start 커맨드는 Electron app의 개발 모드를 여는데 사용된다.

$ npm start

web page 생성하기

어플리케이션 창을 열기 전에, 그 창 안에 들어갈 내용을 만들어야 한다. Electron에서 각 창은 local HTML 파일이나 원격 URL로 로드할 수 있는 웹 콘텐츠를 표시한다.

현재 폴더(my-electron-app)에서 index.html 파일을 만들고 다음과 같이 작성하자.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    We are using Node.js <span id="node-version"></span>,
    Chromium <span id="chrome-version"></span>,
    and Electron <span id="electron-version"></span>.
  </body>
</html>

위의 코드를 보면 text가 조금 어색한 것을 볼 수 있다. 각 Node.js, Chromium, Electron text 뒤에 버전 정보를 넣어줄건데, 추후에 javascript를 통해 넣어줄 것이다.

browswer window를 이용해서 web page 열기

이제 위에 만든 페이지를 창에 로드하기 위해서 두개의 Electron 모듈이 필요하다.

  • 어플리케이션 이벤트 lifecycle을 관리하기 위한 app 모듈
  • 어플리케이션 윈도우를 생성하고 관리하기 위한 BrowserWindow 모듈

메인 프로세스가 Node.js를 실행하기 때문에, 가장 윗 줄에 CommonJS 모듈로 가져올 수 있다.

const { app, BrowserWindow } = require('electron')

그 다음, index.html파일을 BrowserWindow 인스턴스에서 로드하기 위해 createWindow() 함수를 추가한다.

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600
  })

  win.loadFile('index.html')
}

그 다음, 창을 열기 위해 createWindow() 함수를 호출한다.
Electron에서 브라우저 창은 앱 모듈의 준비 이벤트가 발생한 후에만 생성될 수 있다. app.whenReady() API를 사용하여 이 이벤트를 기다릴 수 있다. whenReady()가 Promise를 resolve한 후 createWindow() 함수를 호출한다.

app.whenReady().then() => {
  createWindow()
})

브라우저 창 lifecycle 관리

애플리케이션 창은 각 OS별로 다르게 작동한다.

모든 창이 닫혀있을 때 앱 종료(windows & linux)

윈도우와 리눅스 운영체제에서는 모든 창이 닫히면 일반적으로 응용 프로그램도 완전히 종료된다.

이것을 구현하기 위해서 app에서 window-all-closed 이벤트를 수신하고 macOS(darwin)이 아닌 경우 app.quit() 함수를 호출한다.

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})

열려있는 창이 없으면 창을 열기

열려있는 창이 없을 때 앱을 종료하는 windows와 linux와는 다르게, macOS의 앱은 일반적으로 창이 열려있지 않아도 계속 실행되며 사용 가능한 창이 없을 때 앱을 활성화하면 새 창이 열린다.

ready 이벤트 전에 창을 만들 수 없기 때문에 앱이 초기화된 이후에만 active 이벤트를 수신해야 한다. 기존 whenReady() 콜백 내에서 이벤트 리스너를 추가하면 된다.

app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

preload 스크립트를 사용하여 렌더러에서 Node.js에 접근하는 방법

이제 위에서 언급한 버전 정보를 렌더링하기 위해 preload.js 파일을 생성하여 다음과 같이 작성해 보자.

window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
  }

  for (const dependency of ['chrome', 'node', 'electron']) {
    replaceText(`${dependency}-version`, process.versions[dependency])
  }
})

해당 파일을 preload하기 위해서 BrowserWindow 구조체에 preload path를 명시해 줘야 한다.

// include the Node.js 'path' module at the top of your file
const path = require('path')

// modify your existing createWindow() function
const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  win.loadFile('index.html')
}
// ...

전체 코드

전체적인 코드는 다음과 같다.

// main.js

// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
const path = require('path')

const createWindow = () => {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  // and load the index.html of the app.
  mainWindow.loadFile('index.html')

  // Open the DevTools.
  // mainWindow.webContents.openDevTools()
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
// preload.js

// All the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
  }

  for (const dependency of ['chrome', 'node', 'electron']) {
    replaceText(`${dependency}-version`, process.versions[dependency])
  }
})
<!--index.html-->

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    We are using Node.js <span id="node-version"></span>,
    Chromium <span id="chrome-version"></span>,
    and Electron <span id="electron-version"></span>.

    <!-- You can also require other files to run in this process -->
    <script src="./renderer.js"></script>
  </body>
</html>

 

출처
https://www.electronjs.org/docs/latest/
 

Introduction | Electron

Welcome to the Electron documentation! If this is your first time developing an Electron app, read through this Getting Started section to get familiar with the basics. Otherwise, feel free to explore our guides and API documentation!

www.electronjs.org

 

반응형