저번 글에 이어서 이번 글에서는 React, Typescript, Electron으로 간단한 게임 런쳐를 구현해보려고 합니다.
우선 프로젝트 구조는 다음과 같습니다.
my-game-launcher/
├── package.json // Electron과 React 실행 스크립트 포함
├── tsconfig.json
├── public/
│ └── index.html // React HTML 템플릿 (Create React App 템플릿)
| └── electron.js
└── src/
├── index.tsx // React 진입점 (TypeScript)
├── App.tsx // React 컴포넌트 (게임 런처 UI, 슬라이드 효과)
└── App.css // CSS 스타일
React 프로젝트 생성 (feat.Typescript)
npx create-react-app electron --template typescript
여기서 주의할 점은 위 명령어로 프로젝트를 생성하게 되면 React 19버전으로 생성됩니다.
React 19버전은 아직 호환되지 않는 패키지가 많기 때문에 18버전으로 다운그레이드 하시면 됩니다.
Electron 패키지 설치
npm i electron-is-dev
npm i -D electron electron-builder concurrently cross-env wait-on
- electron-is-dev
개발 환경과 프로덕션 환경을 확인합니다. - electron
electron 패키지입니다. - electron-builder
일렉트론을 패키징하는 모듈입니다.
정말 다양한 옵션이 있으므로 공식문서를 참고하시면 좋을 듯 합니다. - concurrently
두 개 이상의 명령어를 하나의 스크립트에서 실행할 수 있도록 해줍니다. - cross-env
운영체제마다 다른 환경변수 설정을 통일시켜줍니다. - wait-on
node 환경에서 하나 이상의 포트, 소켓같은 자원이 사용 가능해질 때까지 대기하도록 지연시키는 모듈입니다.
Main Process 파일 생성
앞선 글에서 말했듯이 Electron에서 Main Process 파일은 애플리케이션의 진입점입니다.
Electron API를 사용해 애플리케이션의 라이프사이클을 관리합니다.
// public/electron.js
// Electron 모듈에서 app과 BrowserWindow 클래스를 비동기로 가져옵니다.
// app: Electron 애플리케이션의 생명주기를 관리합니다.
// BrowserWindow: 새 브라우저 창(애플리케이션 창)을 생성하는 클래스입니다.
const { app, BrowserWindow } = await import("electron");
// Node.js의 내장 모듈인 path를 가져옵니다.
// 파일 및 디렉터리 경로를 다루는 데 사용됩니다.
const path = await import("path");
// electron-is-dev 모듈을 가져와서 현재 애플리케이션이 개발 환경인지 아닌지를 확인합니다.
// isDev는 개발 환경일 경우 true, 그렇지 않으면 false 값을 가집니다.
const isDev = await import("electron-is-dev");
// 애플리케이션의 메인 창을 저장하기 위한 변수입니다.
let mainWindow;
// 새 창을 생성하는 함수입니다.
function createWindow() {
// BrowserWindow 인스턴스를 생성하면서 창의 크기와 웹 환경 설정을 지정합니다.
mainWindow = new BrowserWindow({
width: 900, // 창의 너비를 900픽셀로 설정합니다.
height: 680, // 창의 높이를 680픽셀로 설정합니다.
webPreferences: {
// 렌더러 프로세스에서 Node.js API 사용을 허용합니다.
nodeIntegration: true,
// 원격 모듈 사용을 활성화합니다.
enableRemoteModule: true,
// 개발자 도구의 사용 여부를 설정합니다.
// 개발 환경(isDev가 true)이면 개발자 도구를 활성화합니다.
devTools: isDev,
},
});
// ***중요***
// 개발 환경에서는 로컬 개발 서버(예: Create React App의 개발 서버)의 URL을 로드합니다.
// 그렇지 않으면, 빌드된 정적 파일(index.html)을 로드합니다.
mainWindow.loadURL(
isDev
? "http://localhost:3000" // 개발 서버 URL
: `file://${path.join(__dirname, "../build/index.html")}` // 빌드 폴더 내 index.html 파일 경로
);
// 개발 환경인 경우, 개발자 도구를 별도의 창으로 엽니다.
if (isDev) mainWindow.webContents.openDevTools({ mode: "detach" });
// 창 크기 조절을 허용합니다.
mainWindow.setResizable(true);
// 창이 닫힐 때의 이벤트 처리
mainWindow.on("closed", () => {
// 창 객체를 null로 설정하여 메모리에서 해제합니다.
mainWindow = null;
// 모든 창이 닫히면 애플리케이션을 종료합니다.
app.quit();
});
// 창에 포커스를 부여하여 활성화시킵니다.
mainWindow.focus();
}
// Electron 애플리케이션이 준비(ready)되면 createWindow 함수를 호출하여 창을 생성합니다.
app.on("ready", createWindow);
// macOS 환경에서는 Dock 아이콘을 클릭했을 때 창이 없으면 새 창을 생성합니다.
app.on("activate", () => {
if (mainWindow === null) createWindow();
});
// 모든 창이 닫혔을 때의 이벤트 처리
app.on("window-all-closed", () => {
// macOS가 아닌 플랫폼에서는 모든 창이 닫히면 애플리케이션을 종료합니다.
if (process.platform !== "darwin") app.quit();
});
위 코드는 공식문서에도 잘 나와있지만 추가 설명이 필요할 것 같아 chatGPT에게 주석에 설명을 추가해달라고 했습니다.
그냥 넘어가지 않고 코드 한 줄 한 줄 읽어보시는 걸 추천드립니다.
- 경로
경로의 경우 public 폴더 아래에 두어야 빌드 후에 build 폴더 바로 아래에 electron.js 파일이 생성되어 진입점 역할을 하기 수월해집니다. - 파일명 : electron-builder가 인식하는 default 메인 프로세스 파일 이름이 electron.js입니다.
고로 다른 파일 명을 사용한다면 별도 설정을 해야하기 때문에 파일 위치와 이름은 그대로 가는게 좋습니다.
package.json 설정
"type": "module",
"main": "public/electron.js",
"homepage": ".",
"scripts": {
"react-start": "react-scripts start",
"react-build": "react-scripts build",
"start": "concurrently \"cross-env NODE_ENV=development BROWSER=none yarn react-start\" \"wait-on http://localhost:3000 && electron .\"",
"build": "yarn react-build && electron-builder",
"build:win": "yarn react-build && electron-builder --win --x64"
},
- type
프로젝트를 mjs 방식으로 사용합니다.
mjs란?
.mjs는 "Module JavaScript"의 약자로, 해당 파일이 ECMAScript 모듈 형식을 사용한다는 것을 명시합니다.
Node.js는 .mjs 확장자를 가진 파일을 ESM으로 인식하며, import/export 구문을 올바르게 처리합니다 - main
Electron의 entry 파일 경로입니다. - start
개발서버가 실행되기까지 기다린 후 Electron을 실행합니다. - build
React 프로젝트를 build해 bundle 파일을 생성 후 bundle 파일을 포함해 Electron으로 packaging합니다.
옵션 없이 electron-builder가 실행될 경우 현재 구동하는 환경에 맞춰 packaging합니다.
저도 게임에 관심이 많기 때문에 Electron을 활용한 프로젝트를 해봤으면 참 좋았을텐데요 아쉬울 따름입니다..
(TMI : 더 찾아보니까 Slack, discord, VSCode, OPGG 등 생각보다 많은 인기있는 런처들이 Electron으로 개발되었다고 합니다.)
기본 프로젝트 생성까지 해봤는데요, 공식문서에 유용한 옵션들이나 Electron API들이 많다고 합니다.
Electron을 활용해 프로젝트를 진행하시는 분들은 꼭 참고하셔서 개발하시면 좋을 것 같습니다.
'Electron' 카테고리의 다른 글
Electron으로 웹 데스크탑 앱 만들기 (1) (feat. React, Typescript) (0) | 2025.02.09 |
---|