programming/node.js2017.06.04 07:32

개요

너무 오랜만에 다시 nodejs를 살펴보면서 (0점대 버전이 엊그제 같은데 벌써 8버전이라니...) 기왕 살펴 보는거 평소 궁금했던 electron으로 간단한걸 하나 만들어 보기로 했습니다. 평소 HTML WYSIWYG Editor로 문서 작성을 하는게 익숙한 터라 블로그 글이나 개인 보관 파일 설명 문서 작성용으로 오프라인용 앱이 있으면 좋겠다고 생각했었는데, 기존에 좋은 에디터가 많이 있지만 대부분 Online 연동이 필수라 이참에 electron 과 nodejs 공부도 할 겸 직접 만들어 보기로 했습니다.

주요기능

  • HTML WYSIWYG Editor
  • 로컬 파일 저장 및 열기(드래그앤 드롭으로 열기 지원)
  • 미려한? 디자인

준비물

  • Nodejs 6.10 LTS - 당연히 필요한 노드
  • CKEditor 4.7 - WYSIWYG Editor의 표준!
  • JQuery 3.2 - 필수요소
  • Bootstrap 3.3 - 미려한 디자인에 필수 요소
  • Electron 1.6 - Nodejs로 멀티플랫폼 어플리케이션을 만들어주는 라이브러리
  • Electron-packager 8.7 - Electron을 쉽게 패키징해주는 라이브러리 (Electron-builder라는 것도 있다.)

개발과정

electron 설치하기

일단 노드 설치는 되어있다 치고 프로젝트 폴더를 만들고 electron 부터 다짜고짜 설치해 봅니다.

npm install electron -g

다음을 뭘 해야할지 몰라 Quick Start를 찾아보니 다행히도 한글 번역 튜토리얼이 있었습니다.

https://github.com/electron/electron/blob/master/docs-translations/ko-KR/tutorial/quick-start.md


일단은 공부보다 무작정 개발이 우선이라 대충 읽어봅니다. 


읽어보니 packager.json, main.js, index.html 이 필요하다고 합니다.

퀵스타트에 나온 예제대로 각 파일 내용물을 복붙합니다.


실행해보기

명령프롬프트로 프로젝트로 폴더로 가서 

electron .

으로 실행해보니 어플리케이션이 잘 뜹니다! 오호...


JQuery 불러오기

이제 잘 뜨는걸 확인했으니 ckeditor와 jquery, bootstrap 을 다운받아 디자인 및 구현을 시작합니다. 일단 그냥 웹페이지 만들 듯이 편하게 구현합니다.

여기서부터 문제가 발생합니다. jquery가 제대로 실행이 안되는지 Uncaught ReferenceError: $ is not defined 에러를 뿜습니다.


내가 잘못한거겠지... 하며 자책하다가 스택오버플로우에 나온 갖가지 답변 중

window.$ = window.jQuery = require('jquery');

이렇게 해보라는 답변을 보고 npm으로 jquery를 설치한 후 해보니 또 잘 됩디다!


선해결 후원인분석 마인드로 원인을 검색해보니 이미 아웃사이더님 블로그에 잘 정리되어 있었습니다. 원인을 요약해보자면 electron은 웹브라우저 기반의 js라기 보다는 nodejs기반의 js다 보니 웹브라우저용 자바스크립트 라이브러리를 electron에서 사용할 경우엔  CommonJS 방식으로 인해 문제가 생길 수 있다는 거였습니다. 즉 jquery 뿐만 아니라 다른 웹브라우저용 js 라이브러리들도 같은 문제가 생길 수 있습니다.


파일 저장&불러오기 구현하기

다음으로 ckeditor나 bootstrap은 별도작업 없이 그냥 각각 공식홈페이지 튜토리얼의 기본셋팅만으로 에디터 환경을 꾸밉니다.


이번에는 local file를 불러오고 저장하는 기능을 구현합니다. fs와 dialog 기능을 찾아봐야 하는데 dialog 안내는 https://github.com/electron/electron/blob/master/docs/api/dialog.md 에 electron의 공식 설명이 있긴 한데 예시가 없습니다.

