(작성중) React와 Electron으로 데스크톱 앱 만들기

곽태욱·2020년 1월 18일
15

0. 사전 설치

Node.js

https://velog.io/@gwak2837/Node.js-%EC%84%A4%EC%B9%98

yarn (선택)

NPM(Node Package Manager)을 대체할 수 있는 패키지 매니저다. 패키지 설치 속도가 NPM보다 좀 더 빠르다고 하지만, NPM과 기능면에선 차이가 없기 때문에 NPM을 사용할 예정이면 설치하지 않아도 된다. 아래 링크에서 설치하고 아래 명령어로 설치된 버전을 확인한다.
https://yarnpkg.com/lang/en/

> yarn -v
1.21.1

Visual Studio Code (선택)

Microsoft에서 개발한 텍스트 편집기다. 널리 쓰이고, 선호도도 높고, 커스터마이징도 쉽고, Javascript로 개발하는데 편리하기 때문에 설치하면 좋다. 아래 링크에서 설치할 수 있다.
https://code.visualstudio.com/

참고로 Visual Studio Code도 Electron을 기반으로 제작됐다.

1. React 프로젝트 생성

CRA(create-react-app)는 명령어 1줄로 react 개발 환경을 자동으로 생성해주는 패키지다. CRA 명령을 실행하면 내부적으로 React와 React-DOM 등을 설치한다. NPM으로 패키지를 설치하는 대신 아래와 같이 NPX를 사용하면 항상 최신 버전의 CRA로 React 실행 환경을 만들 수 있다. app-name은 임의로 설정해도 된다.

> npx create-react-app app-name --template typescript
또는 
> yarn create react-app app-name --template typescript

2. Electron 설치

React 프로젝트 폴더가 만들어지면 해당 폴더로 이동한 후 터미널을 열어 Electron과 Electron을 빌드하는 패키지를 설치하고, 이 둘을 devDependancy 목록에 추가한다.

> yarn add electron electron-builder --dev

3. 기타 개발 도구 설치

디버깅을 도와주는 여러 패키지를 설치한다.

> yarn add electron-is-dev
yarn add concurrently wait-on cross-env --dev
  • electron-is-dev
    Electron이 개발 환경에서 실행 중인지 확인할 수 있는 패키지

  • concurrently
    여러 명령어를 병렬적으로 실행할 수 있게 도와주는 명령어

  • wait-on
    특정 포트, 파일, HTTP 자원 등이 활성화될 때까지 기다려주는 크로스 플랫폼 명령어

  • cross-env
    프로그램을 CLI 환경에서 실행시킬 때에 Windows, Linux, macOS 등 OS에 관계없이 동일한 문장으로 환경변수를 설정할 수 있게 도와주는 명령어

4. Typescript 설치 (선택)

필요하다면 Typescript도 설치한다.

> yarn add typescript

tsconfig.json (필요하나?)

프로젝트 폴더 안에 tsconfig.json파일을 새로 만든다. 이 파일에서 typescript 컴파일 옵션을 정할 수 있다.

{
  "compilerOptions": {
    ...
    "target": "ES2015",
    "sourceMap": true
  },
  "include": [ ..., "./public/electron.ts"],
  "exclude": ["node_modules"]
}
  • "target": "ES2015"
    typescript를 javascript ES6(ES2015)버전으로 컴파일한다.

  • "sourceMap": true
    컴파일 시 .js.map 파일도 생성한다.

  • "include": ["./public/electron.ts"]
    public 폴더 내 electron.ts 파일을 컴파일한다.

  • "exclude": ["node_modules"]
    node_modules 폴더는 컴파일에서 제외한다.

5. Electron 실행 코드 작성

public 폴더 안에 electron.ts 파일을 생성하고 아래와 같이 적는다.

// public/electron.ts
import { app, BrowserWindow } from 'electron';
import * as isDev from 'electron-is-dev';
import * as path from 'path';

// 1. Gabage Collection이 일어나지 않도록 함수 밖에 선언함.
let mainWindow: BrowserWindow;

function createWindow() {
  mainWindow = new BrowserWindow({
    // 이것들은 제가 사용하는 설정이니 각자 알아서 설정 하십시오.
    //alwaysOnTop: true,
    center: true,
    //fullscreen: true,
    kiosk: !isDev,
    resizable: true,
    webPreferences: {
      // 2.
      // 웹 애플리케이션을 데스크탑으로 모양만 바꾸려면 안 해도 되지만,
      // Node 환경처럼 사용하려면 (Node에서 제공되는 빌트인 패키지 사용 포함)
      // true 해야 합니다.
      nodeIntegration: true
    }
  });

  // 3. and load the index.html of the app.
  if (isDev) {
    // 개발 중에는 개발 도구에서 호스팅하는 주소에서 로드
    mainWindow.loadURL('http://localhost:3000');
    mainWindow.webContents.openDevTools();
  } else {
    // 프로덕션 환경에서는 패키지 내부 리소스에 접근
    mainWindow.loadFile(path.join(__dirname, '../build/index.html'));
  }

  // Emitted when the window is closed.
  mainWindow.on('closed', () => {
    mainWindow = undefined!;
  });
}

// 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.on('ready', createWindow);

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('activate', () => {
  if (mainWindow === null) {
    createWindow();
  }
});

