티스토리 뷰
Program Version Upgrade (w. NW.js And Electron)
현재 NW.js의 버전은 0.24.4를
사용 중입니다.
가장 큰 문제는 현재 jQuary, WebSQL, NW.js 옛 버전의 API 등 레거시 코드들을 사용하며 Svelte + routify로 변환 중에 있어 잘 동작하지 않는 부분과 routify 라이브러리가 동작하지 않아 문제였습니다.
이로 인해 1. 버전을 upgrade 2. Electron으로 대체와 같은 2가지 방법을 생각하고 있는 상황이며 문제를 해결하기에 앞서 해당 내용들(Cross-Platform Desktop Application
, NW.js(node-webkit)
, Electron
)에 대해 알아보도록 하겠습니다.
Cross-Platform Desktop Application
Cross(교차) + Platform + Desktop Application의 합성어로 다양한 플랫폼에서 사용할 수 있는 Desktop Application입니다.
사실 Cross-Platform을 구축하기 위해 Node.js를 많이 사용하는 편입니다. 보통 서버 측 애플리케이션을 구축하는 프로그래밍 프레임워크로 알려져 있지만 Slack, Visual Studio Code(IDE)등도 Node.js
데스크톱 앱을 사용한 것입니다.
Node.js 데스크톱 애플리케이션을 기원
2000년 초에 대부분의 소프트웨어는 상점에서 구입할 수 있는 압축 포장된 상자에 데스크톱 앱으로 제공되었으며 CD-ROM을 통해 소프트웨어를 설치하였습니다.
시간이 지나서 AJAX의 출현으로 소프트웨어를 웹/앱으로 제공하게 되었습니다. 이로인해 컴퓨터에 다운로드를 할 필요가 없으며 다양한 OS에서 실행할 수 있으며 소프트웨어를 온라인으로 제공하기 시작하였습니다.
그리고 Apple iPhone 및 Android 모바일앱의 출현등 큰 사건들이 있었지만 2000년대 이후 가장 크게 달라진 점은 OS 중 가장 강력한 Windows 약화로 인해 Mac OS 및 Linux에서도 작동하는 데스크톱 앱을 개발해야 되었습니다.
일반적으로 데스크톱 앱은 C, C++ 및 C#과 같은 프로그래밍 언어를 이용하여 개발하였지만 NW.js 및 Electron등의 등장으로 Node.js
를 가지고 기존 웹/앱을 만드는 데 사용되는 것과 동일한 코드로 빌드하고 Windows, Mac OS 및 Linux에서 작동하는 데스크톱 앱을 Html
, Css
, JavaScript
를 사용하여 쉽게 개발할 수 있게 되었습니다.
NW.js 및 Electron의 기원
2011년 Roger Wang은 Intel의 Open Source Technology Center에서 WebKit
(당시 Safari, Konqueror 및 Google Chrome 뒤에 있는 브라우저 엔진)과 Node.js
을 결합하는 방법을 찾아내어 내부에서 실행되는 JavaScript
코드에서 Node.js
모듈에 액세스할 수 있도록 하였습니다. (node-webkit
)
2012년 Cheng Zhao라는 대학생이 node-webkit
작업을 위해 Intel 인턴으로 Node.js
와 Webkit
이 결합된 방식을 변경 및 내부 아키텍처 개선을 Roger과 협력하였습니다. 코드가 발전함에 따라 node-webkit
은 Node.js
모듈에서 데스크탑 앱을 위한 프레임워크가 되었습니다.
2012년 12월 cheng Zhao는 Intel을 떠나 GitHub의 계약직으로 GitHub의 Atom
편집기를 Chromium Embedded Framework 및 기본 JavaScript
바인딩에 node-webkit
을 사용하게 하려 했지만 어려움이 있어 그들은 Atom용 기본 쉘인 Atom Shell
을 만들게 되었고 추 후 node-webkit
은 NW.js
로 Atom Shell
은 Electron
으로 개발되어 많은 사랑을 받고 있습니다.
NW.js
와 Electron
모두 Chromium, Node.js, API 요소를 가지고 있어 용어를 알고 가도록 하겠습니다.
Chromium : Google에서 만든 Google 브라우저 Chrome에서 사용하는 오픈 소스 라이브러리
Node.js : 서버에서 JavaScript
를 작성하고 파일 시스템 및 네트워크에 액세스 하기 위한 도구 (컴퓨터도 서버)
API : 애플리케이션 프로그램 인터페이스로 라이브러리와 함께 사용할 수 있는 기능 세트
JavaScript 컨텍스트 : JavaScript
코드에 제공할 환경 정보들을 모아놓은 객체
NW.js(node-webkit)
: HTML
, CSS
및 JavaScript
로 데스크톱 앱을 구축하기 위한 프레임 워크
(V8의 공통 사용을 통해 Chromium
의 브라우저 엔진과 Node.js
(프로그래밍 프레임워크)의 조합)
동작
웹/앱과 NW.js
데스크톱 앱을 같이 보면서 NW.js
의 동작의 큰 틀을 알아보겠습니다.
[웹/앱]
클라이언트가 웹 페이지 요청 및 API 요청을 하고 서버에서 코드 실행 후 해당 데이터를 클라이언트에 다시 제공하는 형태입니다.
[NW.js]
NW.js
앱에서 앱 창은 내장된 웹 브라우저와 비슷하지만 웹 페이지 내부의 코드가 컴퓨터 리소스에 액세스 할 수 있고 서버 측 코드도 실행할 수 있습니다. 즉, 클라이언트와 서버의 코드를 동일한 위치에서 실행시킬 수 있습니다.
내부적으로 보면 다음과 같이 작동을 합니다.
- Node.js는 OS 작업을 처리
임베디드 웹 브라우저의 콘텍스트를 통해 Node.js를 사용. - Blink(Chromium Rendering Engine)는 앱의 프런트엔드 랜더링 처리
- Node.js 와 Blink는 V8을 통해
JavaScript
를 실행Node.js
와Chromium
을 로드하여 둘 다 V8 엔진에 로드된JavaScript
콘텍스트를 갖는다.Node.js
의JavaScript
콘텍스트는 모듈, 프로세스 및 요구 사항과 같은 전역 객체 및 기능을 노출한다.Chromium
의JavaScript
컨텍스트는 창, 문서 및 콘솔과 같은 전역 객체 및 기능을 노출한다.
기능
- OS에 대한 기본 UI 및 API 생성 및 액세스를 위한
JavaScript
API: 창 제어, 메뉴 항목 추가, 파일 읽기/쓰기 등 - 앱 내에서
Node.js
를 사용하고 npm을 통해Node.js 모듈
의 라이브러리 설치하고 사용가능 - 단일 코드베이스에서 각 OS에 대한 앱의 실행 파일을 빌드할 수 있음
간단 구현
NW.js
로 감싸주고 nw-builder
로 실행 파일까지 만들어주는 간단한 구현 과정입니다.
- 파일 구조
📦NumberBaseballGame
┣ 📜package.json
┗ 📦src
┣ 📂js
┃ ┣ 📜ballstrike.js
┃ ┣ 📜comnum.js
┃ ┗ 📜playgame.js
┣ 📜index.html
┣ 📜index.js
┗ 📜package.json
- NW.js 및 nw-builder 설치
npm install -D nw@0.77.0-sdk nw-builder
- src 외부 package.json의 script 변경
{
"scripts": {
"dev:nw": "nw src/",
"prod:nw": "nwbuild --platforms win32,win64,osx64,linux32,linux64 --buildDir dist/ src/"
}
}
- src 내부 package.json의 script 변경
{
"main": "index.html",
...
"window": {
// NW.js 공식 Docs의 Manifest format
"title": "NumberBaseballGame",
"toolbar": true,
"width": 1000,
"height": 1000,
"min_width": 1000,
"min_height": 1000,
},
}
- 메인 html src 변경
<!DOCTYPE html>
<html lang="kr">
<script type="module" src="index.js"></script>
</html>
문제
NW.js
최신 버전 + nw-builder
최신 버전으로 사용하다 보니 다음과 같은 에러가 발생하였습니다.
에러 메시지를 보면 다음과 같습니다.
Error: package.json not found in srcDir file glob patterns
'package.json에서 srcDir 파일 glob 패턴을 찾지 못했다'라고 되어 있는데 우선 glob 패턴에 대해서 알아야 했습니다.
glob 패턴은 과거 리눅스 운영체제에서 한 번에 여러 개의 파일을 찾을 때 사용해 온 패턴 매칭 기법이지만 현재는 많은 프로그래밍 언어에서 지원합니다.
즉, * 사용입니다.
그래서 경로를 잘 찾지 못하고 있다고 판단이 되어 nw-builder
를 사용하는 부분에서 경로를 잘 설정하고 명령어에 오류가 있을 수 있어 공식 문서를 보면서 시도해 봤지만 잘 되지 않았습니다.
고민을 했지만 stackoverflow 및 블로그 어디에도 다양한 정보들이 없었습니다. 그래서 차선책으로 nw-builder
가 크게 바뀌기 전 버전을 사용해 보니 문제가 해결되었습니다.
진짜 최신이 가장 좋은 것이다라는 생각을 많이 하였는데 안정적인 버전이 더 좋은 것 같다고 느끼게 되었습니다.
Electron
: JavaScript
, Html
및 Css
로 데스크톱 앱을 구축하는 데 사용할 수 있는 라이브러리
구성 요소
App : Node.js
로드, Chromium
콘텐츠 모듈 로드, libuv
액세스와 같이 Electron 시작 시 로드해야 하는 코드 처리하는 파일 모음
Browser : JavaScript
엔진 초기화, UI 상호 작용, 각 OS별 바인딩과 같은 프런트엔드 부분과 상호작용을 처리하는 파일 모음
Renderer : Electron의 렌더러 프로세스에서 실행되는 코드용 파일
Common : 앱을 실행하기 위한 기본 및 렌더러 프로세스에서 모두 사용하는 유틸리티 코드 + Node.js의 이벤트 루프에 대한 메시징을 Chromium의 이벤트 루프에 통합하는 코드
동작
Chromium
소스 코드와 앱 간의 명확한 분리 하여 Chromium
구성 요소를 더 쉽게 업그레이드하고 소스 코드에서 Electron을 컴파일하는 것이 훨씬 간단하게 합니다.
조금 더 자세히 말하면 Electron
은 백엔드 코드의 JavaScript
상태를 프런트엔드 앱 창의 상태와 별도로 유지하여 Node.js
및 Chromium
의 JavaScript
콘텍스트를 처리합니다.
(Node.js
모듈은 백엔드에 대한 별도의 프로세스에서 작동한다는 점에 주의하며 백엔드와 앱 창 간의 데이터 공유가 프로세스 간 통신 또는 메시지 전달을 통해 처리되는 이유입니다.)
간단 구현
electron
로 감싸주고 electron-builder
로 실행 파일까지 만들어주는 간단한 구현 과정입니다.
- 파일 구조
📦NumberBaseballGame
┣ 📜package.json
┗ 📦src
┣ 📂js
┃ ┣ 📜ballstrike.js
┃ ┣ 📜comnum.js
┃ ┗ 📜playgame.js
┣ 📜index.html
┣ 📜index.js
┗ 📜package.json
electron
및electron-builder
설치
npm install -D electron electron-builder
- src 외부
package.json
의 script 변경
{
"scripts": {
"dev:electron": "electron main.js",
"prod:electron": "electron-builder --win portable --x64"
}
}
- src 외부
main.js
구현
const { app, BrowserWindow } = require('electron');
function createWindow() {
const mainWindow = new BrowserWindow({
width: 800,
heigth: 600,
});
mainWindow.loadFile('./src/index.html');
}
app.whenReady().then(() => {
createWindow();
});
NW.js VS Electron
앱 실행 처리 방법
NW.js
: 데스크톱 앱의 백엔드 및 프런트엔드 부분은 Node.js
및 Chromium
이벤트 루프를 통합하고 JavaScript
콘텍스트를 Node.js
에서 Chromium
으로 복사함으로써 상태를 공유
=> 백엔드, 프런트엔드 동일한 JavaScript 콘텍스트 참조
Electron
: 상태를 공유하기 위해 백엔드의 ipcMain 모듈 와
프런트엔드의 ipcRenderer 모듈
을 거쳐 기본 프로세스와 렌더러 프로세스의 JavaScript
콘텍스트가 분리되어 유지되지만 데이터는 명시적인 방식으로 프로세스 간에 전송될 수 있습니다.
=> 백엔드, 프런트엔드 각각 모듈을 거치며 JavaScript 콘텍스트 분리 but 데이터 공유
Node.js 작동
NW.js
: 임베디드 웹 브라우저의 콘텍스트를 통해 Node.js
를 사용
=> Node.js
의 API 및 브라우저의 JavaScript
네임스페이스(ex. WebSocket)와 관련된 API 메서드에 모두 액세스 하는 JavaScript
파일을 스크립트할 수 있다.
(이 방법은 NW.js
가 Node.js
와 Blink 렌더링 엔진
의 JavaScript
네임스페이스를 병합하고 두 가지의 기본 이벤트 루프를 병합하여 공유 콘텍스트에서 작동하고 상호 작용할 수 있도록 하는 방식으로 가능합니다.)
Electron
: Chromium
과 함께 Node.js
를 사용하지만 Node.js
와 Chromium
의 이벤트 루프를 함께 결합하는 대신 Node.js
의 node_bindings
기능을 사용합니다.
=> 소스 코드의 사용자 정의 수정 및 후속 컴파일 없이 Chromium
및 Node.js
구성 요소를 쉽게 업데이트할 수 있습니다.
추가 정보 요약
사실 Node.js
와 Chromium
의 연결이 가장 중요한 부분이라고 생각이 됩니다.
추가적인 정보에 대한 요약이 궁금하시면 해당 링크를 보는 것이 좋습니다.
NW.js
에서Node.js
와Blink
는 여러 창 간에 데이터를 공유하는 데 사용할 수 있는JavaScript
콘텍스트를 공유합니다.- 이러한
JavaScript
상태 공유는 동일한NW.js
앱에 대한 여러 앱 창이 동일한 상태를 공유할 수 있음을 의미합니다. NW.js
는 맞춤 바인딩이 있는 컴파일된Chromium
버전을 사용하는 반면Electron
은Chromium
의 API를 사용하여Node.js
를Chromium
과 통합합니다.Electron
은 프런트엔드와 백엔드 사이에 별도의JavaScript
콘텍스트를 가지고 있습니다.Electron
앱에서 프런트 엔드와 백 엔드 간에 상태를 공유하려면ipcMain
및ipcRenderer
API를 통해 전달되는 메시지를 사용해야 합니다.
마치며
결국 많은 상황을 본 결과 NW.js만 버전 업을 하기로 하였습니다.
Electron으로의 변환, NW.js와 관련된 nw-builder의 버전 업들은 현재 프로그램에서 연관되고 최신 버전에서 사용하지 않은 것들을 사용하고 있고 현재 개인당 한 가지의 서비스를 개발하고 있어 인원적인 측면으로도 시간적인 측면으로도 여유가 없어서 NW.js 버전 업만 하기로 결정을 하게 되었습니다.
그리고 해당 내용에 대해 발표도 같이 준비를 하는데 논문 파듯이 너무 깊게 발표 준비를 하여 많은 시간을 할애하는 저를 발견했습니다.
이 부분에 대해서 조언을 받고 간단 구현 -> 간단 설명 -> 필요하면 깊은 설명으로 틀을 잡았습니다. (사실 간단 구현 -> 간단 설명만 해도 충분한 것 같습니다.)
또한 버전 업그레이드 관련에 생각을 하면서 연관된 프로그램의 각자 버전이 너무 중요하고 무조건 최신 버전이 중요한 것이 아니라 프로그램이 안전하게 돌아가는 버전이 중요하다는 것을 알게 되는 경험이었습니다. 그러나 NW.js와 nw-builder에 관한 내용이 많이 없어 힘들었습니다. (Document를 보는 능력이 조금 성장해서 좋았다 ㅎㅎ)
NW.js 버전을 업그레이드하여 CheckList를 바탕으로 테스트를 하고 build 한 내용들을 package로 잘 감싸서 사용자들이 잘 사용할 수 있게 만들어야겠습니다.
(추 후 업그레이드할 때마다 CheckList를 바탕으로 직접 테스트하는 수고를 덜기 위해 테스트 코드도 작성해보고 싶습니다.)
마지막으로 이러한 과정을 통해 많은 문제가 있었지만 생각하는 시간을 줄이고 행동하는 시간을 늘리게 되는 좋은 경험이었고 다음 스탭을 나아가기 위해 행동해야겠습니다.
긴 글 읽어주셔서 감사합니다.
Ref
https://livebook.manning.com/book/cross-platform-desktop-applications/chapter-1/207
https://livebook.manning.com/book/cross-platform-desktop-applications/chapter-6/1
https://github.com/electron/electron/issues/5172#issuecomment-210697670
http://tangiblejs.com/posts/nw-js-and-electron-compared-2016-edition
https://freecontent.manning.com/how-does-node-js-work-with-nw-js-and-electron/
https://docs.nwjs.io/en/latest/For%20Users/Advanced/JavaScript%20Contexts%20in%20NW.js/#concept-of-javascript-context
https://www.electronjs.org/
'Tip and Error' 카테고리의 다른 글
설치 파일 만들기 (w. Inno Setup) (8) | 2023.07.13 |
---|---|
[문제] useNavigate()의 state값이 null인 경우 (0) | 2023.07.03 |
[Error] Error: package.json not found in srcDir file glob patterns (0) | 2023.06.30 |
2. OAuth 2.0 카카오 간단 구현 (0) | 2023.06.17 |
1. OAuth 2.0 소셜 로그인 개념 (0) | 2023.06.12 |