더 검색해보니 http://ourcodeworld.com/articles/read/106/how-to-choose-read-save-delete-or-create-a-file-with-electron-framework 에 좋은 예제가 있어 약간만 개선하여 복붙합니다.


로컬용 에디터에서 파일을 드래그앤드롭 해서 여는 기능을 자주 쓰는 터라 이 기능도 https://discuss.atom.io/t/possible-to-get-local-filesystem-path-from-drag-and-drop-file/28858 를 참고하여 구현해 봅니다.


근데 이 드래그앤드롭은 electron window 영역에서만 되고 ckeditor 에서는 동작하지 않네요. 어플리케이션 화면의 90%가 ckeditor로 덮여있는데 이런...

그래도 결국 ckeditor 쪽에서 drop 기능을 찾아서 이를 해결합니다.


윈도우 메뉴 커스터마이징하기

이번엔 electron에서 기본으로 생성해주는 Window Menu를 커스터마이징 해봅니다. 공식설명은 https://electron.atom.io/docs/api/menu/ 에서 볼 수 있고 저는 http://www.codeblocq.com/2016/09/Set-Menu-Items-in-Electron/ 문서를 참고하여 윈도우 메뉴와 단축키(저장, 다른이름으로 저장 , 새문서, 열기)를 커스터마이징 합니다.


어플리케이션 종료 전에 확인창 띄우기

이번엔 변경된 문서를 저장하지 않은 채로 창을 닫을 때 Confirm 창을 띄워 묻는 기능을 구현해 봅니다. window.onunload나 app.close 이벤트들은 대부분 어플리케이션이 이미 종료되기로 결정된 후의 이벤트이기 때문에 window.onbeforeunload 이벤트에서 이 작업을 진행해 보기로 합니다.

window.onbeforeunload = (event) => {
    if(isModified()) {
        if(confirm("Are you sure you want to leave? All data will be lost!") == false) {
            event.returnValue = false;
            event.preventDefault();
            return false;
        }
    }
};
분명 문제가 없는 코드인데 잘 동작하는데 간혹 Cancel 버튼을 눌러도 그냥 어플리케이션이 종료되어버리는 경우가 발생합니다. 특히 Confirm 창을 살짝 이동시키고 Cancel을 클릭했을 때 자주 발생하는 것 같습니다. 구글에 검색해보니 모질라 문서에는 HTML5 spec에서 onbeforeunload 이벤트의 alert(), confirm(), prompt() 는 그냥 넘어갈 수도 있다는데, electron에서는 confirm 창은 항상 잘 떠서 이 문제가 아닌것 같고, 스택오버플로우에 이 문제에 대한 많은 답변이 있었지만 제대로 동작하는 답변이 한 개도 없었습니다.

Electron으로 만든 대표작인 Atom과 VSCode는 잘 되나? 궁금해서 문서 수정 후 저장없이 종료해보니 아무것도 묻지도 않고 쿨하게 그냥 종료해버립디다? 당황해서 다시 실행해보니 마지막 수정된 내용 대로 또 제대로 열립니다?? 엥?? 그럼 파일에 그냥 저장시켜 버리나? 하고 다른 편집기로 문서를 열어보니 또 저장된건 아닙니다. 아마 별도 공간에 수정된 파일을 백업해 놓는 것 같습니다.

아하... Atom과 VSCode도 결국은 onbeforeunload 문제를 해결하지 못하고 이런식으로 해결한 것 같았습니다.
Atom과 VScode도 못했으니 저도 쿨하게 포기하고 걍 놔두도록 합니다.

-- 2017.06.23 추가
삽질의 삽질을 거듭한 결과 버그를 해결 방법을 찾았습니다. 일단 window.onbeforeunload 에서 alert이나 confirm을 호출 할 경우 예상치 못한 동작을 할 가능성이 높습니다. 예를 들면 alert과 confirm, prompt 는 원래 웹브라우저에서는 프로세스를 블락시키는데 electron에서는 UI스레드만 블락되고 메인스레드는 그냥 진행되는 것 같습니다. 따라서 electron의 native dialog를 쓰면 프로세스가 블락(callback이 없을 경우)된다고 https://electron.atom.io/docs/api/dialog/ 설명에 나와있지만 이게 또 beforeunload 이벤트에선 예외인 듯 합니다. 결국 onbeforeunload가 호출되면 일단 무조건 event.preventDefault() 를 실행하고 dialog를 띄워서 callback 받았을 때 flag값을 비교하여 종료시키는 방식으로 해결했습니다...  
버그도 버그지만 electron의 MainProcess와 RendererProcess 방식을 제대로 이해하지 않은 저의 무지함도 한 몫 한거였네요..ㅋ

