# 08. CEO 대시보드 시스템 > **대상**: 프론트엔드/백엔드 개발자 > **버전**: 1.0.0 > **최종 수정**: 2026-03-09 --- ## 1. 아키텍처 개요 CEO 대시보드는 20개 섹션으로 구성된 실시간 경영 현황 화면. ``` CEODashboard.tsx ├── useCEODashboard() # 12개 섹션 API 통합 Hook ├── useEntertainment() # 접대비 독립 Hook ├── useWelfare() # 복리후생비 독립 Hook ├── useTodayIssue() # 금일 이슈 Hook ├── useCalendar() # 캘린더 Hook ├── useVat() # 부가세 Hook ├── SummaryNavBar # 섹션 바로가기 네비게이션 ├── DashboardSettingsDialog # 섹션 표시/순서 설정 ├── DetailModal # 상세 모달 (공통) └── sections/ # 20개 섹션 컴포넌트 ├── DailyReportSection ├── MonthlyExpenseSection ├── EntertainmentSection ├── WelfareSection └── ... (17개 더) ``` --- ## 2. 섹션 목록 | 섹션 | API Hook | 데이터 소스 | |------|----------|------------| | 일일일보 | useCEODashboard.dailyReport | sam_stat 캐시 | | 현황보드 | useCEODashboard.statusBoard | 실시간 집계 | | 당월예상지출 | useCEODashboard.monthlyExpense | 예상경비 테이블 | | 카드/가지급금 | useCEODashboard.cardManagement | 가지급금 테이블 | | 매출채권 | useCEODashboard.receivable | 매출/입금 | | 채권회수 | useCEODashboard.debtCollection | 부실채권 | | 매출현황 | useCEODashboard.salesStatus | 매출 통계 | | 매입현황 | useCEODashboard.purchaseStatus | 매입 통계 | | 일일생산 | useCEODashboard.dailyProduction | 생산실적 | | 미출하 | useCEODashboard.unshipped | 출하 대기 | | 공사현황 | useCEODashboard.construction | 공사 진행 | | 근태현황 | useCEODashboard.dailyAttendance | 근태 데이터 | | **접대비** | **useEntertainment()** | **expense_accounts** | | **복리후생비** | **useWelfare()** | **expense_accounts** | | 금일이슈 | useTodayIssue() | 이슈 목록 | | 부가세 | useVat() | 부가세 신고 | | 캘린더 | useCalendar() | 일정 | | 출하현황 | useCEODashboard.dailyProduction | 출하 실적 | --- ## 3. Invalidation 시스템 다른 화면에서 CUD 발생 시 대시보드 데이터 자동 갱신. ### 흐름 ``` [입금관리에서 입금 등록] ↓ invalidateDashboard('deposit') ↓ DOMAIN_SECTION_MAP에서 영향 섹션 조회 deposit → ['dailyReport', 'receivable'] ↓ 1. sessionStorage에 stale 섹션 저장 2. CustomEvent 발행 ↓ [대시보드가 마운트 중이면] → 즉시 해당 섹션만 refetch [대시보드 비마운트 상태면] → 다음 방문 시 stale 섹션 refetch ``` ### 도메인 → 섹션 매핑 | 도메인 | 영향 섹션 | |--------|----------| | `deposit` | dailyReport, receivable | | `withdrawal` | dailyReport, monthlyExpense | | `sales` | dailyReport, salesStatus, receivable | | `purchase` | dailyReport, purchaseStatus, monthlyExpense | | `badDebt` | debtCollection, receivable | | `expectedExpense` | monthlyExpense | | `bill` | dailyReport, receivable | | `giftCertificate` | entertainment, cardManagement | | `journalEntry` | entertainment, welfare, monthlyExpense | ### 사용법 (CUD 완료 후) ```typescript import { invalidateDashboard } from '@/lib/dashboard-invalidation'; // 입금 등록 성공 후 const handleSuccess = () => { loadData(); invalidateDashboard('deposit'); }; // 전표 등록 성공 후 const handleJournalSuccess = () => { loadData(); invalidateDashboard('journalEntry'); }; ``` ### 새 도메인 추가 시 `src/lib/dashboard-invalidation.ts`에서: 1. `DomainKey`에 새 도메인 추가 2. `DOMAIN_SECTION_MAP`에 영향 섹션 매핑 추가 3. 해당 도메인의 CUD 콜백에서 `invalidateDashboard('newDomain')` 호출 --- ## 4. 사용자 설정 ### 섹션 표시/숨김 + 순서 ```typescript // localStorage에 저장 const settings: DashboardSettings = { dailyReport: true, monthlyExpense: true, entertainment: { enabled: true, companyType: 'medium' }, welfare: { enabled: true, calculationType: 'monthly' }, sectionOrder: ['dailyReport', 'statusBoard', 'monthlyExpense', ...], }; localStorage.setItem('ceo-dashboard-settings', JSON.stringify(settings)); ``` ### 순서 변경 - DashboardSettingsDialog에서 드래그 앤 드롭 또는 순서 변경 - `sectionOrder` 배열로 관리 --- ## 5. expense_accounts 동기화 접대비/복리후생비 대시보드 카드의 데이터 소스는 `expense_accounts` 테이블. ### 현재 동기화 경로 | 입력 경로 | expense_accounts 반영 | |----------|----------------------| | 일반전표 (수기전표) | **반영됨** — syncExpenseAccounts() | | 가지급금 상품권 | **반영됨** — LoanService | | 출금관리/카드사용내역 | **확인 중** | | 세금계산서 | **확인 중** | | 예상경비 | **확인 중** | ### 동기화 원리 - 전표/거래에서 계정과목명에 "복리후생비" 또는 "접대비"가 포함되면 - `expense_accounts` 테이블에 자동 INSERT - CUD 시 delete-then-insert 전략 (정확한 추적) - `journal_entry_id`, `journal_entry_line_id`로 원본 추적 가능 --- ## 6. 백엔드 참고 ### 대시보드 관련 API | 엔드포인트 | 용도 | |-----------|------| | GET /api/v1/daily-report/summary | 일일일보 요약 | | GET /api/v1/monthly-expense/summary | 당월 예상 지출 | | GET /api/v1/entertainments/summary | 접대비 리스크 카드 | | GET /api/v1/welfares/summary | 복리후생비 리스크 카드 | | GET /api/v1/card-management/summary | 카드/가지급금 | | GET /api/v1/receivable/summary | 매출채권 | ### sam_stat 캐시 - 일부 대시보드 API는 5분 캐시 (sam_stat 테이블) - 실시간이 아닌 근사치 데이터 - invalidation은 프론트 refetch → 백엔드가 캐시 갱신 여부 판단