조금 바보같았던 리액트 프로젝트 일렉트론으로 감싸 데스크톱 앱 만들기 (1)

eunjeong·2024년 5월 10일

스터디원들이랑 프로젝트를 하나 기획했다 ..! 이름은 Study with me❣️
'electron'을 사용하면 평소 개발하는 리액트 프로젝트를 데스크톱 앱으로 만들 수 있다.
개발 시작에 앞서 레포지토리에 최초 커밋을 하고싶었던 나는 프로젝트를 만들면서 electron까지 설정하려고 봤는데 ..
이날 가장 크게 참고한 velog 포스팅이다. (감사합니다 혹시 댓글이나 먼저 양해를 구해야하는건가요..?)

electron 프로젝트는 yarn 사용을 강력 권장한다고 한다(Docs 피셜)

또한 Node.js 기반에서 동작하기 때문에 나는 호환 버전을 찾았을 때, 다음과 같은 버전 조합으로 사용했다.

  • Electron: 30.0.2
  • React: 18.x
  • Node.js: 16.x 이상
  • Yarn: 3.x

그럼 시작해보자 'v'

프로젝트 생성하기

npx create-react-app study_with_me --template typescript

나는 타입스크립트를 사용하기로 팀원들과 합의를 해서 타입스크립트 템플릿을 사용해서 리액트 프로젝트를 생성했다!

electron 설치하기

yarn add electron electron-is-dev electron-builder concurrently cross-env wait-o
n --dev

개발에 필요한 일렉트론 모듈을 설치한다.

  • electron-is-dev : 지금 개발모드인지 빌드상태인지 체크할 수 있다. (진짜 좋은 세상인걸 느낀다..)
  • electron : electron 기본 패키지
  • electron-builder : 일렉트론을 데스크탑 앱으로 만들어주는 빌드 패키지인듯 하다
  • concurrently : 두 개 이상의 명령어를 실행할 수 있다고 한다
  • cross-env : 운영체제의 제약을 받지않게 환경변수 값을 설정해준다.
  • wait-on : 파일, 포트, 소켓, http(s) 리소스가 사용 가능해질 때 때까지 대기하는 크로스 플랫폼 CLI 이다.

이렇게 설치한 패키지들을 바탕으로 package.json 파일을 수정해 줘야한다!

  "main": "./pubilc/main.ts",
  "homepage": "./",
  "scripts": {
    "electron": "wait-on http://localhost:3000 && electron .",
    "compile-main": "tsc ./pubilc/main.ts --outdir ./compile-main",
    "dev": "concurrently \"yarn start\" \"yarn electron\""
  },

electron은 node 단에서 실행되기 때문에 루트 주소를 최상단으로 바꿔주는 과정인 것 같다.
또한 electron이 실행하는 main 스크립트가 필요하다.
스크립트 단에 start, build, test, eject가 있을 텐데, 저렇게 3가지를 추가해준다

  • electron : 원래라면 react dev server가 실행되기 전에 electron을 실행해 화면이 안나온다
    -> 위에서 설치한 wait-on 패키지를 사용해 react server가 실행되고 나서 일렉트론 프로세스를 실행한다.
  • compile-main : 원래 electron에서는 js만 컴파일 하기 때문에 ts파일을 js로 컴파일하는 명령어인것 같다.
  • dev : 우리가 개발자모드로 실행할 때 yarn start와 yarn electron을 같이 실행하는 명령어
    -> 아까 설치했던 concurrently 패키지를 사용한 것을 확인할 수 있다.

main 스크립트

import {BrowserWindow, app} from 'electron'
import * as path from 'path'
import * as isDev from 'electron-is-dev'

const BASE_URL = 'http://localhost:3000'

// BrowserWindow 객체는 전역으로 관리합니다.
// 전역이 아닌 경우 자바스크립트 가비지 컬렉팅 발생 시 의도치 않게 browser window가 닫힐 수 있습니다. 
let mainWindow: BrowserWindow | null = null

const createWindow = () => {
  // browser window를 생성합니다.
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    resizable: true,
    webPreferences: {
      devTools: isDev,
      nodeIntegration: true,
      preload: path.join(__dirname, 'preload.js')
    }
  })
  
  // 앱의 index.html을 로드합니다.
  if (isDev) { // 개발 모드인 경우
    mainWindow.loadURL(BASE_URL); // 개발 도구에서 호스팅하는 주소로 로드합니다. 
    mainWindow.webContents.openDevTools({mode: 'detach'}) // DevTools를 엽니다.
  } else { // 프로덕션 모드인 경우
    mainWindow.loadFile(path.join(__dirname, './build/index.html')) // 
  }
}

// Electron이 준비되면 whenReady 메서드가 호출되어,
// 초기화 및 browser window를 생성합니다.
app.whenReady().then(() => {
  createWindow()

  // Linux와 Winodws 앱은 browser window가 열려 있지 않을 때 종료됩니다.
  // macOS는 browser window가 열려 있지 않아도 계속 실행되기 때문에,
  // browser window가 열려 있지 않을 때 앱을 활성화 하면 새로운 browser window를 열어줍니다.
  app.on('activate', () => {
    if(BrowserWindow.getAllWindows().length === 0) {
      createWindow()
    }
  })
})

// Linux와 Winodws에서는 모든 창을 종료하면 일반적으로 앱이 완전히 종료됩니다.
// macOS(darwin)가 아닌 경우, 'window-all-closed' 이벤트가 발생했을 때, 앱을 종료합니다.
app.on('window-all-closed', () => {
  if(process.platform !== 'darwin') {
    app.quit()
  }
})

실행은 됐지만 일렉트론 창이 안나올 때..

자 여기서 나는 진짜 정말 너무 멍청한 실수를 한다ㅠ


이렇게 yarn dev 명령어를 입력하면 페이지가 잘 뜨는데...
electron screen이 안나왔다...
이것때문에 진짜 4시간 넘게 찾아봤는데 나만큼 멍청이는 없었나보다.
결론만 말하자면


이렇게 연결프로그램을.. 열어주면 된다..

이런걸로 고생한 내가 너무 부끄러워서 포스팅 할까 고민했지만
세상엔 나만큼 바보도 많을거라고 생각한다 'ㅠ'
누군가한텐 도움이 될거다... 아마도..

그렇게 열기버튼을 눌러주면

짜라란 ~ 'v'
이제 깃 init commit을 할 수 있게 됐다.
그럼 끝 !

0개의 댓글