패키징하기

대충 기능을 마무리 하고 패키징 작업을 시작합니다. electron-builder와 electron-packager 두 종류가 있는데 왠지 electron-packager 설명이 더 끌립니다.
https://github.com/electron-userland/electron-packager 에 나온 설명대로 설치 한 후
electron-packager . --overwrite --asar --platform=win32 --arch=x64 --out=dist 

위처럼 실행하니 electron 을 못찾겠다는 에러가 뜹니다. 맨 위에서 global로만 설치했어서 못찾는겁니다. 현재 프로젝트에도 설치해줍니다.

npm install electron --save-dev

다시 electron-packager를 실행하면 dist 폴더에 windows x64 어플리케이션으로 잘 만들어집니다. 


위에서 --asar 옵션은 외부에서 리소스를 까볼 수 없게 asar라는 포멧으로 압축하는 것을 뜻합니다. 


windows용 어플의 경우 exe파일 속성의 아이콘이나 제작자, 회사명 등을 기록하기 위해서 --icon이나 --version-string 등의 파라메터를 추가로 입력해야 합니다. 그냥 아래 처럼 packager.json의 scripts로 만들어 둬서 npm build을 통해 실행하는게 편합니다.

{
  "name": "ckeditor_offline",
  "productName": "ckeditor_offline",
  "version": "0.1.1",
  "description": "CKEditor Offline Application",
  "author": "https://github.com/kuimoani",
  "main": "main.js",
  "scripts": {
    "start": "electron .",
    "build": "electron-packager . --overwrite --asar --platform=win32 --arch=x64 --icon=./icons/app.ico --prune --out=dist --version-string.CompanyName=kuimoani --version-string.FileDescription=CKEditor --version-string.ProductName=\"CKEditor Offline App\""
  },
  "dependencies": {
    "jquery": "^3.2.1"
  },
  "devDependencies": {
    "electron": "^1.6.10",
    "electron-packager": "^8.7.0"
  }
}
패키징이 잘 됐지만 한 가지 문제가 더 있습니다. 용량이 너~~무 큽니다. 이 단순한 HTML 편집기의 용량이 무려 135MB입니다. 제가 추가한 jquery, ckeditor, bootstrap을 모두 합쳐도 7MB 정도의 용량밖에 안되니 nodejs와 electron이 차지하는 용량이 120MB가 넘는 셈 입니다. 다만 ZIP으로 압축했을 때 51MB로 줄어드는 것으로 봐서 이 문제를 개선한 버전업을 기대해도 좋을 것 같습니다.

마치며

몇 가지 문제가 있긴 했지만 웹에 익숙한 개발자가 멀티플랫폼 어플리케이션을 만드는데 이만큼 쉬운 플랫폼은 없는 것 같습니다. electron을 처음으로 접하고 시행착오를 겪으며 이 HTML 에디터를 완성하는데 하루 정도 밖에 안걸렸습니다. (블로그에 내용정리하는게 더 오래걸림...ㅋ)


몇몇 버그와 너무 많은 용량, 너무 느린 성능 문제가 여전히 존재하긴 하지만 윈도우, 맥, 리눅스용 어플리케이션을 거의 버전 파편화 없이 개발할 수 있다는 점과 크롬개발도구를 활용하여 런타임중에 화면과 코드를 모두 디버깅할 수 있다는 점은 참 좋았던 것 같습니다.

Hdoc Download

깃허브 링크: https://github.com/kuimoani/Hdoc

릴리즈 다운로드: https://github.com/kuimoani/Hdoc/releases


저작자 표시 동일 조건 변경 허락
신고
Posted by 귀뫄뉘

댓글을 달아 주세요


티스토리 툴바