Frontend Architecture Report v2.1

IBee Frontend Design

Simplified FSD (4-Layer) 기반 아키텍처 설계
Oracle 리뷰 완료 + IA-FINAL 통합 + Agent Admin 신규 5 페이지

25
페이지
102
컴포넌트
4
FSD 레이어
7
MSW 핸들러
8
설계 문서

핵심 설계 결정

프로젝트 규모와 팀 상황에 맞춘 실용적 선택

L4

Simplified FSD (4-Layer)

entities/widgets 생략, app→pages→features→shared 4개 레이어만 사용. 20페이지 규모에 최적화.

P

Pages First Extraction

페이지 내 구현 → 2+ 페이지 사용 시에만 features/ 추출. 과도한 추상화 방지.

IA

IA-FINAL 통합

기존 3개 IA 문서를 단일 IA-FINAL.md로 통합. 버전 분리 없이 페이지별 final 정리.

Oracle Architecture Review — All Feedback Applied

  • ApiError: isClientError, isRetryable 추가, 422를 validation으로 처리
  • Token Refresh Queue: 실패 시 큐 전체 reject + _retry 마커로 무한루프 방지
  • Zustand에서 token persistence 제거 — tokenService가 단일 소스
  • src/api, src/stores → shared/api, shared/stores로 이동 (FSD 정합성)
  • FilterPanel, WidgetCard → MEDIUM-HIGH, ChartCard → MEDIUM 재분류

Simplified FSD 구조

4개 레이어만 사용하여 복잡도를 낮추고, Oracle 피드백을 반영한 최종 구조

app/
providers/
routes/
layouts/
App.tsx
↓ imports from
pages/
chat/
admin/dashboard/
admin/users/
admin/embedding/
admin/excel/
admin/rag/
↓ imports from
features/
chat/
excel-panel/
data-grid/
filter-bar/
chart-widgets/
↓ imports from
shared/
ui/
components/
api/
stores/
hooks/
lib/
types/

Layer Rules

// 의존성 방향: 위→아래만 허용 app → pages, features, shared pages → features, shared features → shared // cross-feature 금지 shared → (외부 라이브러리만) // 역방향 import 시 ESLint 에러

ESLint Enforcement

module.exports = { rules: { 'import/no-restricted-paths': ['error', { zones: [ { target: './src/features', from: './src/features' }, { target: './src/shared', from: ['./src/app', './src/pages'] }, ] }] } };

72개 컴포넌트 분류

IA-FINAL 기반 8개 카테고리, TypeScript Props 정의 완료

Layout (5)

AdminLayout
ChatLayout
PageHeader
ContentSection
SplitPane

Navigation (6)

Sidebar
SidebarItem
TopBar
Breadcrumb
TabNavigation
QuickActions

Data Display (10)

DataTable
MetricCard
StatusBadge
WidgetCard
SummaryStats
ActivityFeed
ProgressBar
Pagination
EmptyState
LoadingState

Charts (5)

ChartCard
LineChart
DonutChart
HeatmapGrid
TrendIndicator

Form Controls (16)

FilterPanel
FilterSelect
FilterChips
DateRangePicker
SearchInput
TextInput
TextArea
Select
Checkbox
Radio
Toggle
Slider
FileUpload
FormField
FormSection
ActionButtons

Chat Components (16)

ChatContainer
MessageList
MessageBubble
UserMessage
BotMessage
ChatInput
TypingIndicator
StreamingText
ConversationList
ConversationItem
FeedbackButtons
SourceReference
ExcelPanel
ExcelPreview
QuickReplies
WelcomeScreen

Domain-Specific (9)

EmbeddingJobCard
RAGScoreCard
QuestionReviewCard
GoldenSetTable
ParserConfigCard
GlossaryTable
RoutineScheduler
UserRoleSelect
AuditLogTable

Overlay (5)

Modal
Drawer
Toast
Tooltip
ConfirmDialog

Agent Admin — 신규 (30)

AgentCard
AgentCardGrid
HealthDot
AgentDetailPanel
HealthCard
EndpointDisplay
CapabilityTag
TestCaseList
FileAttachedZone
TaskSelector
RunButton
ResultCard
BasisList
TaskReviewItem
ProgressBar
ActivationBanner
CheckGrid
CriteriaCard
DiffSection
ReviewerSection
ErrorStats
SeverityBadge
RetryStatus
StackTrace
ContextGrid
RetrySection
ChangeTimeline
ChangeEntry
DiffDetail
RollbackSection

Reusability Analysis (Top 10)

Component Reusability Usage Key Props
MetricCard HIGH Dashboard, RAG, Embedding label, value, change, icon, color, size
StatusBadge HIGH All Admin pages status, label, animated, withIcon
DataTable HIGH Users, Excel, RAG columns, data, selectable, stickyHeader
FilterPanel MEDIUM-HIGH Users, RAG, Excel filters, values, onChange, collapsible
WidgetCard MEDIUM-HIGH Dashboard title, icon, link, span
ChartCard MEDIUM Dashboard, RAG title, tabs, legend, children
SummaryStats MEDIUM-HIGH RAG, Embedding stats, direction, dividers
ActivityFeed MEDIUM Dashboard items, maxItems, timeFormat
Pagination HIGH All list pages currentPage, totalPages, onPageChange
Modal HIGH All pages open, onClose, title, size, children

상태 관리 설계

Server State와 Client State를 명확히 분리, Token은 tokenService가 단일 소스

Server State (TanStack Query)

