Jaerock
피아노 치는 개발자
Jaerock
전체 방문자
오늘
어제
  • 분류 전체보기
    • Front_End
      • Angular
      • Vue.js
      • React
      • Basic
      • Nuxt.js
      • Electron
    • Main
    • WEB
      • PM2
    • 기술면접
      • OS
      • ComputerNetwork
      • ComputerStructure
      • Programming
      • Database
    • Tensorflow

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • vue
  • 웹
  • Angular
  • 컴퓨터 네트워크
  • cookie
  • 면접 질문
  • Tutorial
  • react.js
  • 웹저장소
  • local storage
  • vue.js
  • pm2
  • JavaScript
  • tensorflow
  • 면접질문
  • REACT
  • IT면접
  • tensorflow install mac
  • session storage
  • 쿠키

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Jaerock

피아노 치는 개발자

Front_End/Electron

0. Electron - 기본

2021. 10. 16. 21:13

Before writing

Electron을 현업에서 사용한지가 2년이 다 되가는 것 같습니다. 처음 사용하였을 때는 크로스플랫폼을 지원해서 아주 강력하고 좋은 프레임워크라고 생각이 들었습니다.

(쓰면 쓸수록 제약도 많고 무거워서 역시 native가 짱이다라는 생각이 들기도 합니다.)

그래도 가벼운 프로그램을 만드는데 사용한다면 오직 js만 다루어서 응용프로그램을 만들 수 있게 해주는 꽤나 쓸만한 프레임워크입니다. 약 2년간 사용+공부를 하면서 뭘 공부하면 좋은지에 대해 써볼까합니다.


What is Electron?

Electron is a framework for building desktop applications using JavaScript, HTML, and CSS. By embedding Chromium and Node.js into its binary, Electron allows you to maintain one JavaScript codebase and create cross-platform apps that work on Windows, macOS, and Linux — no native development experience required.

공식 document에 가면 위와같이 설명되있습니다. 말그대로 Web/Front-End 기술들로 데스크톱 응용프로그램을 만들 수 있게 해주는 프레임워크입니다.(심지어 크로스 플랫폼으로요)

마지막에 native에 대한 개발 경험이 필요 없다고 적혀있는데, 사용하는 내내 정말 필요없다고 생각이 들었습니다. 구현에 사용하려는 OS의 기능들만 대강 알고 있으면,(ex: context_menu, key_shortcut, 등) 구현에는 크게 무리가 없었던 것 같습니다.

개인적인 생각이지만 공식 문서도 제법 정리가 잘 되있고, 은근히 사용하는 사람이 많아서 그런지 stack overflow에도 꽤나 많은 에러 및 오류 해결법들이 잘 정리되어 있어 개발하는데 아주 큰 어려움은 없었습니다.





1. Installation

설치에는 Node.js가 필요로합니다. 만약에 32bit window를 지원해줘야하는 응용 프로그램을 만드셔야한다면, Node.js 32bit를 설치 하셔야합니다. 이 점을 유의해주세요!

간단하게, electron 공식 quick start 부터 해볼까합니다.

거의 그럴일은 없겠지만 Node.js가 설치되어 있지 않다면, Node.js부터 설치를 해주셔야합니다.

npm 만세

  1. npm init위 명령어들까지는 Electron과 무관합니다. quick-start 를 위한 폴더를 만들고, node-package-manager(npm)을 이용해서 init을 해줍니다.package.json이 만들어지게 되는데 프로젝트와, 패키지들의 정보가 기록되어 있는 파일입니다. package.json내의 scripts value를 위와 같이 변경해주세요.
{
    "scripts": {
    "start": "electron ."
    }
}
  1. ++ 혹시 script에 다른 명령어를 집어 넣으셨다면?
  2. 위 명령어를 실행하면 이것저것 입력을 하게하는데 entry point를 입력하실 때에, main.js를 기입해주셔야 합니다. 그리고 author, description에는 반드시 어떤 값이라도 기입해주셔야합니다. 위와 같은 이유는 Electron 공식 문서에서 몇가지 따라야할 룰이 있다고 설명해주기 때문입니다.
  3. mkdir my-electron-app && cd my-electron-app npm init
  4. npm install --save-dev electron //
    • install--save-dev는 개발용으로 설치하고, package.json에 기록해서 저장하겠다는 의미를 가지고, 중요한건 뒤에 있는 electron을 설치하게 됩니다.
  5. make electron app
    • package.json생성 시에 entry point를 main.js로 만들었기 때문에 root폴더(my-electron-app 폴더) 안에 main.js라는 js를 생성하고 아래와 같은 코드를 입력합니다.
    • 코드에 대한 설명은 주석으로 대체하겠습니다.
