프로그래밍

Electron + Vite + React: 웹 프론트엔드로 로컬 데스크톱 앱을 만드는 가장 현실적인 조합

푸른강아지 2026. 7. 8. 12:56
반응형

Electron + Vite + React: 웹 프론트엔드로 로컬 데스크톱 앱을 만드는 가장 현실적인 조합

핵심 요약: React는 웹사이트 전용 기술이 아니라 UI를 컴포넌트로 만드는 방식입니다. Electron은 이 React UI를 Chromium 기반 데스크톱 창 안에서 실행하고, Vite는 개발 서버와 빌드를 빠르게 만들어줍니다. Rowboat 같은 로컬 AI 앱, Slack, VS Code, Discord류의 앱은 이 패턴을 이해하면 구조가 훨씬 선명하게 보입니다. 다만 Electron은 가볍기만 한 선택지는 아니므로, 파일 시스템·로컬 프로세스·Node.js 생태계가 필요한 앱에 특히 잘 맞습니다.

📌 React가 웹을 넘어 데스크톱으로 들어온 이유

처음 React를 배울 때는 대부분 브라우저 화면을 만드는 도구로 접합니다. 버튼, 카드, 리스트, 모달 같은 UI를 컴포넌트로 쪼개고, 상태가 바뀌면 화면이 자동으로 다시 그려지는 방식입니다. 그래서 자연스럽게 “React는 웹 서비스 만들 때 쓰는 것”이라고 이해하기 쉽습니다. 하지만 React의 본질은 특정 서버 기술이 아니라 UI를 선언적으로 구성하는 라이브러리입니다.

데스크톱 앱에서 React가 쓰이는 방식은 생각보다 단순합니다. Electron이 앱 창을 만들고, 그 창 안에 Chromium 렌더러를 띄운 다음, 그 안에서 React 앱을 실행합니다. 사용자는 일반 앱처럼 실행하지만 개발자는 상당 부분을 웹 프론트엔드처럼 작성합니다. 여기에 Node.js 런타임과 Electron의 네이티브 API가 결합되면 파일 읽기, 로컬 DB 접근, 프로세스 실행, 메뉴바, 트레이 아이콘, 자동 업데이트 같은 데스크톱 기능까지 붙일 수 있습니다.

최근 Rowboat 같은 로컬 AI coworker 앱이 흥미로운 이유도 여기에 있습니다. README 기준으로 Rowboat는 로컬 우선 AI 앱이며, 작업 맥락을 지식 그래프로 만들고 로컬 Markdown vault에 기록합니다. UI는 웹앱처럼 보이지만, 실제 제품 경험은 데스크톱 앱에 가깝습니다. 이런 유형의 앱은 브라우저 탭 하나로 끝나지 않습니다. 파일 시스템, 로컬 노트, 외부 CLI, MCP 도구, 백그라운드 작업, 인증 파일 같은 로컬 자원과 깊게 연결되어야 하기 때문입니다.

제가 보기에는 이 지점이 Electron + Vite + React 조합의 핵심 가치입니다. “웹 기술로 앱을 포장한다”는 단순한 설명보다, 웹 UI 개발 경험과 로컬 실행 환경을 연결한다는 관점이 더 정확합니다. 특히 AI 도구처럼 채팅 UI, 그래프 UI, 문서 편집기, 터미널, 브라우저, 설정 화면이 한 앱 안에 섞이는 제품은 React 생태계의 이점을 크게 누릴 수 있습니다.

🏗️ 세 가지 역할: Electron은 껍데기, Vite는 엔진, React는 화면

이 조합을 이해하려면 세 도구의 역할을 분리해서 보는 것이 좋습니다. Electron은 데스크톱 앱 런타임입니다. 앱 창을 만들고, 운영체제와 통신하고, Chromium 기반 렌더러를 실행합니다. React는 그 렌더러 안에서 실제 사용자 화면을 구성합니다. Vite는 개발 중 빠른 HMR과 프로덕션 번들링을 담당합니다.

구성요소 담당 역할 개발자가 체감하는 장점
Electron Chromium + Node.js 기반 데스크톱 앱 런타임 Windows, macOS, Linux 앱을 한 코드베이스로 배포
Vite 개발 서버, HMR, 번들링, 플러그인 생태계 수정 후 화면 반영이 빠르고 설정 부담이 작음
React 컴포넌트 기반 UI와 상태 관리 웹 프론트엔드 지식으로 복잡한 앱 UI 구현

