[Electron] Electron 시작하기
Electron이란
Electron은 JavaScript, HTML, CSS를 사용하여 데스크톱 앱을 구현하기 위한 프레임워크이다. Electron은 Chromium과 Node.js를 사용하여 하나의 JavaScript 코드베이스를 유지하고 Windows, macOS 및 Linux에서 작동하는 크로스 플랫폼 앱을 만들 수 있다.
Electron 시작하기
Electron을 시작하기 전에, node
와 npm
이 깔려있는지 확인해야 한다.
$ node -v
$ npm -v
위 명령어로 버전 정보를 확인해 보고 버전 정보가 잘 출력되면 깔려있는 것이다. node
가 설치되지 않았다면, macOS를 기준으로, homebrew
를 설치하고 homebrew
를 이용하여 nvm
을 설치, 그리고 nvm
을 이용하여 node
를 설치하면 된다.
자세한 설치 방법은 https://memostack.tistory.com/274 여기 블로그에 설명이 잘 되어있으니 참고 바란다. npm
은 node
를 설치하면 설치가 될 것이다.
Application 생성하기
$ mkdir my-electron-app && cd my-electron-app
$ npm init
electron을 시작할 디렉토리를 생성하고 해당 디렉토리에 들어가서 npm init
명령어를 쳐보자. 그러면 명령어 프롬프트에 설정을 작성하는 부분이 뜰텐데, 꼭 작성해야 하는 파트가 있다.
entry point
는main.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/