# Mock 데이터 공유 현황 분석 및 통합 결과 > 최초 작성일: 2026-04-06 > 마지막 업데이트: 2026-04-06 > 대상: `kcg-ai-monitoring` 프론트엔드 코드베이스 전체 (31개 페이지) > 상태: **통합 완료** --- ## 1. 선박 데이터 교차참조 현재 동일한 선박 데이터가 여러 컴포넌트에 독립적으로 하드코딩되어 있다. 각 파일마다 동일 선박의 속성(위험도, 위치, 상태 등)이 서로 다른 형식과 값으로 중복 정의되어 있어 데이터 일관성 문제가 발생한다. | 선박명 | 등장 파일 수 | 파일 목록 | |---|---|---| | 鲁荣渔56555 | 7+ | Dashboard, MobileService, LiveMapView, MonitoringDashboard, EventList, EnforcementHistory, ChinaFishing | | 浙甬渔60651 | 4 | Dashboard, LiveMapView, EventList, DarkVesselDetection | | 冀黄港渔05001 | 6 | MobileService, LiveMapView, Dashboard, TransferDetection, EventList, GearDetection | | 3001함 | 6+ | ShipAgent, MobileService, LiveMapView, Dashboard, PatrolRoute, FleetOptimization | | 3009함 | 6+ | ShipAgent, MobileService, Dashboard, PatrolRoute, FleetOptimization, AIAlert | | 미상선박-A | 5 | MobileService, Dashboard, LiveMapView, MonitoringDashboard, EventList | ### 문제점 - 하나의 선박이 평균 5~7개 파일에 중복 정의됨 - 선박 속성(이름, MMSI, 위치, 위험도, 상태)이 파일마다 미세하게 다를 수 있음 - 새 선박 추가/수정 시 모든 관련 파일을 일일이 찾아 수정해야 함 --- ## 2. 위험도 스케일 불일치 동일한 선박의 위험도가 페이지마다 서로 다른 스케일로 표현되고 있다. | 선박명 | Dashboard (risk) | DarkVesselDetection (risk) | MonitoringDashboard | |---|---|---|---| | 鲁荣渔56555 | **0.96** (0~1 스케일) | - | **CRITICAL** (레벨 문자열) | | 浙甬渔60651 | **0.85** (0~1 스케일) | **94** (0~100 정수) | - | | 미상선박-A | **0.94** (0~1 스케일) | **96** (0~100 정수) | - | ### 원인 분석 - Dashboard는 `risk: 0.96` 형식 (0~1 소수) - DarkVesselDetection은 `risk: 96` 형식 (0~100 정수) - MonitoringDashboard는 `'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW'` 레벨 문자열 - LiveMapView는 `risk: 0.94` 형식 (0~1 소수) - EventList는 레벨 문자열 (`AlertLevel`) ### 통합 방안 위험도를 **0~100 정수** 스케일로 통일하되, 레벨 문자열은 구간별 자동 매핑 유틸로 변환한다. ``` 0~30: LOW | 31~60: MEDIUM | 61~85: HIGH | 86~100: CRITICAL ``` --- ## 3. KPI 수치 중복 Dashboard와 MonitoringDashboard가 **완전히 동일한 KPI 수치**를 독립적으로 정의하고 있다. | 지표 | Dashboard `KPI_DATA` | MonitoringDashboard `KPI` | |---|---|---| | 실시간 탐지 | 47 | 47 | | EEZ 침범 | 18 | 18 | | 다크베셀 | 12 | 12 | | 불법환적 의심 | 8 | 8 | | 추적 중 | 15 | 15 | | 나포/검문(금일 단속) | 3 | 3 | ### 문제점 - 6개 KPI 수치가 두 파일에 100% 동일하게 하드코딩 - 수치 변경 시 양쪽 모두 수정해야 함 - Dashboard에는 `prev` 필드(전일 비교)가 추가로 있으나, Monitoring에는 없음 --- ## 4. 이벤트 타임라인 중복 08:47~06:12 시계열 이벤트가 최소 4개 파일에 각각 정의되어 있다. | 시각 | Dashboard | Monitoring | MobileService | EventList | |---|---|---|---|---| | 08:47 | EEZ 침범 (鲁荣渔56555) | EEZ 침범 (鲁荣渔56555 외 2척) | [긴급] EEZ 침범 탐지 | EVT-0001 EEZ 침범 | | 08:32 | 다크베셀 출현 | 다크베셀 출현 | 다크베셀 출현 | EVT-0002 다크베셀 | | 08:15 | 선단 밀집 경보 | 선단 밀집 경보 | - | EVT-0003 선단밀집 | | 07:58 | 불법환적 의심 | 불법환적 의심 | 환적 의심 | EVT-0004 불법환적 | | 07:41 | MMSI 변조 탐지 | MMSI 변조 탐지 | - | EVT-0005 MMSI 변조 | | 07:23 | 함정 검문 완료 | 함정 검문 완료 | - | EVT-0006 검문 완료 | | 06:12 | 속력 이상 탐지 | - | - | EVT-0010 속력 이상 | ### 문제점 - 동일 이벤트의 description이 파일마다 미세하게 다름 (예: "鲁荣渔56555" vs "鲁荣渔56555 외 2척") - EventList에는 ID가 있으나(EVT-xxxx), 다른 파일에는 없음 - Dashboard에는 10개, Monitoring에는 6개, EventList에는 15개로 **건수도 불일치** --- ## 5. 환적 데이터 100% 중복 `TransferDetection.tsx`와 `ChinaFishing.tsx`에 **TR-001~TR-003 환적 데이터가 완전히 동일**하게 정의되어 있다. ``` TransferDetection.tsx: const transferData = [ { id: 'TR-001', time: '2026-01-20 13:42:11', a: {name:'장저우8호'}, b: {name:'黑江9호'}, ... }, { id: 'TR-002', time: '2026-01-20 11:15:33', ... }, { id: 'TR-003', time: '2026-01-20 09:23:45', ... }, ]; ChinaFishing.tsx: const TRANSFER_DATA = [ { id: 'TR-001', time: '2026-01-20 13:42:11', a: {name:'장저우8호'}, b: {name:'黑江9호'}, ... }, { id: 'TR-002', time: '2026-01-20 11:15:33', ... }, { id: 'TR-003', time: '2026-01-20 09:23:45', ... }, ]; ``` ### 문제점 - 변수명만 다르고 (`transferData` vs `TRANSFER_DATA`) 데이터 구조와 값이 100% 동일 - 한쪽만 수정하면 다른 쪽과 불일치 발생 --- ## 6. 함정 상태 불일치 동일 함정의 상태가 페이지마다 모순되는 경우가 확인되었다. | 함정 | ShipAgent | Dashboard | PatrolRoute | FleetOptimization | |---|---|---|---|---| | 5001함 | **오프라인** (`status: '오프라인'`) | **가용** (PATROL_SHIPS에 대기로 표시) | **가용** (`status: '가용'`) | **가용** (`status: '가용'`) | | 3009함 | **온라인** (동기화 중) | **검문 중** | **출동중** | **출동중** | | 1503함 | **미배포** | - | - | **정비중** | ### 문제점 - 5001함이 ShipAgent에서는 오프라인이지만, Dashboard/PatrolRoute/FleetOptimization에서는 가용으로 표시됨 -- **직접적 모순** - 3009함의 상태가 "온라인", "검문 중", "출동중"으로 파일마다 다름 - 실제 운영 시 혼란을 초래할 수 있는 시나리오 불일치 --- ## 7. 현재 상태: 통합 완료 아래 분석에서 식별한 모든 중복/불일치 문제를 해소하기 위해, 7개 공유 Mock 모듈 + 7개 Zustand 스토어 체계로 통합이 **완료**되었다. ### 7.1 완료된 아키텍처: mock -> store -> page ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ src/data/mock/ (7개 공유 모듈) │ ├───────────┬──────────┬──────────┬────────┬───────────┬────────┬────────┤ │ vessels │ patrols │ events │ kpi │ transfers │ gear │enforce-│ │ .ts │ .ts │ .ts │ .ts │ .ts │ .ts │ment.ts │ └─────┬─────┴─────┬────┴─────┬────┴───┬────┴─────┬────┴───┬────┴───┬────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ src/stores/ (7개 Zustand 스토어 + settingsStore) │ ├───────────┬──────────┬──────────┬────────┬───────────┬────────┬────────┤ │ vessel │ patrol │ event │ kpi │ transfer │ gear │enforce-│ │ Store │ Store │ Store │ Store │ Store │ Store │mentStr │ └─────┬─────┴─────┬────┴─────┬────┴───┬────┴─────┬────┴───┬────┴───┬────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ src/features/*/ (페이지 컴포넌트) │ │ store.load() 호출 -> store에서 데이터 구독 -> 뷰 변환은 페이지 책임 │ └─────────────────────────────────────────────────────────────────────────┘ ``` ### 7.2 스토어별 소비 현황 (16개 페이지가 스토어 사용) | 스토어 | 소비 페이지 | |---|---| | `useVesselStore` | Dashboard, LiveMapView, DarkVesselDetection, VesselDetail | | `usePatrolStore` | Dashboard, PatrolRoute, FleetOptimization | | `useEventStore` | Dashboard, MonitoringDashboard, LiveMapView, EventList, MobileService, AIAlert | | `useKpiStore` | Dashboard, MonitoringDashboard, Statistics | | `useTransferStore` | TransferDetection, ChinaFishing | | `useGearStore` | GearDetection | | `useEnforcementStore` | EnforcementPlan, EnforcementHistory | ### 7.3 페이지 전용 인라인 데이터 (미통합) 아래 페이지들은 도메인 특성상 공유 mock에 포함하지 않고 페이지 전용 인라인 데이터를 유지한다. | 페이지 | 인라인 데이터 | 사유 | |---|---|---| | ChinaFishing | `COUNTERS_ROW1/2`, `VESSEL_LIST`, `MONTHLY_DATA`, `VTS_ITEMS` | 중국어선 전용 센서 카운터/통계 (다른 페이지에서 미사용) | | VesselDetail | `VESSELS: VesselTrack[]` | 항적 데이터 구조가 `VesselData`와 다름 (주석으로 명시) | | MLOpsPage | 실험/배포 데이터 | MLOps 전용 도메인 데이터 | | MapControl | 훈련구역 데이터 | 해상사격 훈련구역 전용 | | DataHub | 수신현황 데이터 | 데이터 허브 전용 모니터링 | | AIModelManagement | 모델/규칙 데이터 | AI 모델 관리 전용 | | AIAssistant | `SAMPLE_CONVERSATIONS` | 챗봇 샘플 대화 | | LoginPage | `DEMO_ACCOUNTS` | 데모 인증 정보 | | 기타 (AdminPanel, SystemConfig 등) | 각 페이지 전용 설정/관리 데이터 | 관리 도메인 특화 | ### 7.4 설계 원칙 (구현 완료) 1. **위험도 0~100 통일**: 모든 선박의 위험도를 0~100 정수로 통일. 레벨 문자열은 유틸 함수로 변환. 2. **단일 원천(Single Source of Truth)**: 각 데이터는 하나의 mock 모듈에서만 정의하고, 스토어를 통해 접근. 3. **Lazy Loading**: 스토어의 `load()` 메서드가 최초 호출 시 `import()`로 mock 데이터를 동적 로딩 (loaded 플래그로 중복 방지). 4. **뷰 변환은 페이지 책임**: mock 모듈/스토어는 원본 데이터만 제공하고, 화면별 가공(필터, 정렬, 포맷)은 각 페이지에서 수행. ### 7.5 Mock 모듈 상세 (참고용) 참고: 초기 분석에서 계획했던 `areas.ts`는 최종 구현 시 `enforcement.ts`(단속 이력 데이터)로 대체되었다. 해역/구역 데이터는 RiskMap, MapControl 등 각 페이지에서 전용 데이터로 관리한다. | # | 모듈 파일 | 스토어 | 내용 | |---|---|---|---| | 1 | `data/mock/vessels.ts` | `vesselStore` | 중국어선 + 한국어선 + 미상선박 마스터 (`MOCK_VESSELS`, `MOCK_SUSPECTS`) | | 2 | `data/mock/patrols.ts` | `patrolStore` | 경비함정 마스터 + 경로/시나리오/커버리지 | | 3 | `data/mock/events.ts` | `eventStore` | 이벤트 타임라인 + 알림 데이터 | | 4 | `data/mock/kpi.ts` | `kpiStore` | KPI 수치 + 월별 추이 | | 5 | `data/mock/transfers.ts` | `transferStore` | 환적 데이터 (TR-001~003) | | 6 | `data/mock/gear.ts` | `gearStore` | 어구 데이터 (불법어구 목록) | | 7 | `data/mock/enforcement.ts` | `enforcementStore` | 단속 이력 + 단속 계획 데이터 | --- ## 8. 작업 완료 요약 | 모듈 | 상태 | 스토어 소비 페이지 수 | |---|---|---| | `vessels.ts` | **완료** | 4개 (useVesselStore) | | `events.ts` | **완료** | 6개 (useEventStore) | | `patrols.ts` | **완료** | 3개 (usePatrolStore) | | `kpi.ts` | **완료** | 3개 (useKpiStore) | | `transfers.ts` | **완료** | 2개 (useTransferStore) | | `gear.ts` | **완료** | 1개 (useGearStore) | | `enforcement.ts` | **완료** | 2개 (useEnforcementStore) | ### 실제 작업 결과 - Mock 모듈 생성: 7개 파일 (`src/data/mock/`) - Zustand 스토어 생성: 7개 + 1개 설정용 (`src/stores/`) - 기존 페이지 리팩토링: 16개 페이지에서 스토어 소비로 전환 - 나머지 15개 페이지: 도메인 특화 인라인 데이터 유지 (공유 필요성 없음) --- ## 9. 결론 위 1~6절에서 분석한 6개의 심각한 중복/불일치 문제(위험도 스케일, 함정 상태 모순, KPI 중복, 이벤트 불일치, 환적 100% 중복, 선박 교차참조)는 **7개 공유 mock 모듈 + 7개 Zustand 스토어** 도입으로 모두 해소되었다. 달성한 효과: - **데이터 일관성**: Single Source of Truth로 불일치 원천 차단 - **유지보수성**: 데이터 변경 시 mock 모듈 1곳만 수정 - **확장성**: 신규 페이지 추가 시 기존 store import로 즉시 사용 - **코드 품질**: 중복 인라인 데이터 제거, 16개 페이지가 스토어 기반으로 전환 - **성능**: Zustand lazy loading으로 최초 접근 시에만 mock 데이터 로딩 1~6절의 분석 내용은 통합 전 문제 식별 기록으로 보존한다.