CTRL_F Frontend 아키텍처 문서

최종 산출물 - 시스템 아키텍처 명세서


1. 전체 시스템 아키텍처

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                    CLIENT LAYER                                          │
│  ┌───────────────────────────────────────────────────────────────────────────────────┐  │
│  │                              Web Browser (SPA)                                     │  │
│  │  ┌─────────────────────────────────────────────────────────────────────────────┐  │  │
│  │  │                         CTRL_F Frontend Application                          │  │  │
│  │  │                         React 19.2 + TypeScript 5.9                          │  │  │
│  │  └─────────────────────────────────────────────────────────────────────────────┘  │  │
│  └───────────────────────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────────────────────────┘
                                            │
                                            │ HTTPS (Port 443)
                                            ▼
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                   GATEWAY LAYER                                          │
│  ┌───────────────────────────────────────────────────────────────────────────────────┐  │
│  │                              Nginx (Reverse Proxy)                                 │  │
│  │                              - Static File Serving                                 │  │
│  │                              - SPA Routing (try_files)                            │  │
│  │                              - API Proxy to Backend Services                       │  │
│  └───────────────────────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────────────────────────┘
                                            │
                    ┌───────────────────────┼───────────────────────┐
                    │                       │                       │
                    ▼                       ▼                       ▼
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                  BACKEND SERVICES LAYER                                  │
│                                                                                          │
│  ┌─────────────────────┐  ┌─────────────────────┐  ┌─────────────────────┐             │
│  │   Education Service │  │Infrastructure Service│  │    Chat Service    │             │
│  │      (Port 9002)    │  │     (Port 9003)      │  │    (Port 9005)     │             │
│  │                     │  │                      │  │                     │             │
│  │  - 교육 콘텐츠 관리  │  │  - 파일 스토리지     │  │  - AI 챗봇 API     │             │
│  │  - 영상 진행률 추적  │  │  - S3 Presigned URL │  │  - 세션/메시지 관리 │             │
│  │  - 퀴즈 관리        │  │  - RAG 문서 관리     │  │  - FAQ 서비스      │             │
│  │  - 수강 현황        │  │  - 조직도 정보       │  │  - 피드백 수집     │             │
│  └─────────────────────┘  └─────────────────────┘  └─────────────────────┘             │
│                                                                                          │
└─────────────────────────────────────────────────────────────────────────────────────────┘
                                            │
                                            ▼
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                AUTHENTICATION LAYER                                      │
│  ┌───────────────────────────────────────────────────────────────────────────────────┐  │
│  │                              Keycloak (Port 8090)                                  │  │
│  │                              - OAuth2 / OpenID Connect                            │  │
│  │                              - Realm: ctrlf                                        │  │
│  │                              - Client ID: web-app                                  │  │
│  │                              - Role-Based Access Control                          │  │
│  └───────────────────────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────────────────────────┘


2. 프론트엔드 애플리케이션 아키텍처

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                              CTRL_F Frontend Application                                 │
├─────────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                          │
│  ┌─────────────────────────────────────────────────────────────────────────────────┐    │
│  │                              ENTRY POINT                                         │    │
│  │  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐                          │    │
│  │  │  index.html │───▶│   main.tsx  │───▶│   App.tsx   │                          │    │
│  │  └─────────────┘    └─────────────┘    └──────┬──────┘                          │    │
│  │                                               │                                  │    │
│  │                                    React Router DOM                              │    │
│  │                                               │                                  │    │
│  └───────────────────────────────────────────────┼──────────────────────────────────┘    │
│                                                  │                                       │
│  ┌───────────────────────────────────────────────┼──────────────────────────────────┐   │
│  │                              LAYOUT LAYER     │                                   │   │
│  │                                               ▼                                   │   │
│  │  ┌────────────────────────────────────────────────────────────────────────────┐  │   │
│  │  │                            Layout.tsx                                       │  │   │
│  │  │  ┌──────────────┐  ┌──────────────────────────────┐  ┌──────────────────┐  │  │   │
│  │  │  │    Topbar    │  │         Main Content         │  │ FloatingChatbot  │  │  │   │
│  │  │  │   (Header)   │  │      (Page Components)       │  │      Root        │  │  │   │
│  │  │  └──────────────┘  └──────────────────────────────┘  └──────────────────┘  │  │   │
│  │  │  ┌──────────────┐                                                          │  │   │
│  │  │  │   Sidebar    │                                                          │  │   │
│  │  │  │ (Navigation) │                                                          │  │   │
│  │  │  └──────────────┘                                                          │  │   │
│  │  └────────────────────────────────────────────────────────────────────────────┘  │   │
│  └──────────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                          │
│  ┌──────────────────────────────────────────────────────────────────────────────────┐   │
│  │                              PAGE LAYER (8 Pages)                                 │   │
│  │                                                                                   │   │
│  │  ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐                     │   │
│  │  │ Dashboard  │ │  MyPage    │ │ Approval   │ │  Message   │                     │   │
│  │  │   Page     │ │            │ │   Page     │ │   Page     │                     │   │
│  │  │  (홈/대시보드) │ │ (마이페이지) │ │ (전자결재)  │ │  (메신저)   │                     │   │
│  │  └────────────┘ └────────────┘ └────────────┘ └────────────┘                     │   │
│  │                                                                                   │   │
│  │  ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐                     │   │
│  │  │   Event    │ │   Notice   │ │  OrgChart  │ │ Education  │                     │   │
│  │  │   Page     │ │   Page     │ │   Page     │ │   Page     │                     │   │
│  │  │ (행사일정)  │ │ (공지사항)  │ │  (조직도)   │ │   (교육)    │                     │   │
│  │  └────────────┘ └────────────┘ └────────────┘ └────────────┘                     │   │
│  │                                                                                   │   │
│  └──────────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                          │
└─────────────────────────────────────────────────────────────────────────────────────────┘