공식 문서 기준으로 Vite는 빠른 개발 서버와 HMR, 프로덕션 번들링을 제공하는 도구입니다. electron-vite는 여기에 Electron의 특수한 구조를 얹습니다. Electron 앱은 보통 main process, preload script, renderer process로 나뉘는데, electron-vite는 이 세 영역을 Vite 설정 안에서 다루도록 도와줍니다. 일반 Vite React 앱을 억지로 Electron에 끼워 넣는 것보다 구조가 깔끔합니다.

중요한 해석 포인트는 “React 앱을 그대로 데스크톱 앱으로 바꾼다”가 아니라는 점입니다. React는 화면을 담당하지만, 보안상 로컬 파일이나 OS 기능을 직접 만지면 안 됩니다. 로컬 권한이 필요한 작업은 main process가 처리하고, renderer는 preload를 통해 허용된 API만 호출해야 합니다. 이 경계를 지키는지가 장난감 앱과 실제 배포 앱을 가르는 차이입니다.

🔧 기본 구조는 이렇게 나뉩니다

Electron 앱을 처음 보면 폴더가 웹앱보다 복잡해 보여 당황할 수 있습니다. 하지만 역할은 명확합니다. main은 앱의 관리자, preload는 통역사, renderer는 사용자 화면입니다. 이 구조를 처음부터 머릿속에 넣어두면 보안 설정이나 빌드 오류를 이해하기 훨씬 쉬워집니다.

src 또는 apps/ main/ 앱 창 생성, 메뉴, 트레이, 파일 시스템, 로컬 프로세스 제어 preload/ renderer에 노출할 안전한 API 정의 renderer/ React UI, 라우팅, 컴포넌트, 상태 관리

예를 들어 “사용자가 버튼을 누르면 로컬 Markdown 파일을 읽어 화면에 보여준다”는 기능을 만든다고 가정해보겠습니다. React 버튼이 직접 파일 시스템을 열면 위험합니다. 대신 React는 preload에 노출된 API를 호출하고, preload는 IPC를 통해 main process에 요청합니다. main process가 파일을 읽고 결과를 돌려주면 React가 화면에 렌더링합니다. 이렇게 우회하는 것처럼 보이는 구조가 사실 Electron 보안의 기본입니다.

Rowboat 같은 앱이 로컬 지식 그래프, Markdown vault, 외부 도구, 브라우저, 메일, 회의 노트 같은 기능을 담을 수 있는 이유도 이 분리 덕분입니다. 화면은 React로 빠르게 만들고, 로컬 실행 권한이 필요한 부분은 Electron 계층에서 처리합니다. 제품이 커질수록 이 분리는 더 중요해집니다. 처음에는 귀찮아 보여도 나중에 기능을 확장할 때 구조적 안전장치가 됩니다.

🚀 시작 방법: electron-vite 템플릿이 가장 편합니다

직접 Vite React 프로젝트를 만들고 Electron을 수동으로 붙일 수도 있습니다. 하지만 처음 시작한다면 electron-vite 템플릿을 쓰는 편이 낫습니다. electron-vite 문서에 따르면 공식적으로 main, preload, renderer 설정을 하나의 Electron 친화적 구성으로 다루고, renderer HMR뿐 아니라 main/preload 쪽 hot reloading까지 지원합니다. Electron의 이중 환경, 즉 Node.js와 브라우저 컨텍스트를 같이 다뤄야 하는 문제를 도구가 상당 부분 흡수해줍니다.

npm create @quick-start/electron@latest # 프롬프트에서 React + TypeScript 선택 # 이후 일반적으로: npm install npm run dev

여기서 주의할 점은 Node.js 버전입니다. Vite와 electron-vite 문서는 최근 버전 기준으로 Node.js 20.19+ 또는 22.12+ 같은 비교적 최신 런타임을 요구합니다. 오래된 Node.js LTS를 쓰고 있다면 템플릿 생성이나 빌드 단계에서 예상치 못한 오류가 날 수 있습니다. 데스크톱 앱 개발은 “프론트엔드 프로젝트”처럼 보이지만 실제로는 빌드 도구, 패키징 도구, OS별 서명, 네이티브 모듈까지 걸릴 수 있으므로 개발 환경 버전을 고정하는 습관이 중요합니다.