// Query Key Factory export const queryKeys = { users: { all: ['users'], list: (params) => [...queryKeys.users.all, 'list', params], detail: (id) => [...queryKeys.users.all, 'detail', id], }, rag: { dashboard: (params) => ['rag', 'dashboard', params], questions: (params) => ['rag', 'questions', params], }, embedding: { status: () => ['embedding', 'status'], jobs: (params) => ['embedding', 'jobs', params], }, };

Client State (Zustand)

// Zustand — NO token persistence // tokenService is single source of truth export const useAppStore = create()( devtools( (...a) => ({ ...createAuthSlice(...a), // user info only ...createUISlice(...a), ...createStreamSlice(...a), }) ) ); // Auth slice — no persist for tokens createAuthSlice: (set) => ({ user: null, isAuthenticated: false, // tokens managed by tokenService })

State Ownership Matrix

State Type Owner Scope Persistence
Server Data TanStack Query Request-scoped cache Memory (staleTime/gcTime)
Auth Tokens tokenService App-scoped localStorage (single source)
URL State React Router Route-scoped URL params
Form State React Hook Form Component-scoped None
UI State (cross) Zustand App-scoped Memory only
UI State (local) useState Component-scoped None

API 통신 설계

Token Refresh Queue + ApiError 클래스로 견고한 에러 처리

Q

Token Refresh Queue

401 발생 시 대기 큐 사용. 실패 시 큐 전체 reject + _retry 마커로 무한루프 방지

Z

Zod Schema Validation

API 응답을 런타임에 검증하여 타입 안전성 확보. safeParse로 graceful 처리

M

MSW Mock Layer

6개 핸들러 그룹으로 백엔드 없이 개발. fixtures로 다양한 시나리오 테스트

ApiError Class (Oracle Feedback Applied)

export class ApiError extends Error { constructor( public status: number, public code: string, message: string, public details?: unknown ) { super(message); } get isUnauthorized() { return this.status === 401; } get isForbidden() { return this.status === 403; } get isNotFound() { return this.status === 404; } get isValidation() { return this.status === 400 || this.status === 422; } get isRateLimited() { return this.status === 429; } get isServerError() { return this.status >= 500; } get isClientError() { return this.status >= 400 && this.status < 500; } get isRetryable() { return this.status >= 500 || this.status === 429; } }

Token Refresh Queue (Oracle Feedback Applied)

let isRefreshing = false; let refreshQueue: Array<{ resolve: Function; reject: Function }> = []; async function handleTokenRefresh(originalRequest) { // Prevent infinite loop with _retry marker if (originalRequest._retry) { throw new ApiError(401, 'AUTH_FAILED', 'Session expired'); } if (isRefreshing) { return new Promise((resolve, reject) => { refreshQueue.push({ resolve, reject }); }); } isRefreshing = true; originalRequest._retry = true; try { const newToken = await refreshToken(); refreshQueue.forEach(({ resolve }) => resolve(newToken)); return retryRequest(originalRequest, newToken); } catch (error) { // Reject ALL queued requests on failure refreshQueue.forEach(({ reject }) => reject(error)); tokenService.clear(); throw error; } finally { isRefreshing = false; refreshQueue = []; } }

MSW Handler Coverage

Handler Group Endpoints Features
auth.handlers login, logout, refresh, me Token management, session
chat.handlers conversations, messages, feedback SSE streaming simulation
admin-users.handlers list, detail, update, delete, export Pagination, filtering, bulk ops
admin-embedding.handlers settings, status, jobs, rerun Idempotency key, job queue
admin-rag.handlers dashboard, questions, review, golden-set Metrics, approval workflow
admin-excel.handlers parsers, glossary, routines, history Bulk operations, scheduling

구현 우선순위

ROI 기반 단계별 구현 계획

Component Library

C1 — HIGH ROI (12개)

MetricCard, StatusBadge, DataTable, FilterPanel, Modal, Pagination, Button, Input, Select, Toast

C2 — MEDIUM-HIGH (16개)

WidgetCard, SummaryStats, ChartCard, MessageBubble, ChatInput, FileUpload, DateRangePicker...

C3 — MEDIUM-LOW (44개)

Domain-specific components, Charts, Advanced features...

Page Development

P0 — Core Infrastructure

app/providers, shared/api, shared/stores, shared/ui

P1 — Admin Shell (5 pages)

Dashboard, Users List/Detail, layouts, navigation

P2 — Embedding (4 pages)

Settings, Status, Jobs List/Detail

P3 — RAG (5 pages)

Dashboard, Questions, Review, Golden Set, Settings

P4 — Excel & Chat (5 pages)

Excel Admin (4), Chat UI (1)

P5 — Agent Admin (5 pages) NEW

Registry, Sample Test, Output Review, Error Logs, Change History (AGT-001~042)

설계 문서 목록

8개 핵심 문서로 구성된 아키텍처 문서 세트

IA

IA-FINAL.md v1.1

25페이지 통합 IA
102개 컴포넌트 집계
Agent Admin 신규 5 페이지

D

frontend-implementation-design.md

메인 설계 문서
Oracle 피드백 반영

T

frontend-component-types.md v3

102개 컴포넌트
TypeScript Props 정의
Agent Admin 30개 신규

M

frontend-msw-handlers.md

6개 핸들러 그룹
MSW + Fixtures

F

frontend-fsd-decision.md

FSD 선택 근거

G

frontend-fsd-guide.md

FSD 운영 가이드

H

frontend-architecture-report.html

이 문서
발표용 요약 v2.1

M

Agent Admin Mockups

v19~v23 (5개)
AGT-001~042 매핑