3. 플로팅 챗봇 패널 아키텍처

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                           FloatingChatbotRoot (패널 관리자)                               │
│                                                                                          │
│  ┌─────────────────────────────────────────────────────────────────────────────────┐    │
│  │                           Panel State Management                                 │    │
│  │                           (useReducer + Z-index 관리)                            │    │
│  └─────────────────────────────────────────────────────────────────────────────────┘    │
│                                          │                                               │
│          ┌───────────────┬───────────────┼───────────────┬───────────────┐              │
│          │               │               │               │               │              │
│          ▼               ▼               ▼               ▼               ▼              │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐       │
│  │ ChatbotApp  │ │  EduPanel   │ │  QuizPanel  │ │   Admin     │ │  Reviewer   │       │
│  │             │ │             │ │             │ │  Dashboard  │ │    Desk     │       │
│  │  ┌───────┐  │ │ ┌─────────┐ │ │ ┌─────────┐ │ │  ┌───────┐  │ │  ┌───────┐  │       │
│  │  │Sidebar│  │ │ │Education│ │ │ │  Quiz   │ │ │  │ 8 Tabs│  │ │  │Review │  │       │
│  │  │       │  │ │ │ Video   │ │ │ │Questions│ │ │  │       │  │ │  │ Queue │  │       │
│  │  │Chat   │  │ │ │ Player  │ │ │ │         │ │ │  │Chatbot│  │ │  │       │  │       │
│  │  │Window │  │ │ │         │ │ │ │  Timer  │ │ │  │Edu    │  │ │  │Review │  │       │
│  │  │       │  │ │ │Progress │ │ │ │         │ │ │  │Quiz   │  │ │  │Detail │  │       │
│  │  └───────┘  │ │ │ Tracker │ │ │ │  Score  │ │ │  │Metrics│  │ │  │       │  │       │
│  │             │ │ └─────────┘ │ │ └─────────┘ │ │  │Logs   │  │ │  │Action │  │       │
│  │  드래그/     │ │             │ │             │ │  │Account│  │ │  │ Bar   │  │       │
│  │  리사이즈    │ │  드래그/     │ │  드래그/     │ │  │Policy │  │ │  └───────┘  │       │
│  │             │ │  리사이즈    │ │  리사이즈    │ │  │FAQ    │  │ │             │       │
│  └─────────────┘ └─────────────┘ └─────────────┘ │  └───────┘  │ │  드래그/     │       │
│                                                  │             │ │  리사이즈    │       │
│                                                  │  드래그/     │ │             │       │
│                                                  │  리사이즈    │ └─────────────┘       │
│                                                  └─────────────┘                        │
│                                                                                          │
│  ┌─────────────────────────────────────────────────────────────────────────────────┐    │
│  │                          Creator Studio View                                     │    │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐   │    │
│  │  │  - 교육 콘텐츠 생성                                                        │   │    │
│  │  │  - 영상 업로드                                                             │   │    │
│  │  │  - 스크립트 편집 (Scene Editor)                                           │   │    │
│  │  │  - 검수 요청                                                               │   │    │
│  │  └──────────────────────────────────────────────────────────────────────────┘   │    │
│  └─────────────────────────────────────────────────────────────────────────────────┘    │
│                                                                                          │
└─────────────────────────────────────────────────────────────────────────────────────────┘


