본문 바로가기

Javascript/Electron

Electron + React 데스크탑 앱 개발 (2)

앞의 포스팅에서 언급되었듯이 Electron은 내장된 Chromium에 html, javascript, css로 구성된 화면을 렌더링 하는 방식으로  작동하기 때문에 일반적인 React.js 프로젝트를 생성하는 것과 크게 다르지 않습니다.

 

프로젝트에 React를 적용하는 방법은 크게 두 가지가 있습니다. 첫번째는 React boilerplate인 create-react-app을 이용하여 프로젝트를 생성한 뒤 이를 Electron에 올리는 방식입니다. 두번째로는 React, Babel, Webpack을 설치한 후, 작성된 React 프로그램을 Electron에 올리는 방식입니다. create-react-app을 이용하는 방식은 React를 비롯하여 필요한 라이브러리가 자동으로 설치되고, 설정파일도 사용자가 따로 작성하지 않아도 된다는 측면에서 편리합니다. 하지만 개발하는데 꼭 필요한 라이브러리만 설치되는 것이 아니라 선제적으로 여러 라이브러리를 설치하기 때문에 프로그램이 무거워진다는 단점이 있습니다. 또한 자동으로 설치된 라이브러리의 버전을 바꿔야하거나 설정을 바꿔야하는 경우, 프로젝트 내 라이브러리간 충돌이 발생하는 등 문제가 발생하기 쉽다는 단점이 있어 확장성 측면에서 좋은 선택이라고 할 수 없습니다. 반면 두번째 방식은 필요한 라이브러리를 직접 설치해야하고, 필요한 설정을 해야한다는 측면에서 불편하다는 단점이 있지만, 백지에서부터 스스로 프로젝트를 써나갈 수 있기 때문에 위에서 말한 제약에서 자유로운 편입니다. 무엇이 더 좋다고 단언할 수는 없지만, 프로젝트에 드는 비용과 시간을 줄이고 싶으시다면 전자를, 프로젝트 생성 및 설정에 익숙하시다면 프로그램이 가벼운 후자의 방법을 추천드립니다.

 

이 글에서는 필요한 라이브러리를 설치하고, 설정파일을 작성하는 방식으로 프로젝트를 작성해보도록 하겠습니다. 앞의 글에서 우리는 Electron을 이용하여 index.html을 화면에 출력하는 부분까지 완성하였습니다. React를 적용하는 것은 단순하게 생각해봤을 때, 이 화면에 javascript를 이용하여 동적으로 화면을 변경해준다는 것이라고 할 수 있습니다.

 

그렇기 때문에 처음 electron 프로젝트를 생성해주는 것은 앞서 설명한 내용과 크게 다르지 않습니다.

mkdir electron-react-app
cd electron-react-app
npm init
npm install electron --save-dev

 

그리고 생성된 package.json의 main을 index.js 에서 main.js로 변경해줍니다.

 

electron-react-app/package.json

{
  "name": "electron-react-app",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  ...
}

 

React를 이용한 javascript 코드를 작성하기 위해서는 기본적으로 react와 react-dom 라이브러리가 필요하기 때문에 앞에서 작성한 프로젝트로 이동하여 아래의 명령어를 입력하여 라이브러리를 설치해줍니다.

npm install react react-dom --save-dev

 

설치완료 후에는 Babel과 Webpack을 설치해줍니다. Babel은 es6 및 React에서 사용하는 문법을 es6 이전 javascript 코드로 전환해주며 이는 es6 문법을 처리할 수 없는 구버전의 브라우저에서도 작동할 수 있도록 합니다. Webpack은 프로젝트의 파일을 번들링해주는 역할을 합니다.

 

먼저 Webpack은 다음과 같은 명령어를 실행하여 설치해줍니다. 이때 html과 css도 함께 번들링할 수 있도록 loader를 설치해줘야하는데 이는 html-webpack-plugin, html-loader, css-loader, style-loader 등이 이에 해당합니다. 또한 babel을 사용하여 js를 번들링하도록 babel-loader도 설치합니다. 

npm install webpack webpack-cli html-webpack-plugin html-loader css-loader style-loader babel-loader --save-dev

 

