React + Electron, Next.js + Electron

React + Electron, Next.js + Electron

 처음에는 React에 Electron을 붙이는 것으로 시작했다.

 요즘은 Vite를 대체적으로 사용하고, Vite는 굉장히 세팅이 쉬운 편이다. React에 Electron을 결합하는 것은 어려울 게 없다.

 다만 본격적인 어려움은 Next.js에 Electron을 붙이는 것인데, Next.js는 기본적으로 SSR을 전제로 하는 프론트 프레임워크이다보니 Electron과 결합을 위해서는 넘어야 하는 장벽이 다소 존재한다.

 본 포스팅은 스스로 학습한 것을 복습하는 겸, 혹여 필자의 보일러플레이트를 이용하지 않고 직접 구현해보고자 하는 이들을 위해 작성하는 글이다.

 (인터페이스 선언부)

 기본적으로 Vite에서는 위의 자료처럼 vite-env.d.ts에 electron에 관한 인터페이스를 명시해두면 오류 메시지없이 코드 작성을 용이하게 진행할 수 있다.

 (next.js에서 electron 인터페이스 선언)

 다만 Next.js에서는 그 형태가 사뭇 다를 수 있다. next-env.d.ts의 경우 타입스크립트로 컴파일할 때마다 생성되는 형태이다보니 여기에 electron 인터페이스를 선언해서는 빌드할 때마다 초기화가 되는 현상이 있다. 물론 해결법은 간단하다. 아래처럼 다른 파일에 인터페이스를 선언하면 된다. (여기서는 lib/utils.ts에 선언했다.)

 물론 프로젝트가 production 단위로 거대해진다면 통상적으로 타입스크립트에서 사용하는 형태인 types/ 디렉토리 부분에 별개로 선언해도 무방하다.

 (next.js는 기본적으로 commonJS 타입)

 계속 서술하자면, next.js에서 page router와 app router에서 electron을 사용하기 위해서 공통적으로 인지해야할 사항이라 생각하는데, next.js는 node.js의 기본 모듈형태인 commonJS를 따르는 듯하다. 그래서 package.json에 "type": "module"을 선언할 시에는 오류가 발생하는 것은 아마 다들 알 것이라 생각한다.

 (electron에서는 ESM 모듈을 임포트해야한다. 이는 둘의 모듈 시스템이 다르기 때문이다.)

 처음 electron 진입점에서 모듈을 임포트할 때 commonJS 모듈 시스템으로 임포트하면 크게 어려움이 없을 것이라 생각했지만, 일부 모듈들은 이러한 형태로 임포트할 때 에러를 일으키는 문제점이 있다. 해결법은 간단하다. 아래처럼 electron진입점을 .mjs 형태로 생성하고 ESM 모듈을 임포트하면 된다.

 page router와 app router에서는 일렉트론을 활용한 로직들이 상당부분 CSR로 진행해야하는 경우가 많아서 useEffect 훅을 사용해야하는 경우가 빈번함을 인지해야한다.

 필자의 보일러플레이트에서는 타이틀바를 렌더링 할 때 브라우저 환경인지 아닌지 검사하기 위해서 useEffect 훅을 사용했다. 추가적으로 app router의 경우 이때 상단에 'use client'를 선언해야 server side 부분에서 에러를 일으키지 않는다.

 첨언하자면 타이틀바의 경우 각 라우터 레이아웃 형식에 맞추어 적용하였다. page router와 app router는 레이아웃 로직 부분이 사뭇 다르다.