4. 컴포넌트 계층 구조

src/
├── main.tsx                          # 애플리케이션 진입점
├── App.tsx                           # 라우터 설정
├── keycloak.ts                       # Keycloak 인스턴스
├── index.css                         # 전역 스타일
│
├── auth/
│   └── roles.ts                      # 역할 정의 및 권한 로직
│       ├── UserRole (4가지)
│       │   ├── SYSTEM_ADMIN
│       │   ├── CONTENTS_REVIEWER
│       │   ├── VIDEO_CREATOR
│       │   └── EMPLOYEE
│       ├── Capability (3가지)
│       │   ├── OPEN_ADMIN_DASHBOARD
│       │   ├── OPEN_REVIEWER_DESK
│       │   └── OPEN_CREATOR_STUDIO
│       └── Functions
│           ├── normalizeRoles()
│           ├── pickPrimaryRole()
│           └── can()
│
├── types/
│   └── chat.ts                       # 채팅 관련 타입 정의
│       ├── ChatRole
│       ├── ChatDomain (6가지 UI)
│       ├── ChatServiceDomain (4가지 서버)
│       ├── ChatMessage
│       ├── ChatSession
│       ├── ChatAction
│       └── FaqItem
│
├── utils/
│   └── chat.ts                       # 유틸리티 함수
│       ├── buildSessionTitleFromMessage()
│       ├── buildLastMessagePreview()
│       └── computePanelPosition()
│
├── pages/                            # 페이지 컴포넌트 (8개)
│   ├── Dashboard.tsx
│   ├── MyPage.tsx
│   ├── ApprovalPage.tsx
│   ├── MessagePage.tsx
│   ├── EventPage.tsx
│   ├── NoticePage.tsx
│   ├── OrgChartPage.tsx
│   └── EducationPage.tsx
│
├── components/
│   ├── Layout.tsx                    # 공통 레이아웃
│   │
│   ├── common/
│   │   └── api/
│   │       └── authHttp.ts           # HTTP 클라이언트 (인증 포함)
│   │
│   ├── chatbot/                      # 챗봇 관련 (40+ 파일)
│   │   ├── [UI Components]
│   │   │   ├── FloatingChatbotRoot.tsx
│   │   │   ├── FloatingDock.tsx
│   │   │   ├── ChatbotApp.tsx
│   │   │   ├── ChatWindow.tsx
│   │   │   ├── Sidebar.tsx
│   │   │   ├── EduPanel.tsx
│   │   │   ├── QuizPanel.tsx
│   │   │   ├── ReviewerDeskView.tsx
│   │   │   ├── ReviewerQueue.tsx
│   │   │   ├── ReviewerDetail.tsx
│   │   │   ├── ReviewerActionBar.tsx
│   │   │   ├── ReviewerOverlays.tsx
│   │   │   ├── CreatorStudioView.tsx
│   │   │   ├── CreatorScriptSceneEditor.tsx
│   │   │   ├── CreatorTrainingSelect.tsx
│   │   │   └── ProjectFilesModal.tsx
│   │   │
│   │   ├── [API Layer]
│   │   │   ├── chatApi.ts            # 채팅 API (1700+ 줄)
│   │   │   ├── educationServiceApi.ts
│   │   │   ├── creatorApi.ts
│   │   │   ├── reviewerApi.ts
│   │   │   ├── reviewerApiHttp.ts
│   │   │   ├── ragDocumentsApi.ts
│   │   │   ├── infraPresignApi.ts
│   │   │   └── s3Transfer.ts
│   │   │
│   │   ├── [State Stores]
│   │   │   ├── policyStore.ts        # 정책 문서 상태
│   │   │   └── reviewFlowStore.ts    # 검수/게시 상태
│   │   │
│   │   ├── [Custom Hooks]
│   │   │   ├── useCreatorStudioController.ts
│   │   │   ├── useReviewerDeskController.ts
│   │   │   └── useStableEvent.ts
│   │   │
│   │   ├── [Types]
│   │   │   ├── creatorStudioTypes.ts
│   │   │   ├── reviewerApiTypes.ts
│   │   │   ├── reviewerDeskTypes.ts
│   │   │   ├── policyTypes.ts
│   │   │   └── adminRagGapTypes.ts
│   │   │
│   │   ├── [Mocks & Data]
│   │   │   ├── quizData.ts
│   │   │   ├── policyMocks.ts
│   │   │   └── adminRagGapMocks.ts
│   │   │
│   │   └── [Utils]
│   │       ├── creatorStudioCatalog.ts
│   │       ├── creatorStudioUtils.ts
│   │       └── reviewerApiErrors.ts
│   │
│   └── dashboard/                    # 관리자 대시보드 (25+ 파일)
│       ├── AdminDashboardView.tsx    # 메인 대시보드
│       ├── AdminFilterBar.tsx
│       ├── AdminPolicyView.tsx
│       ├── AdminRagGapView.tsx
│       │
│       ├── api/                      # 대시보드 전용 API
│       │   ├── chatApi.ts
│       │   ├── educationApi.ts
│       │   ├── quizApi.ts
│       │   ├── metricApi.ts
│       │   ├── logApi.ts
│       │   ├── userApi.ts
│       │   ├── faqApi.ts
│       │   ├── ragApi.ts
│       │   └── utils.ts
│       │
│       ├── components/
│       │   ├── KpiRow.tsx
│       │   ├── PiiReportCard.tsx
│       │   └── tabs/                 # 8개 탭 컴포넌트
│       │       ├── AdminChatbotTab.tsx
│       │       ├── AdminEducationTab.tsx
│       │       ├── AdminQuizTab.tsx
│       │       ├── AdminMetricsTab.tsx
│       │       ├── AdminLogsTab.tsx
│       │       ├── AdminAccountsTab.tsx
│       │       ├── AdminPolicyTab.tsx
│       │       └── AdminFAQTab.tsx
│       │
│       └── types/
│           ├── index.ts
│           ├── response.ts
│           ├── adminDashboardTypes.ts
│           └── adminFilterTypes.ts
│
└── assets/                           # 정적 리소스
    └── [이미지, 아이콘 등]


