dark(ship-gis) 프로젝트의 맵 기반 3대 기능을 API 탐색기에 이관.
Feature 폴더 모듈화 구조로 타 프로젝트 재활용 가능하게 구성.
Phase 1: vessel-map 공유 모듈 (Deck.gl 9 + Zustand 5 + STOMP)
Phase 2: 최근 위치 (30초 폴링 + IconLayer + 선종 필터 + 팝업)
Phase 3: 선박 항적 (MMSI 조회 + PathLayer + 타임라인 보간)
Phase 4: 뷰포트 리플레이 (STOMP WebSocket 청크 + TripsLayer 애니메이션)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
백엔드:
- haegu/realtime: DB 공간 JOIN(12s) → 인메모리 캐시 순회(~50ms)
- batch/statistics: N+1 JobExplorer(1.1s) → 단일 SQL 집계(~100ms)
- batch/daily-stats: N+1×7일(9s) → 직접 SQL 2쿼리(~200ms)
- throughput: pg_total_relation_size 매번 호출(1.4s) → Caffeine 5분 캐시
- quality: 풀스캔(0.6s) → 24시간 범위 제한
프론트엔드:
- Promise.allSettled 차단 → 개별 .then() 점진적 렌더링
- useCachedState 훅: 페이지 전환 시 이전 데이터 즉시 표시
- AreaStats: 해구 폴리곤 choropleth 지도 + 선박수 범례 추가
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- AbnormalTracks: 유형별 통계, 일별 추이 차트, 검출 목록 테이블
- abnormalApi 클라이언트 (recent, summary, types)
- ApiMetrics: 시스템 메트릭, 캐시 상세(L1/L2/L3/AIS), 처리 지연, 히트율
- 10초 폴링으로 실시간 갱신
- i18n: abnormal.* 17키 + metrics.* 21키 한/영 추가
- 전체 7개 페이지 라우팅 완성 (Navbar 메뉴 전부 활성)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- MapLibre GL JS 5 지도 컨테이너 (Light/Dark 테마 자동 전환)
- Sidebar 접기/펼치기 레이아웃 (320px 사이드바 + 전체 높이 지도)
- API 유형 선택 UI (최근 위치 / 해구별 항적 / 선박별 항적)
- gisApi 클라이언트 (V1/V2 REST API 인터페이스)
- 지도 상수 (한반도 중심, 항적 색상, OpenFreeMap 타일)
- i18n 한/영 explorer.* 키 12개 추가
- lazy loading: ApiExplorer 청크 분리 (gzip 278KB)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- DataPipeline: 4단계 흐름도(PipelineChart), L1/L2/L3 캐시 현황, 일별 처리량 추이(LineChart), 최근 실행 이력
- AreaStats: 대해구별 선박 통계 테이블, 처리량(파티션 크기), 데이터 품질 검증
- LineChart, PipelineChart 차트 컴포넌트 신규
- API 타입 추가 (CacheDetails, HaeguStat, ThroughputMetrics, DataQuality)
- monitorApi에 getCacheDetails, getHaeguRealtimeStats, getQuality 추가
- i18n pipeline.*, area.* 번역 키 추가 (ko/en)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- CacheMonitoringController: @ConditionalOnProperty 제거, 5개 캐시 통합 집계
- MonitoringController: delay API에서 delayMinutes/status 항상 반환
- FiveMinTrackCache/HourlyTrackCache: getStatsMap() 메서드 추가
- App.tsx: Suspense fallback + ErrorBoundary 추가
- Dashboard.tsx: nullable 필드 방어 (?? 연산자)
- formatters.ts: formatNumber null 안전 처리
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>