Table of contents

2. Building your First App - Setting up your project

Initializing your npm project

initalizing an npm package

Start by creating a folder and initializing an npm package within it withย npm init.

mkdir my-electron-app
cd my-electron-app
npm init
์‹คํ–‰ํ™”๋ฉด

web_application32.png
This command will prompt you to configure some fields in your package.json.

web_application33.png
package.json์ด ์ƒ์„ฑ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. (โ€mainโ€: index.js โ†’ main.js๋กœ ๋ฐ”๊ฟ”์ค€๋‹ค.)

AS-IS

web_application34.png

TO-BE

web_application35.png

install electron โ€”save-dev

You should also now have aย node_modulesย folder containing the Electron executable, as well as aย package-lock.jsonย lockfile that specifies the exact dependency versions to install.

npm install electron โ€”save-dev
์‹คํ–‰ํ™”๋ฉด

web_application36.png

node_modules, package-lock.json, package.json ์ฝ”๋“œ์— devDependencies๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ๋‹ค!

web_application37.png


Running an Electron app

package.json ํŒŒ์ผ์˜ ๋ฉ”์ธ ์Šคํฌ๋ฆฝํŠธ๋Š” ์•ฑ์ด ์‹œ์ž‘๋  ๋•Œ ์‹คํ–‰๋˜๋Š” ์ค‘์‹ฌ์ ์ธ ์ฝ”๋“œ๋ฅผ ๋‹ด๊ณ  ์žˆ์œผ๋ฉฐ, ์ด ์ฝ”๋“œ๋Š” ์ฃผ๋กœ ๋ฉ”์ธ ํ”„๋กœ์„ธ์Šค์—์„œ ์•ฑ์˜ ํ•ต์‹ฌ์ ์ธ ๊ธฐ๋Šฅ์„ ๋‹ด๋‹นํ•œ๋‹ค. ์ด ํ”„๋กœ์„ธ์Šค๋Š” Node.js๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๋ฉฐ, ์•ฑ์˜ ์ „๋ฐ˜์ ์ธ ๋™์ž‘์„ ์กฐ์ •ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

๋ฉ”์ธ ํ”„๋กœ์„ธ์Šค ์ง„์ž…์ ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌ์„ฑ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ(์ƒ๋žต๊ฐ€๋Šฅ)

Electron์˜ ๋ฉ”์ธ ํ”„๋กœ์„ธ์Šค๋Š” ์ผ๋ฐ˜์ ์ธ Node.js ํ™˜๊ฒฝ๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ๋™์ž‘ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ electron ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์ธ ํ”„๋กœ์„ธ์Šค ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด, Node.js์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋ชจ๋“ˆ์ด๋‚˜ ๊ธฐ๋Šฅ๋“ค์„ Electron ๋ฉ”์ธ ํ”„๋กœ์„ธ์Šค์—์„œ๋„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

//main.js
// Create a main.js file in the root folder of your project
console.log('Hello from Electron')
//package.json
//script ์•ˆ์— start ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€.
"scripts": {
    "start": "electron .",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

๊ฐœ๋ฐœ ๋ชจ๋“œ์—์„œ Electron์„ ์‹คํ–‰ํ•˜๋ ค๋ฉด ํ„ฐ๋ฏธ๋„์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉ

npm run start
์‹คํ–‰ํ™”๋ฉด

web_application38.png web_application39.png web_application40.png


Loading a web page into a BrowserWindow

Electron์—์„œ ๊ฐ ์ฐฝ์€ ๋กœ์ปฌ HTML ํŒŒ์ผ ๋˜๋Š” ์›๊ฒฉ ์›น ์ฃผ์†Œ์—์„œ ๋กœ๋“œ๋  ์ˆ˜ ์žˆ๋Š” ์›น ํŽ˜์ด์ง€๋ฅผ ํ‘œ์‹œํ•œ๋‹ค. ํ”„๋กœ์ ํŠธ์˜ ๋ฃจํŠธ ํด๋”์— index.html ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ๊ธฐ๋ณธ ์›น ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•˜์ž! ๊ทธ๋Ÿผ, Electron BrowserWindow์— ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฝ”๋“œ ๋ณด๊ธฐ
//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'"
    />
    <meta
      http-equiv="X-Content-Security-Policy"
      content="default-src 'self'; script-src 'self'"
    />
    <title>Hello from Electron renderer!</title>
  </head>
  <body>
    <h1>Hello from Electron renderer!</h1>
    <p>๐Ÿ‘‹</p>
  </body>
</html>
์‹คํ–‰ํ™”๋ฉด

web_application41.png

main.js ์ˆ˜์ •ํ•˜๊ธฐ

์ฝ”๋“œ ๋ณด๊ธฐ
//main.js
const { app, BrowserWindow } = require('electron')

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

  win.loadFile('index.html')
}