5. 데이터 흐름 아키텍처

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                    DATA FLOW                                             │
└─────────────────────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────────────────────┐
│                                   USER INTERACTION                                        │
│                                                                                           │
│  [사용자 입력] ─────────────────────────────────────────────────────────────────────────▶ │
│       │                                                                                   │
│       ▼                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────────────┐ │
│  │                              REACT COMPONENTS                                        │ │
│  │                                                                                      │ │
│  │   ┌──────────────┐     ┌──────────────┐     ┌──────────────┐                        │ │
│  │   │   useState   │     │  useReducer  │     │   useRef     │                        │ │
│  │   │ (로컬 상태)   │     │ (복잡한 상태) │     │  (DOM 참조)  │                        │ │
│  │   └──────────────┘     └──────────────┘     └──────────────┘                        │ │
│  │                                                                                      │ │
│  └─────────────────────────────────────────────────────────────────────────────────────┘ │
│       │                                                                                   │
│       ▼                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────────────┐ │
│  │                              EXTERNAL STORES                                         │ │
│  │                                                                                      │ │
│  │   ┌────────────────────────────┐     ┌────────────────────────────┐                 │ │
│  │   │       policyStore.ts       │     │     reviewFlowStore.ts     │                 │ │
│  │   │                            │     │                            │                 │ │
│  │   │  - Policy Document 관리    │     │  - Review Items 관리       │                 │ │
│  │   │  - Version Control         │     │  - Published Videos 관리   │                 │ │
│  │   │  - 구독 패턴 (Observer)    │     │  - 구독 패턴 (Observer)    │                 │ │
│  │   │  - useSyncExternalStore    │     │  - useSyncExternalStore    │                 │ │
│  │   └────────────────────────────┘     └────────────────────────────┘                 │ │
│  │                                                                                      │ │
│  └─────────────────────────────────────────────────────────────────────────────────────┘ │
│       │                                                                                   │
│       ▼                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────────────┐ │
│  │                                 API LAYER                                            │ │
│  │                                                                                      │ │
│  │   ┌───────────────────────────────────────────────────────────────────────────────┐ │ │
│  │   │                        authHttp.ts (HTTP Client)                               │ │ │
│  │   │                                                                                │ │ │
│  │   │   - Keycloak 토큰 자동 주입                                                    │ │ │
│  │   │   - 요청 중복 제거 (Dedupe)                                                    │ │ │
│  │   │   - 401 에러 시 토큰 갱신 후 재시도                                            │ │ │
│  │   │   - 타임아웃 방어                                                              │ │ │
│  │   └───────────────────────────────────────────────────────────────────────────────┘ │ │
│  │                                          │                                           │ │
│  │          ┌───────────────────────────────┼───────────────────────────────┐          │ │
│  │          │                               │                               │          │ │
│  │          ▼                               ▼                               ▼          │ │
│  │   ┌─────────────┐               ┌─────────────┐               ┌─────────────┐       │ │
│  │   │  chatApi    │               │educationApi │               │ reviewerApi │       │ │
│  │   │             │               │             │               │             │       │ │
│  │   │ - 메시지    │               │ - 교육 목록 │               │ - 검수 목록 │       │ │
│  │   │ - 세션      │               │ - 영상 재생 │               │ - 승인/반려 │       │ │
│  │   │ - FAQ       │               │ - 진행률    │               │ - 락 관리   │       │ │
│  │   │ - 피드백    │               │ - 퀴즈      │               │             │       │ │
│  │   │ - 스트리밍  │               │             │               │             │       │ │
│  │   └─────────────┘               └─────────────┘               └─────────────┘       │ │
│  │                                                                                      │ │
│  └─────────────────────────────────────────────────────────────────────────────────────┘ │
│       │                                                                                   │
│       ▼                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────────────┐ │
│  │                              BACKEND SERVICES                                        │ │
│  │                                                                                      │ │
│  │   ┌─────────────────┐   ┌─────────────────┐   ┌─────────────────┐                   │ │
│  │   │ Chat Service    │   │ Education Svc   │   │  Infra Service  │                   │ │
│  │   │    (9005)       │   │    (9002)       │   │     (9003)      │                   │ │
│  │   └─────────────────┘   └─────────────────┘   └─────────────────┘                   │ │
│  │                                                                                      │ │
│  └─────────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                           │
└───────────────────────────────────────────────────────────────────────────────────────────┘


