본문으로 건너뛰기

렌더러 프로세스 설계

렌더러 프로세스는 모든 UI 렌더링과 사용자 상호작용을 처리하며, React 18 + TypeScript로 구축되어 있습니다. 진입 파일은 packages/renderer/src/app/App.tsx입니다.

Context Provider 계층

App 컴포넌트는 엄격한 Provider 중첩 순서를 정의합니다. 바깥쪽 Provider는 안쪽 Provider와 컴포넌트에서 접근할 수 있습니다.

graph TB
LP[LocaleProvider — i18n internationalization]
TP[ThemeProvider — theme/wallpaper]
CDP[ConfirmDialogProvider — global confirm dialog]
AP[AuthProvider — auth state]
SDP[SettingsDataProvider — settings data]
EP[ElfiProvider — Elfi assistant]
WSP[WebSearchProvider — search]
ChatDP[ChatDataProvider — chat data cache]
CBP[ChatBackendProvider — WebSocket backend]
UCP[UnifiedChatProvider — unified chat API]
HPP[HtmlPreviewProvider — HTML preview]
DPP[DevPreviewProvider — dev preview]
PR[ProtectedRoute — route guard]
HR[HashRouter — frontend routing]
CTP[ChatTabsProvider — multi-tab management]
AR[AppRoutes — route definition]
AC[AppContent — main content]

LP --> TP --> CDP --> AP --> SDP --> EP --> WSP --> ChatDP --> CBP --> UCP --> HPP --> DPP --> PR --> HR --> CTP --> AR --> AC
// Actual nesting structure in App.tsx
function App() {
return (
<LocaleProvider>
<ThemeProvider>
<ConfirmDialogProvider>
<AuthProvider>
<SettingsDataProvider>
<ElfiProvider>
<WebSearchProvider>
<ChatDataProvider>
<ChatBackendProvider>
<UnifiedChatProvider>
<HtmlPreviewProvider>
<DevPreviewProvider>
<ProtectedRoute>
<HashRouter>
<ChatTabsProvider>
<AppRoutes>
<AppContent />
</AppRoutes>
</ChatTabsProvider>
</HashRouter>
</ProtectedRoute>
</DevPreviewProvider>
</HtmlPreviewProvider>
</UnifiedChatProvider>
</ChatBackendProvider>
</ChatDataProvider>
</WebSearchProvider>
</ElfiProvider>
</SettingsDataProvider>
</AuthProvider>
</ConfirmDialogProvider>
</ThemeProvider>
</LocaleProvider>
);
}

Zustand Store

고빈도로 업데이트되는 채팅 상태는 Context로 인한 불필요한 리렌더링을 피하기 위해 Zustand를 사용합니다.

chatStore

정밀한 구독을 위해 subscribeWithSelector 미들웨어를 사용하는 핵심 채팅 상태 저장소입니다.

// Simplified chatStore state interface
interface ChatState {
// Sessions
sessions: Session[];
sessionsLoading: boolean;
sessionsError: Error | null;

// Assistants
assistants: ChatAssistant[];
assistantsLoading: boolean;

// Providers
providers: LLMProvider[];
providersLoading: boolean;

// Message cache (indexed by sessionId)
messageCache: Map<string, Message[]>;

// Streaming state
streamingState: StreamingState;

// Branch info
branchInfo: Map<string, BranchInfo>;

// Actions
fetchSessions(): Promise<void>;
fetchAssistants(): Promise<void>;
fetchProviders(): Promise<void>;
loadMessages(sessionId: string): Promise<void>;
setStreamingState(state: Partial<StreamingState>): void;
switchBranch(messageId: string, index: number): void;
}
// Use selector for precise subscription, avoid irrelevant re-renders
const sessions = useChatStore(state => state.sessions);
const isStreaming = useChatStore(state => state.streamingState.isStreaming);
Store파일책임
chatStoreshared/state/chatStore.ts세션, 메시지, 스트리밍 상태, 브랜치
settingsStoreshared/state/settingsStore.ts설정 상태
useChatStoreSyncshared/state/useChatStoreSync.tsChatDataContext → chatStore 동기화

React Context 세부 정보

23개 이상의 Context가 있으며, 각각 독립적인 책임을 가집니다.