Webpack을 설치하고 난 후에는 Babel도 다음과 같은 명령어를 이용하여 설치합니다. 이때 Babel에서 class 문법을 이해하여 변환할 수 있도록 plugin-proposal-class-properties를 함께 설치하며, 추가로 React.js 문법을 전환할 수 있도록 preset-react 도 함께 설치합니다.

npm install @babel/core @babel/preset-env @babel/plugin-proposal-class-properties @babel/preset-react --save-dev

 

설치를 모두 마친 후에는 Webpack과 Babel 설정파일을 생성해줍니다. 모두 프로젝트 root 경로에 생성하면 되며, Webpack은 webpack.config.js라는 이름으로 Babel은 .babelrc라는 이름으로 생성합니다.

 

electron-react-app/webpack.config.js

const HtmlWebPackPlugin = require("html-webpack-plugin")

module.exports = {
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        test: /\.html$/,
        use: {
          loader: "html-loader",
          options: { minimize: true }
        }
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: "./public/index.html",
      filename: "./index.html"
    })
  ],
  output: {
    path: __dirname + "/build"
  }
}

 

코드의 내용은 우리가 앞서 설치한 라이브러리들을 사용하여 번들링이 가능하도록 설정하는 것입니다. js, jsx 파일은 babel-loader를 사용하도록 loader를 설정하거나, html 파일에 대한 loader설정, css 파일 등에 대한 설정이며 번들링한 결과 파일에 대한 위치 등을 설정한 것입니다.

 

electron-react-app/.babelrc

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ],
  "plugins": ["@babel/plugin-proposal-class-properties"]
}

 

.babelrc 파일의 내용은 Babel에서 사용하는 preset 정보와 plugin 정보에 대한 설정입니다.

 

그다음 index.html 파일을 생성해주는데 파일은 프로젝트 root 디렉토리 아래 public이라는 경로에 생성해주도록 하겠습니다. 그리고 public과 마찬가지로 root 아래에 src라는 디렉토리 아래 각각 App.js, App.css, index.js를 아래와 같이 생성해줍니다.

 

electron-react-app/public/index.html

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>Electron React App</title>
</head>

<body>
  <div id="root"></div>
</body>

</html>

 

electron-react-app/src/App.js

import React, {Component} from 'react'
import './App.css'

export default class App extends Component {
  render () {
    return (
      <div className='app'>
        <h1>Electron React App</h1>
        <p>
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    )
  }
}

 

electron-react-app/src/App.css

.app {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  color: #6e6e6e;
}

 

electron-react-app/src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

 

파일이 생성된 후에는 프로젝트 root 아래 main.js를 생성해줍니다.

 

electron-react-app/main.js

const { app, BrowserWindow } = require('electron')

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  })

  win.loadFile('./build/index.html')

  win.webContents.openDevTools()
}

app.whenReady().then(createWindow)

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

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

 

앞에서 작성한 main.js와 다른 점은 index.html을 public 경로에서 읽는 것이 아니라 build라는 경로 아래의 것으로 읽는다는 것입니다. 이는 Babel과 Webpack으로 전환되고 번들링된 html을 읽기 위한 것입니다. 그리고 실제로 실행될 때도 빌드가 실행될 수 있도록 package.json의 scripts 아래에 start를 다음과 같이 입력해줍니다.

 

electron-react-app/package.json

{
  "name": "electron-react-test",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "start": "webpack --mode development&&electron ."
  },
  ...
}

 

이제 경로에서 npm start로 electron 앱을 실행하면 build 아래 index.html과 main.js라는 파일로 빌드된 결과를 확인할 수 있으며, 다음과 같은 화면을 확인할 수 있습니다.

 

정상적으로 창이 뜨신다면 이제부터 src 경로 아래의 App.js 등을 편집하시거나 추가적인 파일을 생성하여 일반적인 React.js와 같이 사용하시면, electron의 화면을 변경하실 수 있습니다.

'Javascript > Electron' 카테고리의 다른 글

Electron + React 데스크탑 앱 개발 (1)  (2) 2019.06.27