# require로 설치한 electron을 불러와서 electron 안에 있는 app, BrowserWindow 객체를 정의합니다.
const { app, BrowserWindow } = require('electron') 

# 여기서 path는 현재 app이 사용할 절대 경로 입니다.
const path = require('path')

function createWindow () {
    // 생성자를 통해 window를 생성할 수 있습니다.
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        // 아래 옵션은 preload할 파일을 지정하는 것 입니다. 
        // preload에 대한 자세할 설명은 아래에서
        webPreferences: {
            preload: path.join(__dirname, 'preload.js')
        }
    })

    win.loadFile('index.html')
}

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

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

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

preload한 스크립트에는 웹 콘텐츠(index.html)가 로드되기 전에 렌더러 프로세스에서 실행되는 코드가 포함되어 있습니다. 이러한 스크립트는 렌더러 컨텍스트 내에서 실행되지만 Node.js API에 대한 액세스 권한이 있으면 더 많은 권한이 부여됩니다. 이 말을 이해하기 위해선, Electron의 동작원리를 어느정도 이해해야하는데, 간단히 말하자면 Main process(main.js)위에서 Renderer process가 도는데 이 Renderer process가 Main process에서 load한 index.html을 그려줍니다. preload한 스크립트는 이 index.html이 load되기 이전 시점에 load할 js를 설명합니다. 설명에 두서 없긴하지만 이 구조에 대해서는 다음 장에서 자세히 살펴보도록 하겠습니다.

// DOMContent가 로드가 끝난시점에 process(Node 전역 프로세스 객체)통해 
// `Main process`로 접근하여 version 정보를 가져옴.
window.addEventListener('DOMContentLoaded', () => {
    const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
    }

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

preload를 활용하면, Main process의 Node 전역 객체에 접근과 Dom에 접근이 가능하기 때문에 잘 활용하면 쓸만한 구석이 있어보이나, 초기 페이지 load시에나 활용가능한 여지가 있지, 프로그램이 커진다면, proeload.js만으로 Main process의 접근을 모두 충당할 수는 없기 때문에, 나중에 공부할 Main process - Renderer process간의 통신을 통해 Main process에서만 사용할 수 있는 객체의 property를 가져온다거나 method를 충분히 실행시킬 수 있습니다.

<!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 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 -->
</body>
</html>

main.js에서 load할 index.html 파일입니다.





2. Electron Architecture

아래 구조도는 개인적인 관점으로 바라본 Electron Desktop Application의 대략적인 구조입니다.

Electron을 잘 사용하려면 기본 구조를 이해하는 것이 제법 중요하다고 생각합니다. 전체 프로그램 설계에 아무래도 좀 더 좋은 영향을 주지 않을까 생각합니다.
특히 window간 통신이나 Main process <=> Renderer Process 간의 통신이 많은 프로그램이라면, 통신을 위한 설계에 좋은 영향을 줄것이라고 생각합니다.

Electron Desktop Application을 크게 나눠본다면

  • 1개의 Application
    • 1개의 Main process
    • n개의 Renderer process
    • n개의 Preload Script
      위와 같이 구성된다고 할 수 있습니다.

Main process는 Node JS기반으로 만들어지며, Native UI와 NodeJS내의 Node API를 이용해 OS와 통신을 하여 특정 기능을 수행합니다. 그리고 ipcMain 객체를 이용하여 Renderer process와의 통신도 가능합니다.

Renderer process는 html, css, js를 이용하여 렌더링을 해줍니다. 또한 ipcRenderer객체를 이용하여 Main process와 통신을 수행합니다. Renderer process는 Chromium을 기반으로 합니다.


물론.. 개발상의 이유로 WINDOW2처럼 Node.js환경에서 생성하여 Node API에 직접 접근하는 것도 가능합니다. 다만 이전에는 BroswerWindow를 통해 Renderer process 생성 시에 default로 Node.js환경에서 생성하였으나, 이제 보안상의 이유로 default는 WINDOW1처럼 생성이 됩니다.


Preload Script는 Main Process에서 window를 생성하고, Renderer Process가 생성되기 전에, Main Process에서 실행하게 되는 script를 의미합니다. 그래서 Preload Script에서는 Node js API객체에 접근이 가능합니다.


위에서 설명했듯이 Node js API 객체에 접근하기 위해서는, window 생성시 webPreferences내 nodeIntegration를 true로 변경하던가,
Main Process와의 통신을 통해 Main Process에서 접근하는게 좀 더 바람직하다고 생각합니다. 왜냐하면 많은 통신이 이루어질 경우 preload.js 로는 유지보수에 용이한 코드를 작성하기 어렵기 때문입니다.




    Jaerock
    Jaerock

    티스토리툴바