Context파일책임핵심 상태/메서드
LocaleContextshared/state/LocaleContext.tsxi18n(en/zh/ja)useTranslation(), setLocale()
themeStoreshared/state/themeStore.ts(호스트 app/ThemeHost.tsx)테마 모드, 배경화면, 사용자 지정 CSSmode, resolvedMode, userTheme, customCss
ConfirmDialogHostshared/state/ConfirmDialogHost.tsx전역 확인 대화상자confirm(options)
authStoreshared/state/authStore.ts인증 상태user, isAuthenticated, login(), logout()
SettingsDataHostapp/SettingsDataHost.tsx설정 읽기/쓰기settings, updateSetting()
ElfiContextfeatures/elfi/state/ElfiContext.tsxElfi 스마트 어시스턴트isOpen, messages, sendMessage()
webSearchStoreshared/state/webSearchStore.ts(호스트 app/WebSearchHost.tsx)웹 검색search(), results
chatStoreshared/state/chatStore.ts채팅 데이터 캐시 + 통합 채팅 API(이전 ChatDataContext / UnifiedChatContext가 여기로 마이그레이션됨)sessions, messages, sendMessage(), regenerate(), editMessage()
htmlPreviewStoreshared/state/htmlPreviewStore.ts(호스트 app/HtmlPreviewHost.tsx)HTML 콘텐츠 미리보기showPreview(), previewContent
devPreviewStoreshared/state/devPreviewStore.ts(호스트 app/DevPreviewHost.tsx)Dev 모드 미리보기isDevMode, devData
ChatTabsContextfeatures/chat/state/ChatTabsContext.tsx다중 탭 채팅 관리tabs, activeTabId, createTab(), closeTab()
AgentContextfeatures/agents/state/AgentContext.tsxAgent 상태agents, selectedAgent
subagentStoreshared/state/subagentStore.ts(호스트 shared/state/SubagentHost.tsx)Subagent 상태subagents, status
MessageSelectionContextfeatures/chat/state/MessageSelectionContext.tsx메시지 다중 선택selectedIds, toggleSelect()
sessionOrganizerStoreshared/state/sessionOrganizerStore.ts(호스트 shared/state/sessionOrganizerStore/SessionOrganizerHost.tsx)세션 정리/분류folders, moveSession()
worksStoreshared/state/worksStore.tsWorks 관리works, createWork()
musicWorksStoreshared/state/musicWorksStore.ts음악 Workstracks, playTrack()
musicTemplateStoreshared/state/musicTemplateStore.ts음악 템플릿templates
VideoWorksContextfeatures/media/state/VideoWorksContext.tsx비디오 Worksvideos
videoTemplateStoreshared/state/videoTemplateStore.ts비디오 템플릿templates
TemplateContextfeatures/marketplace/state/TemplateContext.tsx이미지 템플릿templates
useWorldInfoHighlightshared/hooks/characters/useWorldInfoHighlight.tsWI 키워드 하이라이트highlightedKeywords

사용자 지정 Hooks

60개 이상의 사용자 지정 Hooks가 기능 도메인별로 구성되어 있습니다.

채팅 관련

Hook파일목적
useAppStateshared/hooks/useAppState.ts뷰 플래그, 활성 탭, 사용자 기본 설정을 중앙에서 관리
useRouteSyncshared/hooks/useRouteSync.tsURL 경로를 뷰 상태와 동기화
useSessionProtectionfeatures/chat/hooks/useSessionProtection.ts활성 세션 보호(새로고침으로 인한 삭제 방지)
useDraftfeatures/chat/hooks/useDraft.ts입력 초안 저장/복원
useAutoUpdateshared/hooks/useAutoUpdate.ts앱 자동 업데이트
useAudioRecorderfeatures/media/hooks/useAudioRecorder.ts오디오 녹음

기능 Hook 디렉터리

디렉터리목적대표 Hooks
features/chat/hooks/채팅 작업useMessageStream, useBranchNavigation
features/marketplace/hooks/channel/Channel 플러그인useChannelPlugins
shared/hooks/characters/character/캐릭터 카드useCharacterCards
shared/hooks/characters/worldinfo/세계 정보useWorldInfo
shared/hooks/characters/WI 하이라이트 / 태그useWorldInfoHighlight, useTagsData
features/characters/hooks/sprites/표정 스프라이트useSprites
features/settings/components/tabs/tools-tab/hooks/MCP 서버useMcpManagement
features/kb/hooks/노트 시스템useNotesData
features/todo/hooks/TodosuseTodoData
features/tasks/hooks/태스크 관리useTasksData
features/cron/hooks/예약된 태스크useCronJobs
features/marketplace/hooks/skills/Skill 관리useSkillHub

컴포넌트 아키텍처

레이아웃 구조

