본문 바로가기

JavaScript/Electron

[Electron] 간단한 Electron 프로젝트 띄워보기

반응형

최근에 개인적으로 데스크톱 앱을 만들어보고 싶어서 사전 조사를 시작했습니다.

제가 생각하고 있는 구조는 Electron + Vue.js를 함께 사용하는 방식인데, 본 프로젝트 시작 전 Electron의 구조를 어느 정도 알고 시작하는 게 좋겠다는 생각이 들었어서 먼저 Electron 공식 가이드의 Quick Start 문서를 따라 간단한 프로젝트를 생성하고 실행해보는 과정까지만 진행해보려고 합니다.

 

Electron 앱은 다른 Node.js 프로젝트와 동일한 일반적인 구조를 가집니다. 그래서 일반적인 Node 프로젝트를 생성하는 방식과 유사하여 기존에 Node.js를 이용한 프로젝트를 진행한 경험이 있으시다면 쉽게 따라 하실 수 있을 것 같습니다😊

 

사전 준비

Electron을 이용하기 위해서는 Node.js가 설치되어 있어야 합니다.

Node.js가 설치되어있는지 확인해보고 싶으신 분들은 아래 명령어로 확인이 가능합니다.

node -v
npm -v

설치가 되어있지 않으신 분들은 아래 링크에서 LTS 버전을 다운로드해주세요.

 

애플리케이션 생성하기

프로젝트 스케폴딩

1. 폴더를 만들고 npm 패키지를 초기화해줍니다.

Electron 앱은 다른 Node.js 프로젝트와 동일한 일반 구조를 따릅니다. 먼저 폴더를 만들고 npm 패키지를 초기화합니다.

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

❗️이때 주의할 점은, 기존에 node.js 프로젝트를 만들 때는 다 기본 값을 사용했는데 electron은 몇 가지 필수 입력 값이 있습니다.

  1. entry point명은 main.js로 설정합니다.
  2. author와 description은 어떤 값으로 입력되어도 상관없지만, 앱 패키징을 위해서는 필수로 입력되어야 합니다.

 

마지막으로 Electron을 실행할 수 있기를 원합니다. package.json 구성의 script 필드에 다음과 같이 시작 커맨드를 추가합니다.

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

아래 start 커맨드를 사용하면 개발 모드에서 앱을 열 수 있습니다.

npm start

2. Electron 설치

그런 다음 앱의 devDependencies에 electron 패키지를 설치합니다.

npm install --save-dev electron
#npm install --save-dev electron --registry https://registry.npmjs.org/

3. 메인 프로세스 실행

모든 Electron 애플리케이션의 진입점은 main 스크립트입니다. 이 스크립트는 전체 Node.js 환경에서 실행되고 앱의 수명 주기 제어, 기본 인터페이스 표시, 권한 있는 작업 수행, 렌더러 프로세스 관리를 담당하는 기본 프로세스를 제어합니다.

 

실행하는 동안 Electron은 앱 스캐폴딩 단계에서 구성해야 하는 앱의 package.json 구성의 main 필드에서 이 스크립트를 찾습니다.

main 스크립트를 초기화하려면 프로젝트의 루트 폴더에 main.js라는 빈 파일을 만듭니다.

참고: 이 시점에서 시작 스크립트를 다시 실행하면 앱에서 더 이상 오류가 발생하지 않습니다! 그러나 main.js에 코드를 추가하지 않았기 때문에 아직 아무 작업도 수행하지 않습니다.

4. 웹 페이지 만들기

애플리케이션에 대한 window를 만들기 전에 window에 로드할 콘텐츠를 만들어야 합니다. Electron에서 각 window는 로컬 HTML 파일이나 원격 URL에서 로드할 수 있는 웹 콘텐츠를 표시합니다. 이 튜토리얼에서는 전자를 수행합니다.

 

루트 폴더에 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>
참고: 이 HTML 문서를 보면 본문에서 버전 번호가 누락된 것을 볼 수 있습니다. 나중에 JavaScript를 사용하여 수동으로 삽입합니다.

5. 브라우저 창에서 웹 페이지 열기

이제 웹 페이지가 있으므로 애플리케이션 window에 로드합니다. 그렇게 하려면 두 개의 Electron 모듈이 필요합니다.

  • 애플리케이션의 이벤트 수명 주기를 제어하는 ​​app 모듈.
  • 애플리케이션 window를 만들고 관리하는 BrowserWindow 모듈.

 

메인 프로세스가 Node.js를 실행하기 때문에 main.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 모듈의 ready 이벤트가 발생한 후에만 생성할 수 있습니다. app.whenReady() API를 사용하여 이 이벤트를 기다릴 수 있습니다. whenReady()가 Promise를 해결한 후 createWindow()를 호출합니다.

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

 