6. package.json 파일 수정

프로젝트 폴더에 있는 package.json파일에 아래 문장을 추가한다.

{
  ...,
  "description": "YOUR_DESCRIPTION",
  "author": "AUTHOR",
  "main": "public/electron.js",
  "homepage": "./",
  "scripts": {
    "react-start": "react-scripts start",
    "react-build": "react-scripts build",
    "react-test": "react-scripts test",
    "react-eject": "react-scripts eject",
    "start": "concurrently \"cross-env BROWSER=none yarn react-start\" \"wait-on http://localhost:3000 && electron .\"",
    "build": "yarn react-build && electron-builder",
    "release": "yarn react-build && electron-builder --publish=always"
  },
  ...
}

우리가 최종적으로 사용할 스크립트는 3가지 정도 있다.

  • start
    디버그 및 개발 용도로 사용

  • build
    dist 폴더에 독립된 실행 파일 생성

  • release
    dist 폴더에 독립된 실행 파일 생성 및 배포

"main": "public/electron.js" : 프로그램의 시작점을 public 폴더 내 electron.js 파일로 설정한다.
"electron-dev": "..." : React를 브라우저에 표시하지 않고 실행하는 명령과, http://localhost:3000에 React가 활성화될 때까지 기다린 후 Electron을 실행하는 명령을 병렬적으로 실행하는 과정을 electron-dev 명령어로 단축한다. 이 단축어 이름은 아무거나 가능하다.

7. Electron.ts 컴파일

아래 명령어를 입력해 typescript 파일을 컴파일한다. 컴파일할 대상은 tsconfig.json에 미리 정의했기 때문에 tsc만 입력하면 된다. 이 과정은 Electron.ts파일이 변경될 때만 실행해주면 된다.

> yarn tsc ./public/electron.ts

프로젝트 구조

여기까지 따라왔다면 프로젝트 폴더 구조는 대충 이럴 것이다.

  • .git : Git에 관한 설정이 들어있다. (신경 안 써도 됨)

  • node_modules : 현재 프로젝트에 필요한 패키지 파일이 들어있다. (신경 안 써도 됨)

  • public: 가상 DOM을 사용하는 리액트도 실제 DOM 파일은 필요하다. 즉, 소스 코드에서 선언된 React 컴포넌트가 들어갈 실제 HTML이 필요한 것인데, 이 폴더에 그 파일들이 존재한다.

    • favicon.ico : 페이지 상단 아이콘에 쓰일 이미지 파일
    • index.html : React 가상 DOM이 렌더링돼서 들어가는 실제 DOM 파일
    • manifest.json : 웹 앱 매니페스트는 사용자가 앱을 볼 것으로 예상되는 영역(예: 휴대기기 홈 화면)에 웹 앱이나 사이트를 나타내는 방식을 개발자가 제어하고, 사용자가 시작할 수 있는 항목을 지시하고, 시작 시의 모습을 정의할 수 있는 JSON 파일이다.
    • electron.js : electron을 실행하기 위한 프로세스 진입점
    • electron.ts : electron.js의 컴파일 전 파일
    참고 : https://create-react-app.dev/docs/using-the-public-folder/
  • src : React 소스 코드가 포함된 폴더이다. 여기서 주로 React 컴포넌트를 생성하고(js), 그 컴포넌트에 스타일을 입히고(css), 내부 동작을 제어하는 코드 등을 작성한다. App.js와 index.js 파일만 있으면 나머지 파일 없이도 React를 실행할 수 있다.

    • App.js : React 메인 컴포넌트인 App이 정의된 파일
    • index.js : React 컴포넌트를(기본 : App) 실제 DOM인 index.html의 특정 위치에(기본 : root) 렌더링하는 파일
    • css 파일 : 컴포넌트를 디자인하는 파일

8. Electron 실행

이제 아래 명령어를 입력해 프로그램이 제대로 실행되는지 확인한다.

> yarn start

개발 환경 설정 완료

아래 사진이 나오고 저 React 로고가 빙글빙글 돌고 있으면 실행에 성공한 것이다. 그리고 코드를 수정하고 파일을 저장하면 수정된 점이 바로 Electron에 반영된다.

9. Electron 빌드

Node나 기타 패키지 등 별도의 설치 없이 독립적으로 실행할 수 있는 파일을 dist 폴더에 생성한다.

> yarn build

10. Electron 배포

> yarn release
참고 : https://musma.github.io/2019/07/17/electron-getting-started.html
profile
이유와 방법을 알려주는 메모장 겸 블로그. 블로그 내용에 대한 토의나 질문은 언제나 환영합니다.

1개의 댓글

comment-user-thumbnail
2023년 9월 21일

Electron ... 굉장히 재밌어보이는 녀석이군요, 얼핏 보기에 리액트 앱을 일랙트론으로 감싸는 형식 같아보입니다(맞나요...? 쿨럭).

저도 한 번 미니 프로젝트로 데스크톱 앱을 만들어보고 싶어지네요!

저도 블로그를 작성할 때 (작성중)을 붙여놓고 시간을 들여 조금씩 글을 완성해 나가는데, 다음 내용이 궁금해집니다 ㅎㅎ

코코넛톡 탄생기 시리즈를 보러 또 방문하겠습니다. 감사합니다!

답글 달기