graph TB
Root["div.fixed.inset-0.flex.bg-background"]
WS[WorkspaceShell]
WR[WorkspaceRail — left navigation rail]
TB[TitleBar — tab bar + window control]
MC[Main Content — routed content area]

Root --> WS
WS --> WR
WS --> TB
WS --> MC

MC --> ChatPage
MC --> AgentPage
MC --> SettingsPage
MC --> RoleplayPage
MC --> NotesPage
MC --> CoworkPage
  • WorkspaceRail: 왼쪽 고정 내비게이션 레일로, Home, Agents, Settings 진입점을 포함합니다.
  • WorkspaceShell: 메인 레이아웃 컨테이너로, 레일 + 탭 바 + 콘텐츠 영역을 관리합니다.
  • TitleBar: 다중 탭 바 + 창 제어 버튼(최대화/최소화/닫기)입니다.
  • Main Content: 라우트에 따라 페이지 컴포넌트를 동적으로 렌더링합니다.

Workspace 확장(Workspace Registry)

Chat/Agent 페이지 사이의 "workspace 패널"(파일 트리 오른쪽의 editor / git diff / HTML preview / canvas / design studio 영역)은 WorkspaceDefinition registry를 통해 확장됩니다. 호스트 Shell인 WorkspaceArea.tsx는 레이아웃 + registry 디스패치만 수행하며, activeView === 'X' 같은 비즈니스 분기는 포함하지 않습니다.

graph TB
WA["WorkspaceArea<br/>(layout + dispatch)"]
Reg["registry.ts<br/>WORKSPACE_REGISTRY[]"]
Slot["WorkspaceToolbarProvider<br/>(slot context)"]
Aff["host-affordances<br/>(cross-view coordination)"]
Defs["definitions/"]

WA -->|findActiveWorkspace| Reg
WA -->|wraps| Slot
WA -->|consumes| Aff
Reg -->|imports| Defs

Defs --> EW[EditorWorkspace]
Defs --> GW[GitWorkspace]
Defs --> HW[HtmlPreviewWorkspace]
Defs --> AW[A2UIWorkspace]
Defs --> DW[DevPreviewWorkspace]
Defs --> DS[DesignStudioWorkspace]
Defs --> CW[CanvasWorkspace]

WorkspaceDefinition은 다음을 자체 관리합니다.

  • 자체 view 식별자 + isAvailable(ctx) 조건자
  • 자체 뷰 모드 상태(split/code/preview 등 내부 useState — 호스트로 누출되지 않음)
  • useWorkspaceToolbar(config)로 슬롯에 툴바 구성 게시. 호스트의 <WorkspaceToolbar>useWorkspaceToolbarConfig()로 읽음
  • 선택적 onClose(ctx, cb) hook(닫기 버튼으로 트리거되고 React 트리 밖에서 실행되므로 close-fn 채널은 WorkspaceCallbacks를 사용)

새 workspace 유형 추가 = 2개 파일 수정: registry.ts 배열에 항목 추가 + definitions/<Name>Workspace.tsx 생성. WorkspaceArea.tsx는 변경할 필요가 없습니다. 자세한 절차는 packages/renderer/CLAUDE.md의 "🧩 Add New Workspace Type" 섹션, 계약 사양은 openspec/specs/workspace-registry/spec.md에 있습니다.

크로스 뷰 조정(예: editor의 "Preview" 버튼이 htmlPreview 뷰로 이동, HTML preview 최대화 시 전체 workspace 패널 숨김)은 host-affordances.ts에 중앙화되어 있습니다. 이곳만 activeView === 'X' 판단이 허용되는 위치입니다.

파일책임
features/chat/components/content/WorkspaceArea.tsx호스트 Shell(레이아웃 + 슬롯 리더 + registry 디스패치, 비즈니스 분기 없음)
features/chat/components/content/workspaces/types.tsWorkspaceDefinition / WorkspaceHostContext / WorkspaceCallbacks 계약
features/chat/components/content/workspaces/registry.tsWORKSPACE_REGISTRY 단일 등록 지점 + findActiveWorkspace 쿼리
features/chat/components/content/workspaces/host-affordances.ts크로스 뷰 조정(크로스 뷰 토글 + 최대화 숨김)
features/chat/components/content/workspaces/workspace-toolbar-slot{,-internals,-hooks}.{tsx,ts}툴바 슬롯 3종(Provider / contexts / hooks)
features/chat/components/content/workspaces/definitions/<Name>Workspace.tsx7개 workspace 정의(editor / git / htmlPreview / a2ui / devPreview / designStudio / canvas)
features/chat/components/content/workspaces/inline-file-viewers.tsxInlineMarkdownViewer + InlineBinaryViewer(image/audio/video/pdf + "미리보기 불가" 폴백)
features/chat/components/content/workspaces/inline-file-viewers-types.tsgetBinaryFileType / isMarkdownFile / isNonTextFile 파일 유형 감지
features/chat/components/content/unified-page/hooks/useWorkspaceState.tsWorkspace 상태 hook(.htmlopenHtmlPreview() 라우팅 + handleFileSelect의 바이너리 파일 라우팅)

