Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Electron 애플리케이션 만들기

Electron에서

Electron은 Node.js에 기반을 둔 데스크톱 애플리케이션 플랫폼으로(구 atom-shell) GitHub에서 Atom 에디터를 만들면서 오픈 소스로 공개했다. 비슷한 기술로는 NW.js가 있는데 둘 다 비슷하게 HTML, CSS, JavaScript를 이용해서 크로스 플랫폼에서 돌아가는 데스크톱 애플리케이션을 만들 수 있다. 나는 NW.js는 써본 적이 없지만, 초기 Atom 에디터가 나왔을 때 패키지를 만든 게 인연이 되어서 계속 Electron을 사용하고 있다. 초기에는 문서도 잘 안 되어 있어서 힘들었지만, 요즘은 이전보다는 꽤 좋아진 편이다.(상대적 표현이다. 문서화가 잘 되어 있는 편은 아니라고 생각한다.)

Awesome Electron에 가보면 Electron으로 만들어진 데스크톱 애플리케이션을 볼 수 있는데 Atom 에디터 외에도 Slack, Visual Studio Code, Nuclide, pixate등이 Electron으로 만들어졌다.

Electron 애플리케이션 만들기

Electron은 Node 기반으로 만들어져 있다. v0.33.0부터는 Node.js v4에 기반을 두고 있고 이를 이용해서 JavaScript를 실행하고 HTML과 CSS를 이용해서 화면을 그려준다. 그래서 Electron 앱을 만드려면 몇 가지 소스 파일이 기본적으로 필요하다. 나 같은 경우는 나중에 패키징을 하기 위해서 src폴더 안에 모든 소스를 넣는 방식을 사용하고 있고 이 예제의 기본 소스 파일은 Electron 문서(preco21님이 공식 문서를 이미 번역해 주셨다.)를 참고했다.

{
  "name": "hello-electron",
  "version": "0.0.1",
  "main": "main.js"
}

src/package.json'파일이다. npm에서 사용하는package.json과 같은 파일로 의존성 관리나 작성자 정보 등도 동일하게 여기에 넣을 수 있다. 여기서 중요한 부분은main`부분이다. 이 필드값을 보고 Electron이 어떤 JavaScript 파일을 실행할지 결정한다.

// src/main.js
var app = require('app');  // 어플리케이션 기반을 조작 하는 모듈.
var BrowserWindow = require('browser-window');  // 네이티브 브라우저 창을 만드는 모듈.

// Electron 개발자에게 crash-report를 보냄.
require('crash-reporter').start();

// 윈도우 객체를 전역에 유지합니다. 만약 이렇게 하지 않으면
// 자바스크립트 GC가 일어날 때 창이 자동으로 닫혀버립니다.
var mainWindow = null;

// 모든 창이 닫히면 어플리케이션 종료.
app.on('window-all-closed', function() {
  // OS X의 대부분의 어플리케이션은 유저가 Cmd + Q 커맨드로 확실하게 종료하기 전까지
  // 메뉴바에 남아 계속 실행됩니다.
  if (process.platform != 'darwin') {
    app.quit();
  }
});

// 이 메서드는 Electron의 초기화가 모두 끝나고
// 브라우저 창을 열 준비가 되었을 때 호출됩니다.
app.on('ready', function() {
  // 새로운 브라우저 창을 생성합니다.
  mainWindow = new BrowserWindow({width: 800, height: 600});

  // 그리고 현재 디렉터리의 index.html을 로드합니다.
  mainWindow.loadUrl('file://' + __dirname + '/index.html');

  // 개발자 콘솔을 엽니다.
  mainWindow.openDevTools();

  // 창이 닫히면 호출됩니다.
  mainWindow.on('closed', function() {
    // 윈도우 객체의 참조를 삭제합니다 보통 멀티 윈도우 지원을 위해
    // 윈도우 객체를 배열에 저장하는 경우가 있는데 이 경우
    // 해당하는 모든 윈도우 객체의 참조를 삭제해 주어야 합니다.
    mainWindow = null;
  });
});

