Electron 강좌
Electron 강좌 관련 기록.
Basic of Electron (Udemy 강의)
- https://samsungu.udemy.com/ 으로 드가면 들을 수 있음.
- https://samsungu.udemy.com/course/electron-react-tutorial/learn/lecture/6986540?start=0#content
Basic of Electron
- 플랫폼. 데스크톱 앱을 만들기 위함.
- 웹 앱은 최근들어 굉장하게 복잡해졌다. Electron은 이러한 특성을 데스크톱 앱에서 사용하기 위해 등장한 플랫폼이라고 보면 됨.
- 기본적으로 생각해야할 부분은 웹 브라우저는 유저의 하드디스크에 접근이 불가능하다는 것. 이러한 제약을 풀어주는 것이 Electron 이라는 플랫폼이라고 생각하면 된다.
- 사용자의 컴퓨터 리소스에 접근 가능하게 된다는 점이 핵심!!
- Electron === Google Chrome (Mostly..)
- Task Manager를 보면 Google Chrome Helper라는 놈이 여러개가 같이 존재함. 이것을 이해하면 Electron을 이해하는 데에 도움이 된다.
- 왜 다른 프로세스가 같이 도는가?
- 같이 죽지 않게 하기 위해. 랜더링 이슈를 막기 위해. Isolate 시키기 위해.
- RendererProcess가 핵심임. 이 프로세스가 웹페이지를 그린다.
- IPC(Inter Process Communication)을 통해 MainWindow, RendererProcess들이 통신한다.
- 웹브라우저와 다른 점은, 웹브라우저의 주소표시줄과 같은 완전 브라우저 자체의 내용까지도 접근이 가능하다는 점.
- Electron의 역사(?)
- GitHub -> Electron -> Atom (지금은 VS Code가 먹었지만..)
- GitHub는 처음에 Atom을 위해 Electron을 만들었고(Atom은 JS 유저가 많아 JS로 만들었다 함), 이것이 쓸만하다고 판단해서 Open Source로 만들었음
- 이것을 Slack, Discord, VS Code 등에서 사용하기 시작했다.
Handling Electron Project
- Electron (Run at terminal, Overall Chrome Process로 생각) -> Create MainWindow(BrowserWindow) -> index.html을 로딩.
- BrowserWindow를 생성하는 로직 또한 js로 작성한다는 점! (타 언어 사용 0%)
- nodemon을 사용하면 지속적인 F5 키를 눌러야 하는 것을 방지할 수 있음. -> 자동 시작을 해주는 서버 side에서는 이미 자주 쓰이고 있는 녀석임
- 아래 명령어는, src/js/index.js 디렉토리에서 코드변화가 감지하면 재시작을 하도록 설정.
"start": "npm-run-all --parallel watch:webpack watch:nodemon",
"watch:webpack": "webpack --config=webpack.config.js --mode=development --watch",
"watch:nodemon": "nodemon --exec \"electron .\" --watch \"./src/js/setup.js\""
- Step by Step Guide
- npm init
- package.json 생성
- npm install —save electron
- 2 파일 생성 필요. init을 위한 js 과 보여줄 index.html
- init을 위한 js는 터미널에서 실행된다. node를 통해.. 여기서는 require만 사용 가능
- const electron = require(‘electron’);
- import는 node에서 기본적으로 지원되진 않음.
app은 overall process 를 의미함.
const { app } = require('electron');- app은
event를 방출하며, 이것은 app.on 으로 청취 가능함- Event Driven Programming
app만 실행해서는 사실 아무것도 진행되지 않음!- 이후 BrowserWindow를 만들어야 함, 그래야 사용자에게 브라우저가 보이게 된다.
app은 처음 로딩이 끝나면ready이벤트를 가져온다. 그 후 mainWindow를 생성하는 것이 일반적인 Electron App의 패턴.app에 전체 Main Process의 Life Cycle이 엮여 있다고 보면 됨.
- BrowserWindow
new BrowserWindow()만 해도 바로 뭔가 나온다.- 개발자 도구도 바로 튀어나오게 됨 원한다면.
- 그러나 주소 표시줄 같은 것은 기본적으로 없다.
- 위에서 본 app과는 다른 녀석임. 완전히 다른 Process 라고 생각하면 됨
- 처음 만들기만 하면 html document가 load되지 않았으므로 빈 화면만 나오게 된다.
- 불러오기 위해서는
new BrowserWindow().loadURL('https://google.com')와 같이 하면 됨 - 물론 local file도 불러오기 가능하며 대부분의 ELectron App은 로컬 앱을 만드는 것이기 때문에 로컬 파일을 불러올 것임.
- 불러오기 위해서는
- 특수한 Node.js 함수를 실행하기 전에는 일반 웹 개발 하는 것과 동일하게 개발이 진행되게 된다. HTML / JS / CSS를 얼마나 잘 다루느냐에 따라 앱 개발 속도가 달라지게 된다.
- 차이점은 Local HDD를 접근가능하느냐 마느냐 정도로 생각해도 됨
- ffmpeg 같이 node.js를 통해 interact 하기 쉬운 cli process와 소통하기도 좋다.
- BrowserWindow 부분을 Web App Side라고 할 수 있는데, 이 부분은
Keep as generic as posslbie한게 좋다. 그래야 나중에 재사용성에 유리함.
- App <-> BrowserWindow 소통 방법?
- IPC 시스템을 사용함
- IPC: Inter Process Communication
const { ipcMain } = require('electron')- Main 에서 쓰이는 IPC object.
const { ipcRenderer } = require('electron')- 랜더러 프로세스에서 사용하는 IPC
ipcRenderer.send('eventName', 'Data')- 형태만 딱 봐도 사용하기 쉽지~
- 이건 랜더러 프로세스에서 메인으로 메시지 보내기 위해서 쓰는 것
- 메인에서 받기 위해서는
ipcMain.on을 사용
mainWindow.webContents.send- 랜더러 프로세스로 보낼 때 쓰는 것. BrowserWindow 객체를 참조하여 보내게 됨
- 받을 때는
ipcRenderer.on을 사용
- IPC 시스템을 사용함
- 예제에서는 ffmpeg 관련된 동작은 BrowserWindow Process 에서 처리하지 않고, App Process에서 처리하는 식으로 구현했음. 이게 좀 더 바람직해 보이기도 함.
Status Tray Application
Tray와BrowserWindow는 당연하게도 다르다.Tray Icon을 만드는 방법?new Tray(iconPath)tray.on('click', () => { mainWindow.show(); });자주 쓰이는 패턴
Tray근처에 창을 생성하는 방법? (특히 OS, 사용자마다 위치가 다를 것..)click이벤트가 올 때,bounds객체가 전달된다. 이 객체에 x, y 좌표가 제공됨. 이것을 참고하여 window 의 위치를 조절하면 된다.mainWindow에setBounds를 설정하면 지정한 영역에 윈도우를 잘 생성할 수 있다.
ETC (다른 강의 내용 포함)
- app 의 webContent에
new-window이벤트에preventDefault를 걸어두면 링크에서 새 창이 뜨는 것을 막을 수 있음. - session은 모든 browserWindow와 공유 됨.
mainWindow.webContents.sessionconst {session} = require('electron')도 같은 값 참조.session.defaultSession
- custom session도 만들 수 있긴 하다.
cookie도session의 하위 object 임.- download 도 control 가능하다. (창 안뜨고 자동 다운 가능)
globalShortcut: 화면이 떠 있지 않더라도 전체적으로 등록되는 Shortcut- 심지어 앱이 켜져있지 않더라도 실행됨! 그러나 충돌나는 것은 알아서 회피해야 할 것..
const {screen} = require('electron')을 통해서 스크린에 관련된 모든 데이터를 가져올 수 있음- getAllDisplay(): 전체 연결된 display에 대한 정보들을 가져올 수 있다.
- touchSupport 등등 포함..
- getAllDisplay(): 전체 연결된 display에 대한 정보들을 가져올 수 있다.
- Main Process가 BrowserWindow를 소유하며, Browser Window는 Renderer Process 그 자체다.
- Main Process는 여러개의 BrowserWindow를 소유한다.
- BrowserWindow는 webFrame > webContents 를 소유한다.
- ex) Zoom Factor
electron.desktopCapturer: 데스크탑의 화면을 저장 가능함process.version: 각 버전을 가지고 있음..- ex) chrome, napi, electron, v8, opensssl 등등..
process.hang(): Renderer를 Hang을 걸 수 있음.process.crash(): crash 될 때를 시뮬레이팅 할 수 있음.- 이 때 reload 걸면 복구될 수 있음. 복구 되는게 낫나?..
- 몇몇 electron API들은 Shared API로, renderer와 main 모두에게서 쓰일 수 있음. (ex:
shell등..)- electron.remote 안써도 된다는 뜻
Distribution
- Electron-Builder 가 진리.
- cli 옵션도 지원한다. 어떤 platform으로 distribute 할지는 이걸로 결정
- 결과물은 dist 디렉토리에 제공됨.
- 제대로 하려면 code-signing도 해야 함. (아마 mac은 더 강제되는듯?)
- Electron-Builder에 이미 AutoUpdater가 있다.
- GitHub 를 통해 배포하려면, Personal access token을 발급받아야 한다.
- 이를 등록하면, 빌드 후 자동으로 GitHub release에 올려버릴 수 있음. (이미 만들어진 tag를 참조해서 올리는 듯?)
- (참고) setx 커맨드를 윈도우에서 사용하면 환경변수를 잠시 설정할 수 있다.
- 자동 업데이트는 electron-updater와 함께~
이전 블로그에서 옮긴 글입니다. 원래 주소