라우팅 시스템

HashRouter(Electron은 BrowserRouter를 지원하지 않음)를 사용하고, useRouteSync Hook으로 URL을 뷰 상태와 동기화합니다.

// Sync route to view state
function useRouteSync(pathname: string, state: AppState) {
useEffect(() => {
if (pathname.startsWith('/chat')) {
state.setIsChatView(true);
state.setIsHomeView(false);
} else if (pathname.startsWith('/agents')) {
state.setIsAgentView(true);
} else if (pathname.startsWith('/settings')) {
state.setIsSettingsView(true);
}
}, [pathname]);
}

i18n 국제화

useTranslation() Hook을 사용해 3개 언어를 지원합니다.

언어디렉터리파일
Englishlocales/en/15개 이상의 JSON 파일
Chinese (Simplified)locales/zh/15개 이상의 JSON 파일
Japaneselocales/ja/15개 이상의 JSON 파일

번역 파일은 common.json, chat.json, settings.json, characters.json, elfi.json 등 기능 도메인별로 분할됩니다.

AppState Hook

useAppState는 전역 UI 상태를 중앙에서 관리합니다.

// Simplified AppState interface
interface AppState {
// View flags
isHomeView: boolean;
isChatView: boolean;
isAgentView: boolean;
isSettingsView: boolean;

// Active session
selectedSession: string | null;
activeSessions: Set<string>;
processingSessions: Set<string>;

// Tabs
activeTab: string;
settingsInitialTab: string;

// User preferences
autoExpandTools: boolean;
showRawParameters: boolean;
showThinking: boolean;
autoScrollToBottom: boolean;
sendByCtrlEnter: boolean;

// Modals
showVersionModal: boolean;
}

빌드 구성

구성
Build toolVite 7.0
StylingTailwind CSS 3.4 + CSS 변수(시맨틱 토큰)
Code splitting라우트 수준 지연 로딩(lazy/ 디렉터리, 목적별 6개 파일 + 1개 barrel)
Tree shakingNamed imports
Main bundle limit500 KB

관련 파일

파일설명
packages/renderer/src/app/App.tsxApp 진입점, Provider 계층 및 레이아웃
packages/renderer/src/shared/state/chatStore.tsZustand 채팅 상태 Store
packages/renderer/src/shared/state/settingsStore.tsZustand 설정 상태 Store
packages/renderer/src/shared/state/chatStore.ts통합 채팅 API(이전 UnifiedChatContext가 chatStore로 마이그레이션됨)
packages/renderer/src/shared/state/themeStore.ts테마 Store(이전 ThemeContext)
packages/renderer/src/shared/hooks/useAppState.ts중앙화된 UI 상태 관리
packages/renderer/src/shared/hooks/useRouteSync.ts라우트 동기화
packages/renderer/src/app/layout/WorkspaceShell.tsx메인 레이아웃 컨테이너
packages/renderer/src/app/layout/WorkspaceRail.tsx왼쪽 내비게이션 레일
packages/renderer/src/app/title-bar/탭 바 컴포넌트
packages/renderer/src/app/lazy/지연 로드 컴포넌트 디렉터리(pages.tsx / workspaces.tsx / inline.tsx / shell.tsx / skeletons.tsx / with-suspense.tsx, barrel은 lazy/index.ts)
packages/renderer/src/features/chat/components/content/WorkspaceArea.tsx중앙 workspace 호스트 Shell(레이아웃 + registry 디스패치, 비즈니스 분기 없음)
packages/renderer/src/features/chat/components/content/workspaces/Workspace registry(WorkspaceDefinition 계약 + 7개 정의 파일 + 툴바 슬롯 + host-affordances)
packages/renderer/src/app/railItems.ts내비게이션 레일 구성
packages/renderer/src/app/mainContentRouter.tsx메인 콘텐츠 라우터 파싱
packages/renderer/CLAUDE.md프론트엔드 UI 개발 표준