완성된 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()
})
참고: 이 시점에서 Electron 애플리케이션은 웹 페이지를 표시하는 window가 성공적으로 열려야합니다.

실행 결과 화면

 

정상적으로 Electron 앱이 실행된 것을 확인하였습니다.

 


6. window의 수명 주기 관리

 

이제 브라우저 window를 열 수 있지만 각 플랫폼에 더 기본적으로 느껴지도록 하려면 몇 가지 추가 상용구 코드가 필요합니다. 애플리케이션 window는 OS마다 다르게 작동하며 Electron은 개발자에게 앱에서 이러한 규칙을 구현하는 책임을 둡니다.

 

일반적으로 process의 전역 platform 속성을 사용하여 특정 운영 체제용 코드를 실행할 수 있습니다.

 

모든 창이 닫히면 앱 종료(Windows 및 Linux)

Windows 및 Linux에서 모든 창을 종료하면 일반적으로 애플리케이션이 완전히 종료됩니다.

 

이를 구현하려면 앱 모듈의 'window-all-closed' 이벤트를 수신하고 사용자가 macOS(darwin)를 사용하지 않는 경우 app.quit()를 호출합니다.

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

아무 것도 열려 있지 않으면 창 열기(macOS)

Linux 및 Windows 앱은 창이 열리지 않으면 종료되지만 macOS 앱은 일반적으로 창이 열리지 않아도 계속 실행되며 사용 가능한 창이 없을 때 앱을 활성화하면 새 창이 열립니다.

 

이 기능을 구현하려면 앱 모듈의 activate 이벤트를 수신하고 브라우저 창이 열려 있지 않으면 기존 createWindow() 메서드를 호출하세요.

 

준비 이벤트 전에 창을 만들 수 없으므로 앱이 초기화된 후에만 활성화 이벤트를 수신 대기해야 합니다. 기존 whenReady() 콜백 내에서 이벤트 리스너를 연결하여 이를 수행합니다.

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

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

7. preload 스크립트를 사용하여 렌더러에서 Node.js에 액세스​

이제 마지막으로 해야 할 일은 Electron의 버전 번호와 웹 페이지에 대한 종속성을 인쇄하는 것입니다.

 

이 정보에 액세스하는 것은 Node의 전역 process 개체를 통해 메인 프로세스에서 수행하는 것이 간단합니다. 그러나 렌더러의 document 컨텍스트에 액세스할 수 없기 때문에 메인 프로세스에서 DOM을 편집할 수 없습니다. 그들은 완전히 다른 프로세스에 있습니다!

 

여기서 렌더러에 preload 스크립트를 첨부하면 편리합니다. preload 스크립트는 렌더러 프로세스가 로드되기 전에 실행되며 렌더러 전역(예: window 및 document)과 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])
  }
})

위의 코드는 Node.js process.versions 객체에 접근하고 기본 replaceText 헬퍼 함수를 실행하여 HTML 문서에 버전 번호를 삽입합니다.

 

이 스크립트를 렌더러 프로세스에 연결하려면 preload 스크립트의 경로를 기존 BrowserWindow 생성자의 webPreferences.preload 옵션에 전달하십시오.

// 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')
}
// ...

여기에 사용되는 두 가지 Node.js 개념이 있습니다.

  • __dirname 문자열은 현재 실행 중인 스크립트의 경로(이 경우 프로젝트의 루트 폴더)를 가리킵니다.
  • path.join API는 여러 경로 세그먼트를 함께 결합하여 모든 플랫폼에서 작동하는 결합된 경로 문자열을 만듭니다.

 

위의 단계를 수행한 후에는 다음과 같이 완전히 작동하는 Electron 애플리케이션을 확인 할 수 있습니다.

우리가 수행한 모든 단계를 요약하자면: 

  • Node.js 애플리케이션을 스캐폴딩하고 Electron을 종속성으로 추가했습니다.
  • 앱을 제어하고 Node.js 환경에서 실행되는 메인 프로세스를 실행하는 main.js 스크립트를 만들었습니다. 이 스크립트에서는 Electron의 앱과 BrowserWindow 모듈을 사용하여 별도의 프로세스(렌더러)에서 웹 콘텐츠를 표시하는 브라우저 창을 만들었습니다.
  • 렌더러에서 특정 Node.js 기능에 액세스하기 위해 preload 스크립트를 BrowserWindow 생성자에 연결했습니다.

 

 

다음 포스팅에서는 OS별 패키징하여 배포하는 과정을 작성해보겠습니다.

 

Reference

 

반응형