제 의견으로는 첫 프로젝트에서 너무 많은 것을 한 번에 붙이지 않는 편이 좋습니다. React Router, Tailwind, shadcn/ui, SQLite, 자동 업데이트, 트레이 아이콘, 파일 감시까지 한 번에 넣으면 어디서 문제가 났는지 추적하기 어렵습니다. 먼저 “창이 뜬다 → React 화면이 보인다 → preload API 하나가 동작한다 → 패키징된다”까지 확인한 뒤 기능을 추가하는 순서가 안정적입니다.

📋 Electron, Tauri, 순수 웹앱은 언제 다르게 선택해야 할까

Electron이 강력하다고 해서 모든 로컬 앱에 최선은 아닙니다. Tauri는 OS의 WebView와 Rust 백엔드를 사용해 더 작은 앱 크기와 낮은 메모리 사용량을 목표로 합니다. 반대로 Electron은 Chromium과 Node.js를 함께 제공하기 때문에 앱 크기와 메모리 측면에서 불리할 수 있지만, 웹 호환성과 Node.js 생태계 활용성은 매우 강합니다. 이 차이는 단순 취향 문제가 아니라 제품 요구사항의 문제입니다.

선택지 잘 맞는 경우 주의점
Electron 복잡한 웹 UI, Node.js 도구, 로컬 프로세스, 터미널, 플러그인 생태계가 필요한 앱 앱 크기와 메모리 사용량이 커질 수 있음
Tauri 가벼운 배포 파일, 보안 중심 설계, Rust 백엔드를 받아들일 수 있는 팀 Node.js 기반 패키지를 그대로 쓰기 어렵고 WebView 차이를 고려해야 함
순수 웹앱 브라우저 안에서 충분하고 로컬 권한이 거의 필요 없는 SaaS 파일 시스템, 백그라운드 작업, OS 통합에는 한계가 있음

AI 개발자 도구 관점에서는 Electron이 여전히 매력적입니다. Claude Code, Codex, Git, 터미널, 로컬 파일, 브라우저 세션, MCP 서버처럼 이미 Node.js와 CLI 생태계에 걸쳐 있는 기능이 많기 때문입니다. 반면 단순 메모 앱, 작은 유틸리티, 시스템 트레이 앱이라면 Tauri가 더 적합할 수 있습니다. “Electron은 무겁다”는 비판은 맞지만, “그래서 항상 나쁘다”는 결론은 성급합니다.

저라면 판단 기준을 이렇게 잡겠습니다. 사용자가 하루 종일 켜놓는 생산성 앱이고, UI가 복잡하며, 로컬 개발 도구와 자주 통신한다면 Electron을 검토합니다. 반대로 기능이 작고, 배포 크기와 배터리 사용량이 제품 경쟁력의 핵심이라면 Tauri를 먼저 봅니다. 중요한 것은 프레임워크의 유행이 아니라 앱이 실제로 어떤 로컬 권한과 생태계를 필요로 하는지입니다.

🖥️ Rowboat에서 보이는 패턴: 웹 UI가 로컬 AI 앱의 표준 인터페이스가 되고 있다

Rowboat 저장소를 보면 데스크톱 앱 구조가 더 구체적으로 보입니다. `apps/x/apps/main`, `apps/x/apps/preload`, `apps/x/apps/renderer`처럼 Electron 계층을 나눈 흔적이 있고, renderer 패키지에는 React, Vite, Radix UI, TipTap, Mermaid, xterm 같은 프론트엔드 라이브러리가 함께 들어갑니다. 즉, 단순한 웹페이지가 아니라 채팅, 문서 편집, 그래프, 터미널, 마크다운 렌더링 같은 복합 UI를 React 생태계로 구성하는 방식입니다.

이 구조가 흥미로운 이유는 로컬 AI 앱의 UI 요구사항이 일반 업무용 웹앱보다 더 복잡해지고 있기 때문입니다. 사용자는 채팅창만 원하는 것이 아닙니다. 에이전트 실행 로그, 파일 변경 diff, 지식 그래프, 노트 편집기, 브라우저 자동화 화면, 터미널 출력, 설정 패널을 한곳에서 보고 싶어 합니다. 이런 UI는 전통적인 네이티브 앱 프레임워크로도 만들 수 있지만, React 생태계에는 이미 필요한 부품이 많습니다.

다만 여기서 한 가지 냉정하게 봐야 할 점도 있습니다. React로 화면을 쉽게 만들 수 있다고 해서 제품이 쉽게 완성되는 것은 아닙니다. 데스크톱 앱은 배포가 끝이 아니라 시작입니다. 자동 업데이트, OS별 권한, 코드 서명, 로컬 데이터 마이그레이션, crash report, 보안 업데이트까지 챙겨야 합니다. Electron + Vite + React는 UI와 개발 경험을 빠르게 만들어주지만, 운영 난이도를 없애주지는 않습니다.