이 파일이 Electron 애플리케이션의 진입점이 되는 파일로 앱을 어떻게 실행할지 전역적으로 어떤 설정이 필요한지를 모두 여기서 지정한다. 이 파일에서 중간에 보면 mainWindow.loadUrl('file://' + __dirname + '/index.html');부분이 있는데 여기서 index.html파일을 로딩해서 화면에 그려준다.

<!-- src/index.html -->
<!DOCTYPE html>
<html>
<head>
  <title>Hello World</title>
  <meta http-equiv="Content-Security-Policy" content="default-src *; script-src 'self'; style-src 'self' 'unsafe-inline';">
</head>
<body>
  <h1>Hello World</h1>
</body>
</html>

실제 앱에 보여줄 화면은 이 HTML 파일에서 만들어 준다. 이렇게 하면 앱의 진입점을 만드는 데 필요한 파일이 모두 끝나고 여기서 CSS로 화면을 디자인하고 JavaScript로 동작을 부여하면 애플리케이션을 만들 수 있다.

Electron 애플리케이션 실행하기

Electron 애플리케이션을 실행하려면 일단 Electron이 필요하다. 기본적인 방법은 Electron의 새 버전의 바이너리 파일을 다운로드 받아서 다음과 같이 실행하면 된다.

$ ./Electron.app/Contents/MacOS/Electron src/

여기서 보면 다운로드 받은 Electron 바이너리가 ./Electron.app/Contents/MacOS/Electron에 있고 Electron이 사용할 소스파일을 앞에서 src에 넣었으므로 src/폴더를 지정한 것이다. 이렇게 하면 앞에서 만든 소스파일로 Elctron 애플리케이션을 실행할 수 있다.

이 방법도 유효하지만 이렇게 하면 Elctron 애플리케이션을 만들 때마다 바이너리 파일을 다운로드 받아야 하는 귀찮음이 생긴다. 그래서 공식 문서에서는 electron-prebuilt의 사용을 권장하고 있다. npm install -g electron-prebuiltelectron-prebuilt를 전역으로 설치하고 이를 다음과 같이 실행하면 된다.(전역이 아니라 로컬에 설치해도 된다.)

$ electron src/

이 명령어는 사실상 앞에서 사용한 것과 같지만 electron-prebuilt이 미리 바이너리를 다운받아 놓고 이를 사용하도록 하는 것이다.

Hello World Electron 애플리케이션


grunt-download-electron

나는 electron-prebuilt가 있기 전부터 쓰다 보니 grunt-download-electron를 사용하고 있다.(Grunt를 쓰고 있기도 하고...) grunt-download-electron를 설치하고 Gruntfile.js에 다음 설정을 추가하고 원하는 버전을 지정하면 된다.

module.exports = function(grunt) {
  grunt.initConfig({
    'download-electron': {
      version: '0.33.0',
      outputDir: 'build'
    }
  });
};

grunt download-electron를 실행하면 Electron을 다운로드 받아서 outputDir 아래에 설치한다. Grunt를 이용해서 Electron을 다운로드 받았으므로 앞에서 설명한 첫 번째 방식으로 ./build/electron/Electron.app/Contents/MacOS/Electron src/로 실행하면 앱을 띄울 수 있다. 이 명령어가 길어서 좀 귀찮으므로 나는 예전에는 공식 문서에 링크가 걸려있던 hello-atom을 참고해서 초기에 프로젝트를 구성했으므로 다음과 같이 run.sh를 만들어서 사용하고 있다.

#! /usr/bin/env bash
set -e

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

mkdir -p "${DIR}/build"

pushd "${DIR}/build"
  npm install -g grunt-cli
  npm install
  grunt download-electron
popd

"${DIR}/build/Electron.app/Contents/MacOS/Electron" "${DIR}/src"

./run.sh을 실행하면 관련 의존성을 설치하고 Electron까지 받은 다음에 애플리케이션을 실행하게 된다.

2015/09/29 21:02 2015/09/29 21:02