백엔드:
- 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>
GREATEST() 반환값이 double precision이라 ROUND(dp, int) 호출 시
PostgreSQL에서 미지원 함수 에러 발생 → 전체 나눗셈 결과를 ::numeric 캐스팅
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- JdbcTemplate이 timestamptz를 java.sql.Timestamp로 반환하는 케이스 처리
- toLocalDateTime() 유틸 메서드로 Timestamp/OffsetDateTime/LocalDateTime 통합 변환
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>
- CacheBasedVesselTrackDataReader: stale 그룹 스킵 제거 → 전체 통과 + 감지 로깅
- VesselTrackStepConfig: Processor에서 stale time_bucket 감지 시 비정상 궤적으로 전환
- abnormal_type: stale_timestamp (신규 분류)
- time_bucket: 현재 5분 버킷으로 오버라이드 (파티션 존재 보장)
- details: 원본 time_bucket, 지연 시간(분/시), 속도/거리 정보
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- CollectDB 다중 신호 수집 → S&P Global AIS API 단일 수집으로 전환
- sig_src_cd + target_id 이중 식별자 → mmsi(VARCHAR) 단일 식별자
- t_vessel_latest_position → t_ais_position 테이블 전환
- 레거시 배치/유틸 ~30개 클래스 삭제 (VesselAggregationJobConfig, ShipKindCodeConverter 등)
- AisTargetCacheManager 기반 캐시 이중 구조 (최신위치 + 트랙 버퍼)
- CacheBasedVesselTrackDataReader + CacheBasedTrackJobListener 신규 추가
- VesselStaticStepConfig: 정적정보 CDC 변경 검출 + hourly job 편승
- SignalKindCode enum: vesselType/extraInfo 기반 선종 자동 분류
- WebSocket/STOMP 전체 mmsi 전환 (StompTrackStreamingService ~40곳)
- 모니터링/성능 최적화 코드 mmsi 기반 전환
- DataSource 설정 통합 (snpdb 단일 DB)
- AreaBoundaryCache Polygon→Geometry 캐스트 수정 (MULTIPOLYGON 지원)
- ConcurrentHashMap 적용 (VesselTrackStepConfig 동시성 버그 수정)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 모든 모드(ANY/ALL/SEQUENTIAL)에서 동일 구역 재방문 시 개별 방문 단위로 분리
- PolygonHitDetail에 visitIndex 필드 추가 (구역별 방문 순번, 1-based)
- 진입/진출 시각을 JTS LineSegment.intersection() 기반 거리 비율 보간으로 산출
- SEQUENTIAL 모드: greedy chain 탐색, 유효 체인만 반환 (visitIndex=1 재설정)
- hitDetails 배열을 entryTimestamp 오름차순 정렬 (배열 인덱스 = 전체 방문 순서)
- Swagger 설명에 개별 방문 분리, 경계 보간 관련 내용 추가
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- POST /api/v2/tracks/vessels: DailyTrackCacheManager 캐시-DB 분리 조회
- 모든 V2 항적 엔드포인트에 ActiveQueryManager 공유 Semaphore 적용
- 포인트 버짓: 총 포인트 초과 시 비율 기반 균등 분배 간소화
- prod/prod-mpr/query 프로파일에 rest.v2.query 설정 추가
- 원격 DB 필요 테스트 @Disabled 처리, Maven Wrapper/gitattributes 정비
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
vessel.integration.datasource.table-name → vessel.integration.table-name으로 변경.
YAML 구조와 불일치하여 prod에서 기본값(signal.t_ship_integration_sub)이 사용되었고,
별도 DB(mdadb2 gis 스키마)에 signal 스키마가 없어 조회 실패하던 문제 해결.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
캐시 기반 인메모리 다중 폴리곤 영역 내 선박 탐색 API 구현.
JTS STRtree + PreparedGeometry로 고속 공간 검색, ANY/ALL/SEQUENTIAL 3가지 모드 지원.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- IntegrationVesselService에 전용 DataSource 자체 생성/관리 추가
- vessel.integration.datasource.* 설정으로 별도 DB 연결 가능
- @PostConstruct에서 경량 HikariDataSource 생성 (max 3, min 1)
- 미설정 시 queryDataSource 자동 폴백 (기존 동작 유지)
- prod: 별도 DB (mdadb2 gis.t_ship_integration_sub) → 전용 DataSource
- dev/prod-mpr: queryDB signal 스키마 → queryDataSource 폴백
- 기존 DataSourceConfig 4개 파일 수정 없이 프로파일 완벽 호환
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
문제: 캐시 경로에서 뷰포트 공간 필터를 이중 적용하여,
다른 날짜에서 뷰포트를 통과한 선박의 항적이 누락되는 버그
수정 내용:
- collectViewportVesselIds: 캐시된 날짜는 메모리에서 뷰포트 체크 (DB 커넥션 절약)
- processDailyStrategy: viewportVesselIds(2-pass 결과) 있으면 vessel ID 필터만 적용,
공간 필터 재적용 금지 → 전체 조회기간 항적 무결성 보장
- processQueryInChunks: 동일 패턴 적용
- StompTrackStreamingService: 캐시 경로에 filteredVessels 필터 적용
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- DailyTrackCacheManager: D-1~D-7 daily 테이블 데이터 인메모리 캐시
- @Async 비동기 워밍업 (서버 시작 차단 없음, 최근 우선 로드)
- 뷰포트 필터링, 다중 날짜 병합 조회, 하이브리드 쿼리 분리
- 메모리 한도 체크 (기본 5GB), 날짜별 즉시 활성화
- DailyTrackCacheProperties: enabled, retentionDays, maxMemoryGb 설정
- DailyAggregationJobConfig: 배치 완료 시 캐시 자동 갱신 리스너
- ChunkedTrackStreamingService: daily 전략에서 캐시 우선 조회 + DB 폴백
- StompTrackStreamingService: 동일 캐시 우선 패턴 적용
- WebSocketMonitoringController: GET /api/websocket/daily-cache 엔드포인트
- application-prod.yml: cache.daily-track 설정 추가
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 4: 설정 외부화 및 모니터링
- WebSocketProperties: websocket.* 설정을 @ConfigurationProperties로 바인딩
- query: 동시 제한, 세션 제한, 대기 큐 타임아웃
- transport: 인바운드/아웃바운드 채널 스레드풀, 메시지 크기
- backpressure: 버퍼 크기, 메시지 크기 제한
- WebSocketMonitoringController에 /api/websocket/load-control 엔드포인트 추가
- 글로벌 동시 쿼리 수, 대기 큐 현황
- 활성 쿼리 상세 (세션ID, 쿼리ID, 시작시간, 진행테이블, 청크수, 취소여부)
- 메모리 사용률
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 3: 백프레셔 고도화
- ChunkedTrackStreamingService:
- CompletableFuture+Thread.sleep(100ms) 추정 방식 제거
- 전송 완료 후 try-finally에서 즉시 버퍼 크기 감소 (정확한 추적)
- 정적 대기 → 버퍼 사용률(%) 기반 4단계 적응형 지연
- StompTrackStreamingService:
- 총 트랙 수 기반 정적 지연 제거
- BlockingQueue 사용률 + 데이터 크기 복합 적응형 지연으로 교체
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 2.2: 쿼리 관리 시스템 통합
- StompTrackController의 status callback에서 activeQueryManager.completeQuery() 제거
- 리소스 정리를 서비스(ChunkedTrack/StompTrack) finally 블록에서 일괄 처리
- 중복 completeQuery 호출 제거로 쿼리 생명주기 관리 단일화
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 2.1: 기존 TODO만 있던 cancelQuery()에 실제 취소 메커니즘 추가
- 쿼리별 AtomicBoolean 취소 플래그(queryCancelFlags) 관리
- streamChunkedTracks 시작 시 취소 플래그 등록, finally에서 정리
- 테이블 전략별 루프 진입 전 취소 확인
- isQueryCancelled()에 queryCancelFlags 통합 확인 추가
- cancelQuery() 호출 시 플래그 설정으로 진행 중인 스트리밍 중단
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 1.3: 무제한 스레드 생성 방지
- newCachedThreadPool → ThreadPoolExecutor(core:5, max:20, queue:100)
- CallerRunsPolicy 적용으로 큐 포화 시 자연 백프레셔
- 부하 시 무제한 스레드 생성으로 인한 OOM/컨텍스트 스위칭 오버헤드 방지
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 1.1 + 1.2: WebSocket 리플레이 요청 동시 부하 제어
- ActiveQueryManager에 Fair Semaphore 기반 글로벌 동시 쿼리 제한 추가 (기본 30개)
- @Async 스트리밍 메서드 내에서 슬롯 획득 (인바운드 채널 블로킹 방지)
- 쿼리 완료/실패/취소 시 finally 블록에서 반드시 리소스 반환
- 글로벌 Semaphore 슬롯 반환
- 세션별 쿼리 카운트 감소 (기존 누락 수정)
- ActiveQueryManager 쿼리 정리
- TrackQueryInterceptor 세션 제한값 외부 설정화 (@Value)
- application-prod.yml에 websocket.query 설정 추가
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- GisService: 하위 구간 미집계 감지 시 상위 테이블에서 보완 집계하는
계층적 폴백 로직 추가 (daily→hourly→5min)
- ChunkedTrackStreamingService: 빈 LineString으로 인한 선박 객체 누락 방지,
MAX_TRACKS_PER_CHUNK를 500,000으로 증가
- ChunkedTrackStreamingService: 2-pass 뷰포트 필터링 구현
Pass 1에서 뷰포트 교차 선박 ID를 수집하고, Pass 2에서 해당 선박의
전체 항적을 viewport 필터 없이 조회하여 선박 소실 현상 해결
- TrackConverter: 빈 geometry에서도 선박 객체 반환하도록 수정
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add GisControllerV2/GisServiceV2 for CompactVesselTrack responses
- Add nationalCode and shipKindCode fields to REST API responses
- Add flexible DateTime parsing support (multiple formats)
- Add TrackConverter utility for track data conversion
- Update SwaggerConfig with V2 API endpoints and unified tags
- Update ProdDataSourceConfig for prod-mpr profile support
- Enhance Swagger documentation for all DTOs