본문으로 건너뛰기

시작 단계

Elftia의 메인 프로세스 시작 흐름은 13개 단계로 나뉘며, 각 단계에는 명확하게 정의된 책임과 의존성이 있습니다. 모든 단계 코드는 packages/desktop/app/main/index.tscreateServices() 함수에 있습니다.

시작 단계 개요

flowchart TB
P0[Phase 0: Protocol Registration + Logger]
P1[Phase 1: Core Services]
P2[Phase 2: Feature Services]
P25[Phase 2.5: Package Loading]
P26[Phase 2.6: Package Sync]
P27[Phase 2.7: Package Management Service]
PS1[Phase S1: Magi Dispatch]
PS2[Phase S2: MagiService]
PS25[Phase S2.5: CronService]
PC1[Phase C1: Channel Plugins]
PS3[Phase S3: ChannelMagiBridge]
P3[Phase 3: IPC Route Registration]
PT[Phase T1-T3: Todo/Task/Notes]
PW1[Phase W1: Window Creation]
PW2[Phase W2: WebSocket/Protocol]

P0 --> P1 --> P2 --> P25 --> P26 --> P27
P27 --> PS1 --> PS2 --> PS25
PS25 --> PC1 --> PS3
PS3 --> P3 --> PT --> PW1 --> PW2

Phase 0: Protocol Registration + Logger

app.whenReady() 전에 실행됩니다. 사용자 지정 프로토콜과 핵심 로깅 서비스를 등록합니다.

