- AreaSearch/VesselContact 동시성·메모리 관리 통합 (ActiveQueryManager + MemoryBudget)
- 순차 통과 SQL 동적 N-구역(2~10) 확장
- 성능 최적화: ArrayList 사전 할당, Coordinate 재사용, equirectangular 근사
- 3개 API에 chnPrmShipOnly 파라미터 추가 (~1,400 MMSI 필터링)
- 대시보드 DataPipeline 차트 개선
- parseTimestamp 실패 로깅 추가 (AreaSearchService)
- isNightTimeContact 야간 판정 로직 단순화 (VesselContactService)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase A: 버그 수정
- isQueryCancelled: queryCancelFlags 전체 순회 → queryId 직접 조회 (O(n)→O(1))
한 쿼리 취소 시 서버 전체 쿼리 조기 종료되던 치명적 버그 해결
- QueryContext 내부 클래스 추출: 싱글턴 인스턴스 변수 5개를 쿼리별 로컬로 전환
동시 쿼리 간 상태 교차 오염 원천 차단
- 대기열 타임아웃: 하드코딩 120초 → ActiveQueryManager 설정값 사용
Phase B: 쿼리 메트릭 DB 저장
- QueryMetricsService: signal.t_query_metrics 비동기 INSERT
- QueryMetricsController: GET /api/monitoring/query-metrics, /stats
- streamChunkedTracks finally 블록에서 자동 저장 (QueryBenchmark 데이터 연동)
Phase C: N+1 해소 + 데드코드 제거
- VesselInfo 배치 프리로드: viewportVesselIds 수집 후 1회 배치 조회
- 미사용 코드 ~400줄 삭제: simplificationStrategy, executorService, processQueryInChunks,
batchGetVesselInfo, processChunk, selectTableByTimeRange, groupRangesByDate 등
Phase D: 코드 품질
- WKTReader: 싱글턴 공유 → ThreadLocal (스레드 안전성)
- avgSpeed 계산: 4곳 중복 → calculateAvgSpeed() 헬퍼 추출
2,984줄 → 2,575줄 (409줄 삭감)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- SignalKindCode 매핑 변경: aton→DEFAULT, tug/tender→DEFAULT,
Vessel+towing/dredging/diving→DEFAULT, Vessel+leisure→DEFAULT
- shipName 기반 BUOY 검출: '.' '_' 문자 2개 이상 → BUOY
- 캐시 저장 시 1회 치환, API 응답 시 DB/캐시 값 직접 사용
- 응답 경로 6곳 resolve() 재계산 제거
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 1: L1/L2/L3 캐시 키 기반 직접 O(1) 조회 (전체 스캔 대체)
Phase 2: 64GB JVM 메모리 예산 논리적 파티셔닝 (캐시 35GB/쿼리 20GB)
Phase 3: L2 HourlyTrackCache 6시간 경과 엔트리 Nth-point 간소화
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- application.yml: gzip 압축 활성화 (1KB 이상 JSON 자동 압축, 70~85% 감소)
- JacksonConfig: NON_NULL 전역 설정 (null 필드 직렬화 제거, 5~15% 감소)
- VesselPositionService: sog/cog 소수점 1자리, lon/lat 6자리 제한 (3~5% 감소)
- MapTileController: @Tag, @Operation, @Parameter Swagger 문서 추가
- LockMonitorController: @Tag, @Operation Swagger 문서 추가
- BatchAdminController daily-stats: @ApiResponse 응답 스키마 예시 추가
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PostGIS ST_AsText()는 "LINESTRING M (...)" (공백 포함) 반환하지만
Java 코드는 "LINESTRING M(...)" (공백 없음) 형식만 매칭하여
앱 재시작 후 DB fallback/warmup 데이터가 전량 필터되는 버그 수정.
- DB 읽기 시 WKT 정규화 (CacheWarmup, CacheBasedReader 4곳)
- merge processor regex에 \s* 방어적 처리 (Daily/Hourly)
- countWktPoints indexOf('(') 기반으로 개선
- BatchAdmin: dailyJob 수동 실행 시 timeBucket 파라미터 추가
- DataPipeline: L3 표시를 cachedDays → totalVessels로 변경
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hourly Job에 적용된 캐시 기반 병합 패턴을 Daily Job에 동일 적용:
- CacheBasedDailyTrackReader: L2(HourlyTrackCache)에서 읽기 + DB fallback
- DailyTrackMergeProcessor: Java 인메모리 WKT 병합 + 통계 집계
- 비정상 검출: MMSI별 개별 쿼리 → 1회 bulk prefetch
- SQL ~20,000건 → ~3건 (99.98% 감소), 24분 → 30~60초 예상
삭제: DailyTrackProcessor, DailyTrackProcessorWithAbnormalDetection,
BaseTrackProcessorWithAbnormalDetection (N+1 SQL 프로세서)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ShipImageService @PostConstruct로 85K IMO 인메모리 캐시 로드
- RecentVesselPositionDto에 shipImagePath, shipImageCount 필드 추가
- VesselPositionService에서 imo 기반 O(1) lookup으로 사진 정보 주입
- ShipImageRepository에 이미지 수 포함 쿼리 추가
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- RecentVesselPositionDto에 imo 필드 추가 (0이면 null 처리)
- GET /api/v2/shipimg/valid-list: 선박사진 보유 IMO 전체 목록 + 썸네일 경로
- 초기 로딩 시 선박 썸네일 즉시 표시 용도 (85K+ IMO)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- DateTimeParseUtil: zdt.toLocalDateTime() → withZoneSameInstant(systemDefault) 변환
클라이언트 UTC 시각("Z" 접미사)이 KST로 변환되지 않아 9시간 밀리는 버그 수정
- GisServiceV2 queryWithCache: Daily 캐시 HIT 후 요청 MMSI 미존재 시
DB fallback(hourly/5min 계층 조회) 추가
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GET /api/v2/vessels/chnprmship/recent-positions?minutes=60
ChnPrmShipCacheManager에서 지정 시간 내 신호 수신된 선박 조회.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
L1/L2 캐시에 다른 선박 데이터가 있어 HIT로 판정되지만
요청한 MMSI가 캐시에 없을 때 DB fallback이 누락되는 버그 수정.
filterByMmsi() 후 누락된 MMSI에 대해 부분 DB fallback 실행.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- t_chnprmship_positions 월별 파티션 테이블 (PartitionManager 관리)
- ChnPrmShipPositionSyncStep: 5분 Job 편승 캐시→DB 이중 적재
- ChnPrmShip 캐시 TTL 2→7일, 워밍업 소스 전용 DB + t_ais_position 이중화
- tracks/vessels API: includeChnPrmShip=true 시 ChnPrmShipInfo enrichment
- ShipImageControllerV2: /api/v2/shipimg/{imo} 추가
- SwaggerConfig: V2 경로 분리 + shipimg V2 그룹 추가
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- SwaggerConfig: 서버 URL을 현행 환경(192.168.1.18:18090)으로 업데이트
- AbnormalTrackResponse: 13개 필드에 @Schema 어노테이션 추가
- AbnormalTrackStatsResponse: 7개 필드에 @Schema 어노테이션 추가
- GisController V1: minutes 파라미터 4곳에 @Parameter 추가
- BatchAdminController: step/details 엔드포인트에 @Operation 추가
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
application-prod.yml의 five-min-track/hourly-track가 app.ais-api 아래에
잘못 중첩되어 적용되지 않았음. application.yml의 app.cache 아래가 실제
@Value가 읽는 경로이므로 해당 파일을 수정.
- L1: 700K→1.5M, L2: 1.4M→3.5M (application.yml)
- application-prod.yml: 잘못된 중첩 제거
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>
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>
- 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>