생소해서 어려운. 하지만 의외로 쉬운.

 

너 거기있고, 나 여기있고.

 

 


링크

데스크탑 앱 만들기 #1 - Vue CLI + Electron

데스크탑 앱 만들기 #2 - ExcelJS, SheetJS, js-xlsx, js-xlsx-style

데스크탑 앱 만들기 #3 - ipcMain, ipcRenderer

④ 데스크탑 앱 만들기 #4 - ExcelJS, ipcRenderer, ipcMain, removeListener

 

 위 포스팅에서 Vue CLI를 이용해서 frontend(renderer)를 만들고, electron-builder를 이용해서 backend(Main)를 만들었습니다. 그리고 excel 파일을 읽는 라이브러리를 ExcelJS를 이용해서 로딩에 성공하였으니 이제 이 객체를 frontend로 보내줘야 데이터를 가지고 이것저것 만지작 거릴 수 있겠죠? 그 이후에 만지작 거린 객체를 다시 백엔드로 보내서 엑셀 파일에 저장해주면 제 프로젝트가 성공하게 됩니다.

 

 아, 그 전에 애초에 frontend에서 파일을 읽고 바로 수정하면 되지 않냐 생각도 했었는데 시스템 안에 있는 파일을 직접 읽고 쓰기 위해서는 일렉트론 같은 시스템 프로그램이 필요하더라구요. 시스템 프로그램이 없으면 프로젝트 로컬 폴더 안에 있는 내용만 접근 가능하고, 폴더 밖에 있는 파일들은 접근이 안되니 업로드하는 방식으로 밖에 없는 것 같았습니다. 애초에 기획이 자동화니까 일렉트론을 쓰기로 결정했었죠.


 그럼 이제 본격적으로 fontend와 backend의 데이터 교환 방법을 알아보겠습니다.

 

 일렉트론 공식 문서에 뭐라고 설명되어있는지 부터 확인하고 갈게요!

 

★ ipcRenderer - renderer 프로세스에서 main 프로세스로 비동기적인 통신을 합니다.

★ ipcMain - main 프로세스에서 renderer 프로세스들로 비동기적인 통신을 합니다.

 

 내용만 봐서는 뭔지 정확히 감이 오질 않습니다. 혹시 Javascript 좀 해보신 분들은 좀 익숙하실지도 모르겠습니다. 웹페이지에서 event emit, listen과 많이 닮아 있다고 생각이 들었거든요.

 

 그럼 공식 문서에 나와있는 테스트 코드를 확인해봅니다.

 

 다음 코드는 frontend에 있는 아무 파일에 넣으면 되는데 저는 App.vue 파일에 넣어서 테스트를 해보겠습니다.

// renderer 프로세스(웹 페이지)안에서
const { ipcRenderer } = require('electron')
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // "pong"이 출력됩니다.

ipcRenderer.on('asynchronous-reply', (event, arg) => {
  console.log(arg) // "pong"이 출력됩니다.
})
ipcRenderer.send('asynchronous-message', 'ping')

 

 ipcRenderer 테스트 코드에서 사용된 메소드는 on, send, sendSync로 3가지입니다.

- on: backend에서 frontend로 통신을 시도하면 받아 주는 메소드

- send: frontend에서 backend로 통신을 보내는 메소드

- sendSync: send메소드는 비동기적으로 보내지고, 이 메소드는 동기적으로 작동한다(동기, 비동기는 여기서 설명하기엔 내용이 복잡해지므로 패스!).

 

 아래 코드가 backend 파일인 background.js에 들어갑니다.

// main 프로세스안에서
const { ipcMain } = require('electron')
ipcMain.on('asynchronous-message', (event, arg) => {
  console.log(arg) // "ping" 출력
  event.reply('asynchronous-reply', 'pong')
})

ipcMain.on('synchronous-message', (event, arg) => {
  console.log(arg) // "ping" 출력
  event.returnValue = 'pong'
})

 ipcMain 테스트 코드에서 사용된 메소드는 on, reply로 2가지입니다.

- on: frontend에서 background.js로 통신을 요청하면 받는 주는 메소드

- reply: on이 성공하면 frontend로 다시 통신을 넣어주는 메소드

 

 위의 테스트 코드를 실행했을 때의 결과는 다음과 같습니다.

 

▶︎ frontend(renderer) side

▶︎ backend(main) side

 

 frontend에서 pong 두 번, backend에서 ping 두번이 로그에 출력이 되었네요. 보내고 받고를 두번 했다는 뜻인데 코드를 한번 살펴볼게요.

 빨간색은 비동기(asychronous) 통신을 나타내고, 파란색은 동기(synchronous) 통신을 나타냅니다. 두 가지의 통신을 테스트하는 코드였네요. 그래서 frontend와 backend 콘솔에 pong이 2개, ping이 2개가 출력된 것입니다.

 

 자세히 좀 볼까요?

 

▶︎ 비동기 통신(분홍색, asychronous)

① frontend에서 ipcRenderer.send 메소드를 'asynchronous-message' 채널을 통해 'ping'이라는 데이터를 backend로 보냅니다.

② backend에서 ipcMain.on 메소드에서 정의한 'asynchronous-message' 채널을 통해서 인자를 받고 콘솔에 출력하네요.

그리고 바로 ipcMain.reply 메소드를 'asychronous-reply' 채널을 통해 'pong'이라는 데이터를 frontend로 보냅니다.

④ 마지막으로 frontend에서 ipcRenderer.on 메소드를 통해 정의된 'asychronous-reply' 채널을 통해 받아진 'pong'이라는 데이터는 콘솔에 출력되는 것으로 끝이 납니다.

 

▶︎ 동기 통신(파란색, sychronous)

① frontend에서 ipcRenderer.sendSync 메소드를 'synchronous-message' 채널을 통해 'ping'이라는 데이터를 backend로 보냅니다.

② backend에서 ipcMain.on 메소드에서 정의한 'synchronous-message' 채널을 통해서 인자를 받고 콘솔에 출력하네요.

③ 그리고 event의 returnValue를 'pong'으로 입력하면서 자동적으로 frontend로 데이터가 리턴됩니다.

④ 마지막으로 frontend로 ipcRenderer.sendSync의 리턴 값이 'pong'으로 전달되었고 바로 콘솔에 출력됩니다.

 

 

 어떤가요? 일렉트론의 frontend와 backend이 통신을 어떻게 하는지 같이 살펴보았는데 이해가 되셨으면 좋겠네요. 저는 테스트 코드를 해보면서 생각보다 쉽다는 생각을 했습니다. ipc라는 용어 자체가 헷갈릴 뿐이죠.

 

 그럼 다음 포스팅에서는 제 프로젝트에서 ExcelJS와 ipcMain, ipcRenderer를 이용해서 어떻게 구현하였는지, 그리고 Listner가 중첩돼서 중복적으로 통신 이벤트가 발생하는 현상을 수정하는 방법들을 적어보도록 하겠습니다.

 

 

※ 동기와 비동기의 차이점은 생활코딩님께서 영상으로 너무 잘 설명해주셔서 링크를 남깁니다. 영상은 개념 설명이고 아래 더보기에 강좌 링크는 남겨놓았으니 동기, 비동기가 궁금하신 분은 참고해주세요!

 

생활코딩 - 동기와 비동기의 개념

 


다음 : 데스크탑 앱 만들기 #4 - ExcelJS, ipcRenderer, ipcMain, removeListener

더보기 : 생활코딩 - nodejs에서의 동기, 비동기, 콜백

프로젝트가 끝나갈 무렵, 코딩은 참 즐겁다는 생각이 들었다.

 

+ Recent posts