🧐 냉정한 평가: 입문은 쉽지만, 배포 앱은 구조 싸움입니다

Electron + Vite + React의 가장 큰 장점은 진입 장벽입니다. 웹 프론트엔드 경험이 있다면 데스크톱 앱의 첫 화면을 매우 빠르게 만들 수 있습니다. Vite 덕분에 개발 피드백 루프가 빠르고, React 생태계 덕분에 UI 컴포넌트 선택지도 넓습니다. Rowboat처럼 복잡한 화면을 가진 앱도, 기본 원리는 “React renderer + Electron shell”로 설명할 수 있습니다.

하지만 실제 제품으로 가면 핵심은 보안 경계입니다. renderer에서 Node.js 권한을 막고, context isolation을 켜고, preload를 통해 필요한 API만 노출하는 구조를 지켜야 합니다. 이것을 무시하면 웹앱의 XSS 문제가 곧 로컬 파일 접근 문제로 확대될 수 있습니다. 브라우저 안의 취약점이 사용자의 컴퓨터 권한과 만나는 순간, 위험의 크기가 달라집니다.

또 하나의 한계는 무게입니다. Electron은 앱마다 Chromium을 사실상 품고 가는 모델이기 때문에 작은 유틸리티에는 과할 수 있습니다. 반면 개발자 도구, AI coworker, IDE, 협업 앱처럼 UI가 복잡하고 웹 기술 재사용성이 큰 제품에서는 이 무게를 감수할 만한 이유가 생깁니다. 결국 Electron은 “가벼운 도구”가 아니라 복잡한 크로스플랫폼 제품을 빠르게 만들기 위한 타협에 가깝습니다.

🔮 개발자에게 주는 의미: 로컬 AI 앱 시대의 프론트엔드 스택

앞으로 AI 앱은 점점 “웹 서비스 하나”와 “로컬 앱 하나”의 경계가 흐려질 가능성이 큽니다. 모델 호출은 클라우드에서 하더라도, 작업 맥락은 로컬 파일과 앱에 흩어져 있습니다. 이메일, 캘린더, 문서, 코드 저장소, 터미널, 브라우저 세션을 다루려면 브라우저 탭만으로는 부족한 경우가 많습니다. 그래서 React를 아는 개발자가 Electron을 이해하면 만들 수 있는 제품 범위가 크게 넓어집니다.

  • 웹 프론트엔드 개발자에게: 기존 React 지식을 버리지 않고 데스크톱 앱으로 확장할 수 있습니다. 다만 IPC, preload, 보안 설정은 새로 익혀야 합니다.
  • AI 앱 개발자에게: 채팅 UI뿐 아니라 지식 그래프, 파일 탐색기, 터미널, 워크플로우 편집기까지 한 앱 안에 담을 수 있습니다.
  • 스타트업/개인 개발자에게: Windows, macOS, Linux를 각각 네이티브로 만들지 않아도 초기 제품을 빠르게 검증할 수 있습니다.
  • 운영 관점에서: 패키징, 자동 업데이트, 코드 서명, 보안 업데이트 계획을 초기부터 포함해야 합니다. 데모와 제품은 다릅니다.

정리하면 Electron + Vite + React는 “웹 개발자가 데스크톱 앱을 흉내 내는 방법”이 아닙니다. 오히려 복잡한 로컬 생산성 앱을 만드는 데 필요한 현실적인 산업 표준 중 하나입니다. 특히 Rowboat처럼 로컬 데이터와 AI 에이전트를 결합하는 앱에서는 이 조합이 꽤 자연스럽습니다. 무겁다는 단점은 있지만, 복잡한 UI와 로컬 실행 능력을 동시에 얻는 비용으로 보면 납득 가능한 선택입니다.

💡 한 줄 요약: Electron은 React UI를 로컬 앱으로 실행하게 해주는 데스크톱 런타임이고, Vite는 그 개발 경험을 빠르게 만드는 빌드 도구입니다. Rowboat 같은 로컬 AI 앱을 이해하려면 “React는 웹 전용”이라는 생각보다 “React는 여러 런타임에서 재사용 가능한 UI 계층”이라는 관점으로 보는 편이 훨씬 정확합니다.

반응형