아키텍처 개요
Elftia는 엄격한 프론트엔드/백엔드 분리 아키텍처를 기반으로 구축된 Electron + React 데스크톱 AI 채팅 애플리케이션입니다. 이 문서는 시스템의 전체 구조, 핵심 설계 원칙, 주요 기술 선택을 설명합니다.
멀티 프로세스 모델
Electron 애플리케이션은 세 개의 프로세스와 여러 Worker 스레드에서 실행됩니다.
graph TB
subgraph "Renderer Process (React)"
UI[React UI Components]
Ctx[Context / Zustand Store]
Hooks[Custom Hooks]
end
subgraph "Preload Script (contextBridge)"
Bridge[window.api / window.native]
end
subgraph "Main Process (Node.js)"
Services[45+ Service Modules]
Routers[68+ IPC Routers]
Engines[5 Engines: API / Chat / ClaudeSDK / TinyElf / CLI]
Security[Security Control Layer]
end
subgraph "Worker Threads"
DbWorker[db.worker — SQLite read/write]
FileSearch[fileSearch.worker — file search]
FileWatcher[fileWatcher.worker — file watching]
McpWorker[mcp.worker — MCP server]
DiagWorker[diagnostics.worker — diagnostics]
ProjWorker[project.worker — project indexing]
end
subgraph "External APIs"
LLM[LLM Provider APIs]
Media[Media Generation APIs]
Search[Search Engine APIs]
Channel[Channel Platform APIs]
end
UI --> Bridge
Bridge --> Routers
Routers --> Services
Services --> Engines
Services --> Security
Services --> DbWorker
Services --> FileSearch
Services --> FileWatcher
Services --> McpWorker
Services --> DiagWorker
Services --> ProjWorker
Services --> LLM
Services --> Media
Services --> Search
Engines --> Channel
프로세스 책임
| Process | Responsibilities | Key Files |
|---|---|---|
| Main Process | 모든 비즈니스 로직, 외부 API 호출, 데이터베이스 작업, 파일시스템 접근, 보안 제어 | packages/desktop/app/main/index.ts |
| Renderer Process | 순수 UI 렌더링과 사용자 상호작용. 외부 API나 파일시스템에 직접 접근하지 않음 | packages/renderer/src/app/App.tsx |
| Preload Script | contextBridge를 통해 렌더러 프로세스에 안전한 IPC 인터페이스 노출 | packages/desktop/app/preload/index.ts |
| Worker Threads | 시간이 오래 걸리는 I/O 작업(데이터베이스, 파일 인덱싱, MCP 프로세스 관리) | packages/desktop/app/main/workers/ |
핵심 설계 원칙
1. 엄격한 프론트엔드/백엔드 분리
렌더러 프로세스는 UI만 담당하며, 모든 외부 호출은 Main Process에서만 처리됩니다.
Renderer ──(IPC)──> Main Process ──> External API / Filesystem / Database
│
└──> Process response and return final result
│
Renderer <──(IPC)──< Main Process
금지 사항: 프론트엔드에서 외부 API를 직접 호출하거나, 대량의 데이터를 처리한 뒤 백엔드로 다시 보내는 것.
2. 보안 우선
- Context Isolation: 렌더러 프로세스는 완전히 격리되며
contextBridge를 통해 노출된 인터페이스로만 통신할 수 있습니다 - IPC Auth Token: 모든 IPC 호출은 Main Process의
secureHandle에서 검증되는 인증 토큰을 포함합니다 - API 키는 Main Process에만 저장: 모든 키는 저장 전에
SecurityService(AES-256-GCM)로 암호화됩니다 - ExecutionFirewall: 시스템 디렉터리와 자격 증명 파일에 대한 접근을 차단합니다
- GuardianAgent: 도구 호출 안전성을 AI 기반으로 검토합니다
3. 플러그인 아키텍처
시스템은 여러 플러그인 유형을 지원합니다.
| Plugin Type | Description | Load Location |
|---|---|---|
| Agent Packages | 사전 구성된 Agent 정의(MCP, Skill, Prompt) | agent-packages/ |
| Persona Packages | 사전 구성된 Persona(캐릭터) 정의 | persona-packages/ |
| Script Plugins | 핫 플러그 가능한 MCP 도구 서버 | script-plugins/ |
| Channel Plugins | 멀티 플랫폼 메시징 채널(Discord, Telegram 등) | elftia-channels/ |
| Extensions | SillyTavern 호환 확장 | 동적으로 로드됨 |
4. 멀티 엔진 디스패치
다섯 개의 엔진은 EngineDispatcher를 통해 일관되게 관리되며, Agent 구성에 따라 적절한 엔진으로 라우팅됩니다.
{/* Simplified engine registration */}
interface IEngine {
type: EngineType;
chat(session: EngineSession): Promise<EngineResult>;
cancel(sessionId: string): Promise<void>;
}
type EngineType = 'api' | 'chat' | 'claude-sdk' | 'tinyelf' | 'cli' | 'st-roleplay';
| Engine | Purpose | Implementation File |
|---|---|---|
ApiEngine | 미디어 생성 API(이미지, 음악 등) | services/agent-core/engine/ApiEngine.ts |
ChatEngine | 일반 LLM 채팅 완성 | services/agent-core/engine/ChatEngine.ts |
ClaudeSdkEngine | Claude Agent SDK 세션 | services/agent-core/engine/ClaudeSdkEngine.ts |
TinyElfEngine | 내장 경량 Agent 엔진 | services/agent-core/engine/tinyelf/ |
CliRunnerEngine | CLI 하위 프로세스 Agent(Claude CLI, Codex CLI) | services/agent-core/engine/cli/CliRunnerEngine.ts |
STChatEngine | SillyTavern 호환 RP 파이프라인 | services/agent-core/engine/STChatEngine.ts |
커스텀 프로토콜
Electron은 로컬 리소스를 안전하게 로드하기 위해 4개의 커스텀 프로토콜을 등록합니다.
| Protocol | Purpose | Permissions |
|---|---|---|
elftia:// | Deep Link(OAuth 콜백 등) | Default protocol client |
wallpaper:// | 배경화면 이미지 로딩 | secure, fetchAPI, stream, bypassCSP, CORS |
media:// | 미디어 파일(이미지, 오디오, 비디오) | secure, fetchAPI, stream, bypassCSP, CORS |
resource:// | 일반 리소스 파일 | secure, fetchAPI, stream, bypassCSP, CORS |
데이터베이스 개요
- Engine: better-sqlite3 + Drizzle ORM
- Mode: WAL(Write-Ahead Logging), 동시 읽기 지원
- Location:
{userData}/elftia.db - Access pattern: Worker Thread를 통한 Main Process 비동기 RPC(
DbClient→db.worker.ts)
자세한 데이터베이스 설계는 데이터베이스를 참조하세요.
Monorepo 패키지 구조
elftia/
├── packages/
│ ├── desktop/ # Electron main process + preload
│ │ └── app/
│ │ ├── main/ # Main process code
│ │ │ ├── services/ # 45+ service modules
│ │ │ ├── workers/ # Worker threads
│ │ │ ├── db/ # Drizzle ORM schema
│ │ │ └── ipc/ # IPC security utilities
│ │ ├── preload/ # contextBridge definitions
│ │ └── shared/ # Frontend/backend shared types
│ ├── renderer/ # React frontend (Vite)
│ │ └── src/
│ │ ├── app/ # App entry, layout, Provider host
│ │ ├── features/ # Feature domains (components/hooks/state)
│ │ ├── pages/ # Page-level components
│ │ ├── shared/ # Cross-feature shared (state/Zustand, hooks, utils, components/ui)
│ │ ├── components/ # Legacy shared UI components (including components/ui)
│ │ ├── contexts/ # React Context (limited, retained)
│ │ └── locales/ # i18n (en/zh/ja)
│ ├── server/ # Web server (Fastify) — optional
│ ├── channel-sdk/ # Channel plugin SDK
│ └── pack-cli/ # Agent package management CLI
├── agent-packages/ # Built-in Agent definitions
├── persona-packages/ # Built-in Persona definitions
├── script-plugins/ # Built-in Script plugins
├── elftia-channels/ # Built-in Channel plugins
└── docs/ # Development documentation
경로 별칭
| Alias | Points To | Used In |
|---|---|---|
@/* | packages/renderer/src/* | Renderer process |
@shared/* | packages/desktop/app/shared/* | 전역 공유 타입 |
@main/* | packages/desktop/app/main/* | Main Process 내부 |
기술 스택
| Layer | Technology | Version |
|---|---|---|
| 데스크톱 프레임워크 | Electron | 31.7 |
| 프론트엔드 프레임워크 | React + TypeScript | 18.2 / 5.6 |
| 빌드 도구 | Vite (renderer) / tsup (main) | 7.0 |
| 스타일링 | Tailwind CSS + CSS variables | 3.4 |
| 상태 관리 | React Context + Zustand | — |
| 데이터베이스 | better-sqlite3 + Drizzle ORM | — |
| 코드 편집기 | CodeMirror 6 | — |
| 터미널 에뮬레이터 | xterm 5.5 | — |
| AI SDK | @anthropic-ai/claude-agent-sdk | — |
관련 파일
| File | Description |
|---|---|
packages/desktop/app/main/index.ts | Main Process 진입점. 서비스 초기화와 시작 단계 정의 |
packages/renderer/src/app/App.tsx | Renderer Process 진입점. Context Provider 계층 |
packages/desktop/app/preload/index.ts | Preload Script. contextBridge 인터페이스 노출 |
packages/desktop/app/shared/contracts/ | 프론트엔드와 백엔드 간 공유 타입 계약 |
packages/desktop/app/main/services/agent-core/engine/EngineDispatcher.ts | 엔진 디스패처 |
packages/desktop/app/main/ipc/safe-handle.ts | IPC 보안 핸들 유틸리티 |
vite.config.js | Vite 빌드 구성 |
tsconfig.base.json | TypeScript 기본 구성 |