flowchart LR
A[Register elftia:// protocol] --> B[Register privileged schemes]
B --> C[wallpaper://]
B --> D[media://]
B --> E[resource://]
단계작업설명
1app.setAsDefaultProtocolClient('elftia')Deep Link 프로토콜 등록
2protocol.registerSchemesAsPrivileged()wallpaper/media/resource 권한 프로토콜 등록
3new LoggerService()로깅 서비스 생성(Winston + daily-rotate)
4setIpcLogger(logger)IPC 계층 logger 설정
5new ErrorHandler(logger)전역 오류 핸들러 생성
6setIpcErrorHandler(errorHandler)IPC 계층 오류 핸들러 설정
7new AutoUpdateService(logger)자동 업데이트 서비스 생성
8new DownloadService(logger)다운로드 서비스 생성
9new WebUpdateService(logger, downloadManager)웹 업데이트 서비스 생성

주요 파일: packages/desktop/app/main/services/infra/logger/LoggerService.ts, packages/desktop/app/main/services/infra/error/ErrorHandler.ts

Phase 1: Core Services

애플리케이션 실행에 필요한 기반 서비스를 생성합니다. 이 서비스들은 외부 의존성이 없습니다.

flowchart LR
RT[RuntimeService] --> AP[AppPaths]
AP --> DB[DbClient + ready]
DB --> SS[SettingsService]
SS --> CS[ConfigStore]
CS --> Migrate[Config Migration]
Migrate --> Auth[Auth Service Chain]
Auth --> WC[WindowControlsService]
단계서비스의존성설명
1RuntimeServiceNone런타임 정보(버전, 플랫폼, 채널)
2AppPathsNone경로 해석
3DbClientAppPathsDatabase Worker 생성
4await db.ready()DbClientWorker 초기화가 완료될 때까지 차단 대기
5initDatabase()db.readyDrizzle ORM + WAL + migrate
6SettingsServiceAppPaths애플리케이션 설정
7ConfigStoreAppPathselectron-store config 파일
8migrateSettingsToConfigStore()Settings, ConfigStoreSQLite -> config.json 마이그레이션
9settings.setConfigStore(configStore)-Delegate 패턴 연결
10configStore.startWatching()-fs.watch config 핫 리로드
11AccountServiceAppPaths사용자 자격 증명
12AuthTokenStoreAccountService토큰 저장소
13AuthSessionServiceRuntime, AuthStore, AuthApi인증 세션
14AppPreferencesServiceConfigStore애플리케이션 환경설정
15WindowControlsServiceSettings창 컨트롤

핵심 포인트: await db.ready()는 SQLite Worker가 스키마 생성을 완료한 뒤에만 진행되도록 보장하는 차단 지점입니다. 이를 통해 첫 시작 시 두 연결이 동시에 쓰기를 수행할 때 발생하는 SQLITE_BUSY 오류를 방지합니다.

Phase 2: Feature Services

가벼운 기능 서비스를 생성합니다. 무거운 초기화는 사용 시점까지 지연됩니다.

서비스의존성설명
ConfigManagerLogger, AppPathsConfig 파일 관리
SecurityServiceLoggerAES-256-GCM 암호화
PerformanceMonitorLogger성능 모니터링
CacheServiceLogger범용 캐시
DatabaseOptimizerLogger, DbClientSQLite 최적화
NotificationServiceLogger데스크톱 알림
PluginManagerLogger플러그인 생명주기
ProjectServiceDbClient, AccountService프로젝트 관리
DiagnosticsServiceAppPaths, ProjectService진단 서비스
ChatServiceLogger채팅 서비스
McpServiceLoggerMCP server 관리
LLMConfigServiceAppPaths, DbClientLLM 설정
CompletionServiceAppPaths, LLMConfigServiceLLM completion
ApiKeyPoolServiceDB, CompletionService다중 키 라운드로빈
ElfiServiceConfigStore, LLMConfig, CompletionElfi assistant
MediaConfigServiceAppPaths, DbClient미디어 설정
ImageGenerationServiceMediaConfig이미지 생성
ThemeServiceSettings, AuthSession테마 관리
AgentServiceDbClient, Settings, LoggerAgent 서비스
TransformerService-요청 변환
WebSearchService-웹 검색
EngineDispatcher + engine registration각 engine의 의존성Engine dispatch

Engine 등록 순서

{/* Engine registration */}
engineDispatcher.registerEngine(new ApiEngine(...));
engineDispatcher.registerEngine(new ChatEngine(...));
engineDispatcher.registerEngine(new ClaudeSdkEngine(...));
engineDispatcher.registerEngine(new CliRunnerEngine(...));
engineDispatcher.registerEngine(new TinyElfEngine(...));
engineDispatcher.registerEngine(new STChatEngine(...));

Phase 2.5: Package Loading

Agent 패키지, Persona 패키지, Script 플러그인을 디스크에서 메모리로 로드합니다.

flowchart TB
subgraph "Phase 2.5a: Agent Packages"
AL[AgentPackageLoader] --> BP[Load builtin packages]
BP --> UP[Load user packages]
UP --> AR[AgentPackageRegistry]
end

subgraph "Phase 2.5b: Persona Packages"
PL[PersonaPackageLoader] --> BPP[Load builtin packages]
BPP --> UPP[Load user packages]
UPP --> PR[PersonaPackageRegistry]
end

subgraph "Phase 2.5c: Script Plugins"
SL[ScriptPluginLoader] --> BSP[Load builtin plugins]
BSP --> USP[Load user plugins]
USP --> SR[ScriptPluginRegistry]
end

로드 경로(이중 디렉터리 패턴):

패키지 유형내장 경로(패키징됨)내장 경로(dev)사용자 경로
Agentresources/agent-packages/../../agent-packages/{userData}/agent-packages/
Personaresources/persona-packages/../../persona-packages/{userData}/persona-packages/
Scriptresources/script-plugins/../../script-plugins/{userData}/script-plugins/

Phase 2.6-2.7: Package Sync and Management

Phase작업설명
2.6PackageSyncService.syncAll()인메모리 패키지 정의를 데이터베이스에 동기화합니다(upsert FK anchors + persona data)
2.7new AgentPackageService(...)install/uninstall을 지원하는 패키지 관리 서비스를 생성합니다

Phase S1: Magi Dispatch

Agent 오케스트레이션 및 dispatch와 관련된 서비스를 생성합니다.

flowchart TB
AGM[AgentManagementService] --> EB[SessionEventBus]
EB --> AD[AgentDiscovery]
AD --> AO[AgentOrchestrator]
AO --> MR[MessageRouter]
MR --> SDI[SessionDispatcherImpl]

AO -.->|setEngineDispatcher| ED[EngineDispatcher]
AO -.->|setDbProvider| DB[DbClient]
SDI -.->|injected into| TE[TinyElfEngine]
단계서비스설명
1AgentManagementServiceAgent CRUD + 패키지 레지스트리 쿼리
2InternalSessionEventBus세션 이벤트 게시/구독
3AgentDiscovery스케줄 가능한 Agent 목록(DB + 패키지 레지스트리에서 발견)
4AgentOrchestratorAgent dispatch 및 오케스트레이션, API dispatch 핸들러
5MessageRouter이중 모드 메시지 라우팅(직접 / Orchestrator 경유)
6SessionDispatcherImpl세션 간 dispatch 구현
7TinyElfEngine에 주입tinyElfEngine.setSessionDispatcher(sessionDispatcher)
8SubagentRegistry.setDb(db)Subagent 레지스트리 write-through 영속화

역사적 참고: DispatchServer HTTP dispatch server는 cleanup-legacy-mcp(2026-05-19)에서 제거되었습니다. 이제 dispatch 도구는 통합 레지스트리를 통해 MagiDispatchProvider + MagiDispatchHandlers로 프로세스 내부에서 조립됩니다. 핸들러는 HTTP를 거치지 않고 AgentOrchestrator / AgentDiscovery를 직접 호출합니다. CLI subprocess는 중앙 services/capabilities/tools/mcp-builtin/BuiltinMcpHttpServer.ts를 통해 이에 접근합니다.

Phase S2: MagiService

핵심 메시지 처리 서비스를 생성하고 모든 의존성을 주입합니다.

{/* MagiService dependency injection chain */}
const magiService = new MagiService(
magiWorkspace, magiSession, magiOptionsBuilder,
magiOrchestrator, magiMessageRouter, magiEventBus,
llmConfig, logger, configStore,
);

// Deferred injection (avoids circular dependencies)
magiService.setAgentService(agent);
magiService.setCompletionService(completion);
magiService.setAsrService(new AsrService(asrConfig));
magiService.setEngineDispatcher(engineDispatcher);
magiService.setDbProvider(db);
magiService.setMcpListProvider(() => mcp.list());
magiService.setDeveloperModeProvider(() => ...);

MCP 핫 리로드: MCP server 목록이 변경되면 Magi workspace에 자동으로 동기화되고 활성 세션이 핫 리로드됩니다.

mcp.on('servers:changed', () => {
magiService.syncMcpServersToWorkspace();
magiService.notifyMcpChanged();
});

Phase S2.5: CronService

Cron 예약 작업 서비스를 생성합니다.

주입목적
setNotificationService(notification)데스크톱 알림
setNotificationChecker(...)알림 환경설정 확인
setAgentExecutor(...)MagiService를 통해 예약 작업 실행
setStatusBroadcaster(...)작업 상태를 frontend에 브로드캐스트

Phase C1: Channel Plugins

Channel 플러그인을 발견, 로드, 등록합니다.

flowchart TB
CL[ChannelPluginLoader] --> Discover[discover plugins]
Discover --> Load[load each plugin]
Load --> CR[ChannelPluginRegistry.registerPlugin]
CR --> CM[ChannelMarketplaceService<br/>async fetch remote manifest]

subgraph "Security Service Wiring"
UPS[UserPermissionService] --> CMR[ChannelMessageRouter]
CPG[ChannelPermissionGate] --> CMR
AL[AuditLogger] --> TE[TinyElfEngine]
RL[RateLimiter] --> CMR
IS[InputSanitizer] --> CMR
PG[PromptGuardian] --> CMR
end

CR --> CMR

로드 경로(이중 디렉터리 패턴):

소스경로(패키징됨)경로(dev)
Bundled (read-only)resources/bundled-channel-plugins/elftia-channels/dist-plugins/
Marketplace (writable){userData}/channel-plugins/same

보안 서비스 연결 순서:

  1. UserPermissionService -> ChannelMessageRouter (사용자 권한 확인)
  2. ChannelPermissionGate -> ChannelMessageRouter + TinyElfEngine (권한 확인)
  3. AuditLogger -> TinyElfEngine (감사 로깅)
  4. RateLimiter -> ChannelMessageRouter (속도 제한)
  5. InputSanitizer -> ChannelMessageRouter (입력 정리)
  6. PromptGuardian -> ChannelMessageRouter (프롬프트 인젝션 감지)

Phase S3: ChannelMagiBridge

Channel 이벤트를 MagiService에 연결합니다.

const channelMagiBridge = new ChannelMagiBridge(
channelRegistry,
channelMessageRouter,
magiService,
logger,
);

역사적 참고: ChannelServer HTTP server는 cleanup-legacy-mcp(2026-05-19)에서 제거되었습니다. 이제 channel_send / channel_list 및 기타 도구는 통합 레지스트리를 통해 MagiChannelProvider + MagiChannelHandlers로 프로세스 내부에서 조립됩니다. 핸들러는 ChannelPluginRegistry / ChannelMessageRouter를 직접 호출합니다.

Phase 3: IPC Route Registration

모든 IPC 핸들러는 창 생성 전에 등록됩니다.

const router = new Router(/* 60+ service dependencies */);
const { skillHubDownloadService } = router.register();

registerAllRouters()는 내부적으로 68개 이상의 Router 인스턴스를 생성하고 등록합니다.

Router 클래스채널 접두사
AuthRouterauth:*
ProjectRouterprojects:*
SessionRoutersessions:*
CompletionRoutercompletion:*
LLMRouterllmProviders:*, llmModels:*
MediaRoutermedia:*
MagiRoutermagi:*
ChannelPluginRouterchannels:*
SecurityRoutersecurity:*
TodoRoutertodo:*
TaskRoutertasks:*
NoteRouternotes:*
SubagentRoutersubagents:*
ElfiRouterelfi:*
EnvironmentRouterenv:*
... and 50+ other routers...

Phase T1-T3: Todo/Task/Notes

flowchart LR
T1[Phase T1: TodoService] --> T1a[initialize — load TODO.md]
T2[Phase T2: TaskService] --> T2a[initialize — scan tasks]
T3[Phase T3: NoteFileService + NoteWatcher] --> T3a[ensureVaultDir]
T3a --> T3b[scanAllNotes + reindex]
T3b --> T3c[DB notes migration check]
Phase서비스작업
T1TodoServiceMarkdown 할 일 시스템 초기화
T2TaskService파일시스템 + SQLite 작업 관리 초기화
T3NoteFileServicevault 디렉터리가 존재하는지 확인
T3NoteWatcher파일시스템 watcher
T3Notes migrationDB에서 .md 파일로 1회 마이그레이션
T3Startup reindex모든 노트를 스캔하고 DB 인덱스 업데이트

Phase W1: Window Creation

모든 서비스와 IPC route가 등록된 후 BrowserWindow를 생성합니다.

mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
sandbox: true,
preload: preloadPath,
},
});

Phase W2: WebSocket/Protocol Handling

창 생성 후 초기화:

단계작업
1wallpaper:// 프로토콜 핸들러 등록
2media:// 프로토콜 핸들러 등록
3resource:// 프로토콜 핸들러 등록
4renderer URL 로드(dev server 또는 file://)
5대기 중인 Deep Link 처리
6Channel 인스턴스 복원(autoConnect)
7Content Security Policy 설정
8Navigation 가로채기(isAllowedNavigation)

시작 타이밍

createServices()는 주요 단계의 타이밍을 기록합니다.

[INFO] Core services initialized { duration: ~50ms }
[INFO] Feature services created { duration: ~200ms }
[INFO] Agent packages loaded { builtin: N, user: M }
[INFO] Persona packages loaded { builtin: N, user: M }
[INFO] Script plugins loaded { builtin: N, user: M }
[INFO] Magi dispatch services created (Phase S1)
[INFO] MagiService created (Phase S2)
[INFO] ChannelMagiBridge created (Phase S3)
[INFO] IPC handlers registered { duration: ~500ms }

관련 파일

파일설명
packages/desktop/app/main/index.ts메인 프로세스 진입점, createServices() 함수
packages/desktop/app/main/services/routers/index.tsregisterAllRouters() route 등록
packages/desktop/app/main/db/index.tsinitDatabase() 데이터베이스 초기화
packages/desktop/app/main/workers/DbClient.tsDatabase Worker 클라이언트
packages/desktop/app/main/services/infra/logger/LoggerService.ts로깅 서비스
packages/desktop/app/main/services/infra/paths/paths.tsAppPaths 경로 관리
packages/desktop/app/main/services/platform/config/store/ConfigStore.tsConfig 저장소 + fs.watch
packages/desktop/app/main/services/agent-core/agent/AgentPackageLoader.tsAgent 패키지 로더
packages/desktop/app/main/services/agent-core/agent/PersonaPackageLoader.tsPersona 패키지 로더
packages/desktop/app/main/services/capabilities/tools/script-plugin/ScriptPluginLoader.tsScript 플러그인 로더
packages/desktop/app/main/services/capabilities/integrations/channel/ChannelPluginLoader.tsChannel 플러그인 로더
packages/desktop/app/main/services/agent-core/magi/MagiService.tsMagi 핵심 서비스
packages/desktop/app/main/services/agent-core/magi/AgentOrchestrator.tsAgent dispatch 오케스트레이터
packages/desktop/app/main/services/platform/cron/CronService.ts예약 작업 서비스
packages/desktop/app/main/services/content/workspace/todo/TodoService.ts할 일 서비스
packages/desktop/app/main/services/content/workspace/tasks/TaskService.ts작업 관리 서비스
packages/desktop/app/main/services/content/workspace/notes/NoteFileService.ts노트 파일 서비스