Eletron으로 Desktop App을 만들고자한다.
평소에 이리저리 분주하게 일하는 편이지만 요즘 들어 개발 문서를 작성하다가도 검색하고, 참고해야될 내용을 찾을때도 Chrome 브라우저를 열어 검색해서 URL 붙여넣기, 아키텍쳐 예시 이미지 검색해서 붙여넣기 등..
특히 요즘 개발자들은 md 파일로 문서를 작성하는 트랜드라서 여러 기능이 들어간 markdown edit workdock을 만들어 보고자 한다.
Eletron Forge는 공식적으로 Vite + TypeScript 템플릿을 제공하고 있기 때문에 아래와 같이 프로젝트 셋팅을 진행합니다.
> pnpm create electron-app@latest . --template=vite-typescript
PS D:\dev\git\dock> pnpm create electron-app@latest . --template=vite-typescript
Downloading typescript@5.4.5: 5.82 MB/5.82 MB, done
Packages are hard linked from the content-addressable store to the virtual store.
Content-addressable store is at: C:\Users\user\AppData\Local\pnpm\store\v11
Virtual store is at: AppData/Local/pnpm/store/v11/links
[ERR_PNPM_EXOTIC_SUBDEP] Exotic dependency "@electron/node-gyp" (resolved via git-repository) is not allowed in subdependencies when blockExoticSubdeps is enabled
This error happened while installing the dependencies of create-electron-app@7.11.2
at @electron-forge/cli@7.11.2
at @electron-forge/core-utils@7.11.2
at @electron/rebuild@3.7.2
[WARN] GET https://registry.npmjs.org/minimist error (UND_ERR_DESTROYED). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/signal-exit error (UND_ERR_DESTROYED). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/globalthis error (UND_ERR_DESTROYED). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/sprintf-js error (UND_ERR_DESTROYED). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/@types%2Fmute-stream error (UND_ERR_DESTROYED). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/@types%2Fwrap-ansi error (UND_ERR_DESTROYED). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/type-fest error (UND_ERR_DESTROYED). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/eslint-scope error (UND_ERR_DESTROYED). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/color-name error (UND_ERR_DESTROYED). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/minimatch error (UND_ERR_DESTROYED). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/bluebird error (unknown). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/glob error (unknown). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/@types%2Fnode error (UND_ERR_DESTROYED). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/es-module-lexer error (unknown). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/enhanced-resolve error (unknown). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/@webassemblyjs%2Fwasm-parser error (unknown). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/acorn error (unknown). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/@webassemblyjs%2Fwasm-edit error (unknown). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/@webassemblyjs%2Fast error (unknown). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/@xmldom%2Fxmldom error (UND_ERR_DESTROYED). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/get-stream error (UND_ERR_DESTROYED). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/@types%2Fyauzl error (UND_ERR_DESTROYED). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/isbinaryfile error (UND_ERR_DESTROYED). Will retry in 10 seconds. 2 retries left.
[WARN] GET https://registry.npmjs.org/browserslist error (unknown). Will retry in 10 seconds. 2 retries left.
.../mrwr9xx4-bsw | Progress: resolved 148, reused 0, downloaded 149, added 0
Exotic dependency "@electron/node-gyp" (resolved via git-repository) is not allowed in subdependencies when blockExoticSubdeps is enabled
최신 pnpm은 기본적으로 blockExoticSubdeps: true라서, 하위 패키지가 Git 저장소 같은 비표준 경로의 의존성을 가져오면 차단한다. 그런데 Electron Forge 내부의 @electron/rebuild가 @electron/node-gyp를 Git 의존성으로 사용해서 막힌것이다.
프로젝트 생성 단계만 npm으로 진행하자.
현재 폴더에 생성 중 남은 파일이 있는지 먼저 확인한다.
절대로 누구처럼 프로젝트 디렉토리에
git init부터 하시면 안됩니다.
프로젝트 root에.git디렉토리가 있으면 삭제한 뒤에 프로젝트 설정이 끝나면 다시 설정하시는걸 권장드립니다.
Get-ChildItem -Force
중간 생성물이 없다면 그대로 실행한다.
npm init electron-app@latest . -- --template=vite-typescript
또는
npx create-electron-app@latest . --template=vite-typescript
npm start
Electron 창이 뜨면 Electron 프로젝트 셋팅은 성공
아닙니다. 프로젝트 생성만 npm으로 하고, 생성된 뒤 pnpm으로 전환할 수 있습니다.
Remove-Item package-lock.json
pnpm install
pnpm start
다만 같은 오류가 다시 발생할 수 있어서, 당장은 이 프로젝트는 npm으로 통일하는 게 가장 편한 길입니다.
Electron Forge와 네이티브 모듈 쪽은 npm 기준 자료와 검증 사례가 많아서, MVP 단계에서는 굳이 패키지 매니저 문제까지 같이 해결할 필요까진 없을 것 같습니다.
전역 설정을 끄는 방법도 있습니다.
pnpm config set block-exotic-subdeps false --global
확인
pnpm config get block-exotic-subdeps
그다음 다시
pnpm create electron-app@latest . --template=vite-typescript
하지만 이 설정은 pnpm이 제공하는 공급망 보안 기능을 전역으로 비활성화 합니다. 그래서 개인적으로는 추천하는 방법은 아닙니다. blockExoticSubdeps는 하위 의존성이 Git URL이나 직접 tarball URL을 사용하는 것을 막기 위한 설정입니다.
현재 Windows 환경에서 개발을 진행하기 때문에 Powershell 기준으로 작성하고 있습니다.
Linux 또는 macOS 환경에서 개발을 진행하실 분들은 해당 내용을 AI Agent에게 질의하여 진행하시면 될 것 같습니다.
cd ~/{workspace_path}/
Get-ChildItem -Force
npx create-electron-app@latest . --template=vite-typescript
npm start
정리하면 pnpm 최신 보안 정책과 Electron Forge 의존성 구조가 충돌한 상황입니다.