6. 인증 흐름 아키텍처

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                              AUTHENTICATION FLOW                                         │
└─────────────────────────────────────────────────────────────────────────────────────────┘

┌──────────┐                    ┌──────────┐                    ┌──────────┐
│          │                    │          │                    │          │
│  Browser │                    │ Frontend │                    │ Keycloak │
│          │                    │   App    │                    │  Server  │
│          │                    │          │                    │          │
└────┬─────┘                    └────┬─────┘                    └────┬─────┘
     │                               │                               │
     │  1. 앱 접속                    │                               │
     │ ─────────────────────────────▶│                               │
     │                               │                               │
     │                               │  2. keycloak.init()           │
     │                               │  (login-required)             │
     │                               │──────────────────────────────▶│
     │                               │                               │
     │  3. 로그인 페이지 리다이렉트   │                               │
     │◀──────────────────────────────│◀──────────────────────────────│
     │                               │                               │
     │  4. 사용자 로그인 (ID/PW)     │                               │
     │──────────────────────────────────────────────────────────────▶│
     │                               │                               │
     │  5. Authorization Code        │                               │
     │◀──────────────────────────────────────────────────────────────│
     │                               │                               │
     │  6. Code → Token Exchange     │                               │
     │ ─────────────────────────────▶│──────────────────────────────▶│
     │                               │                               │
     │                               │  7. Access Token + Refresh    │
     │                               │◀──────────────────────────────│
     │                               │                               │
     │                               │  8. 토큰 저장 (메모리)         │
     │                               │  - Access Token               │
     │                               │  - Refresh Token              │
     │                               │  - Token Parsed (roles 포함)  │
     │                               │                               │
     │  9. 앱 렌더링 완료            │                               │
     │◀──────────────────────────────│                               │
     │                               │                               │
     │                               │                               │
     │         [API 요청 시]          │                               │
     │                               │                               │
     │  10. API 호출                  │                               │
     │ ─────────────────────────────▶│                               │
     │                               │                               │
     │                               │  11. updateToken(30)          │
     │                               │  (만료 30초 전 자동 갱신)      │
     │                               │──────────────────────────────▶│
     │                               │                               │
     │                               │  12. 새 Access Token          │
     │                               │◀──────────────────────────────│
     │                               │                               │
     │                               │  13. Authorization Header     │
     │                               │      Bearer {token}           │
     │                               │─────────────────────▶ Backend │
     │                               │                               │
     │                               │                               │

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                              TOKEN STRUCTURE                                             │
├─────────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                          │
│   keycloak.tokenParsed = {                                                              │
│       sub: "user-uuid",                                                                 │
│       name: "홍길동",                                                                    │
│       email: "user@company.com",                                                        │
│       realm_access: {                                                                   │
│           roles: ["SYSTEM_ADMIN", "EMPLOYEE", ...]                                      │
│       },                                                                                │
│       resource_access: {                                                                │
│           "web-app": {                                                                  │
│               roles: ["VIDEO_CREATOR", ...]                                             │
│           }                                                                             │
│       },                                                                                │
│       exp: 1234567890,                                                                  │
│       iat: 1234567800                                                                   │
│   }                                                                                     │
│                                                                                          │
└─────────────────────────────────────────────────────────────────────────────────────────┘