app.whenReady().then(() => {
  createWindow()
})
์ฝ”๋“œ ์„ค๋ช…

Importing two Electron modules with CommonJS module syntax

  • app: ์ „๋ฐ˜์ ์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ด๋ฒคํŠธ ๋ผ์ดํ”„์‚ฌ์ดํด์„ ์ œ์–ด
  • BrowserWindow: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฐฝ์˜ ์ƒ์„ฑ๊ณผ ๊ด€๋ฆฌ๋ฅผ ๋‹ด๋‹น
const { app, BrowserWindow } = require('electron')

Writing a reusable function to instantiate windows (์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ์ฐฝ์„ ์ƒ์„ฑ)

  • createWindow() ํ•จ์ˆ˜๋Š” ์ƒˆ๋กœ์šด BrowserWindow ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ํ•ด๋‹น ์ฐฝ์˜ ๊ตฌ์„ฑ์„ ์„ค์ •ํ•˜๋ฉฐ(width, height, webPreferences ๋“ฑ), index.html ํŒŒ์ผ์„ ์ฐฝ์— ๋กœ๋“œ
const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600
  })

  win.loadFile('index.html')
}

Calling your function when the app is ready

  • Electron์—์„œ BrowserWindow์€ app ๋ชจ๋“ˆ์˜ ready ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ํ›„์—๋งŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. app.whenReady() API๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ํ•ด๋‹น ํ”„๋กœ๋ฏธ์Šค๊ฐ€ ์ดํ–‰๋˜๋ฉด createWindow()์„ ํ˜ธ์ถœํ•จ์œผ๋กœ์จ ์ด ์ด๋ฒคํŠธ๋ฅผ ๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์žˆ๋‹ค.
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ดˆ๊ธฐํ™”๋˜๊ณ  ํ•„์š”ํ•œ ์„ค์ •์ด ์™„๋ฃŒ๋œ ํ›„์— ์ฐฝ์„ ์ƒ์„ฑํ•˜๋„๋ก ๋ณด์žฅ
app.whenReady().then(() => {
  createWindow()
})

์ด์ œ, Electron ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‹œ์ž‘ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ฉด ์„ฑ๊ณต์ ์œผ๋กœ ์›น ํŽ˜์ด์ง€๊ฐ€ ํ‘œ์‹œ๋˜๋Š” ์ฐฝ์ด ์—ด๋ฆด ๊ฒƒ์ด๋‹ค!

์‹คํ–‰ํ™”๋ฉด

web_application42.png

web_application43.png


Managing your appโ€™s window lifecycle

[Windows ๋ฐ Linux] ์ผ๋ฐ˜์ ์œผ๋กœ ๋ชจ๋“  ์ฐฝ์„ ๋‹ซ์œผ๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์™„์ „ํžˆ ์ข…๋ฃŒ๋œ๋‹ค. Electron ์•ฑ์—์„œ ์ด ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด app ๋ชจ๋“ˆ์˜ window-all-closed ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ macOS์—์„œ ์ž‘์—… ์ค‘์ด ์•„๋‹Œ ๊ฒฝ์šฐ app.quit()์„ ํ˜ธ์ถœํ•˜์—ฌ ์•ฑ์„ ์ข…๋ฃŒํ•˜๋„๋ก ํ•œ๋‹ค.

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

[macOS] macOS์—์„œ๋Š” ์ฐฝ์„ ๋‹ซ์•„๋„ ์•ฑ์ด ์™„์ „ํžˆ ์ข…๋ฃŒ๋˜์ง€ ์•Š๊ณ , macOS ์•ฑ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์ฐฝ์ด ์—ด๋ ค ์žˆ์ง€ ์•Š์•„๋„ ๊ณ„์† ์‹คํ–‰๋œ๋‹ค. ์ฐฝ์ด ์—†์„ ๋•Œ ์•ฑ์„ ํ™œ์„ฑํ™”ํ•˜๋ฉด ์ƒˆ ์ฐฝ์ด ์—ด๋ฆฌ๋„๋ก ํ•ด์•ผํ•œ๋‹ค. ์ฐฝ์ด ์ค€๋น„๋˜๊ธฐ ์ „์—๋Š” ์ฐฝ์„ ๋งŒ๋“ค ์ˆ˜ ์—†์œผ๋ฏ€๋กœ, ์•ฑ์ด ์ดˆ๊ธฐํ™”๋œ ํ›„์—๋งŒ activate ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•˜๋„๋ก ํ•ด์•ผํ•œ๋‹ค. ๊ธฐ์กด์˜ whenReady() ์ฝœ๋ฐฑ ๋‚ด์—์„œ๋งŒ activate ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜๋„๋ก ํ•œ๋‹ค.

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

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