release: 2026-03-31 (39건 커밋) #210

병합
htlee develop 에서 main 로 39 commits 를 머지했습니다 2026-03-31 10:12:10 +09:00
소유자

[2026-03-31]

추가

  • 어구 연관성 멀티모델 폴리곤 오버레이 + 토글 패널
  • deck.gl + Zustand 리플레이 전환 (TripsLayer GPU)
  • 재생 컨트롤 확장: 항적/이름/일치율/개별 on-off
  • 트랙 API 전체 모델 확장
  • 모델별 폴리곤 중심 경로 + 중심점

변경

  • FleetClusterLayer 10파일 리팩토링
  • 리플레이: MapLibre → deck.gl (re-render 0회)

수정

  • identity 레이어 항상 ON + 최상위
  • Prediction API DB/proxy 수정

기타

  • CI/CD: Prediction 수동 배포 전환
  • zustand, deck.gl/geo-layers 추가
## [2026-03-31] ### 추가 - 어구 연관성 멀티모델 폴리곤 오버레이 + 토글 패널 - deck.gl + Zustand 리플레이 전환 (TripsLayer GPU) - 재생 컨트롤 확장: 항적/이름/일치율/개별 on-off - 트랙 API 전체 모델 확장 - 모델별 폴리곤 중심 경로 + 중심점 ### 변경 - FleetClusterLayer 10파일 리팩토링 - 리플레이: MapLibre → deck.gl (re-render 0회) ### 수정 - identity 레이어 항상 ON + 최상위 - Prediction API DB/proxy 수정 ### 기타 - CI/CD: Prediction 수동 배포 전환 - zustand, deck.gl/geo-layers 추가
htlee added 39 commits 2026-03-31 10:11:48 +09:00
- CoordDebugTool: Ctrl+Click 다중 좌표 표시 (DD/DMS, WGS84)
- import.meta.env.DEV 가드로 프로덕션 빌드에서 코드 제거
- CLAUDE.md: 디버그 도구 가이드 섹션 추가
- lazy + 동적 import로 DEV에서만 청크 로드
- mapRef 기반 이벤트 등록으로 KoreaMap 코드에 디버그 흔적 없음
- 이전 CoordDebugTool/useCoordDebug 삭제
- debug/index.tsx: 모든 디버그 도구 조합 export
- KoreaMap: lazy import 1줄 + JSX 1줄만 유지
- 디버그 도구 추가/제거 시 debug/index.tsx만 수정
- fillGapFrames: API 응답 로드 시 빈 구간 보간 프레임 삽입
  - gap ≤ 30분: 5분 간격 직선 보간 (중심만, 폴리곤 유지)
  - gap > 30분: 30분 간격 멤버 위치 보간 + convex hull 가상 폴리곤
- _interp/_longGap 플래그로 원본/보간/장기gap 프레임 구분
- 빨간 중심 포인트: 현재 재생 시점 위치 표시
- 가상 구간 회색 렌더링 (폴리곤/아이콘/라벨)
- 중심선: 실데이터 노란색 + 장기gap 주황색 파선
- 재생바: 원본 데이터만 표시 (보간 프레임 제외)
- buildInterpPolygon: Python polygon_builder.py 동일 로직
- gear_correlation.py: 적응형 EMA + freeze + shadow + 배치 최적화
- 5개 글로벌 모델 병렬 추적 (default/aggressive/conservative/proximity-heavy/visit-pattern)
- 어구 중심 점수 체계: 어구 비활성 시 FREEZE, 선박 shadow 추적
- 유형별 메트릭: 어구-선박(proximity+visit+activity), 선박-선박(DTW+SOG+COG)
- DB: correlation_param_models + raw_metrics(일별 파티션) + scores + system_config
- partition_manager: 일별 파티션 생성/정리 (system_config hot-reload)
- track_similarity: SOG상관 + COG동조 + 근접비 3개 메트릭 추가
- scheduler Step 4.7 통합, fleet_tracker MMSI 점수 이전
- chat/tools: query_gear_correlation 도구

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Backend: GET /api/vessel-analysis/groups/{groupKey}/correlations 엔드포인트
- GroupPolygonService: gear_correlation_scores JOIN correlation_param_models 쿼리
- Frontend: fetchGroupCorrelations API 클라이언트 + GearCorrelationItem 타입
- FleetClusterLayer: 어구 그룹 선택 시 연관 선박/어구 목록 팝업에 표시
  - default 모델 기준 일치율 % + 바 그래프
  - 선박(⛴)/어구(◆) 유형 구분, 상위 8건 표시

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
scores 테이블에는 composite 점수만, 세부 메트릭(proximity/visit/heading)은
raw_metrics에 있으므로 LATERAL JOIN으로 최신 raw 메트릭 결합

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 어구 그룹 선택 시 전체 모델(5개) 연관성 데이터 로드
- enabledModels 상태: 'identity'(이름 기반) + 'default' 기본 ON
- 모델별 오퍼레이셔널 폴리곤 클라이언트 생성 (70%+ 연관 대상 합산 convex hull)
- Source+Layer 오버레이: 모델별 고유 색상, 대시 라인 구분
- 팝업 UI: 모델 토글 체크박스 (최대 5개), 색상 인디케이터 + 70%+ 대상 수
- 연관 선박 상위 8건 바 그래프 (default 모델 기준)
- 선택 시 팝업 maxWidth 280px로 확장

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
호버 팝업은 마우스 이동 시 사라져서 토글 조작 불가 →
어구 그룹 선택 시 하단 중앙에 고정 패널 배치:
- 좌측: 그룹 정보 + 폴리곤 오버레이 토글 (이름 기반 + 5개 모델)
- 우측: 연관 선박 목록 (default 모델 상위 12건, 스크롤)
- ✕ 버튼으로 선택 해제
- 히스토리 재생 컨트롤러와 동일 위치/스타일

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- !historyData 조건 제거 — 어구 클릭 시 히스토리 자동 로딩되므로 항상 표시
- 히스토리 모드: bottom 80px (재생 컨트롤러 위), 비히스토리: bottom 20px
- z-index 21 (재생 컨트롤러 20 위)
- 오퍼레이셔널 폴리곤/이름 기반 하이라이트도 히스토리 조건 조정

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FleetClusterLayer.tsx 2357줄 → 10개 파일 분리:
- fleetClusterTypes/Utils/Constants: 타입, 기하 함수, 모델 상수
- useFleetClusterGeoJson: 27개 useMemo GeoJSON 훅
- FleetClusterMapLayers: MapLibre Source/Layer JSX
- CorrelationPanel/HistoryReplayController: 패널 서브컴포넌트
- GearGroupSection/FleetGearListPanel: 좌측 목록 (DRY)
- FleetClusterLayer: 오케스트레이터 524줄

deck.gl + Zustand 리플레이 기반 (Phase 0~2):
- zustand 5.0.12, @deck.gl/geo-layers 9.2.11 설치
- gearReplayStore: Zustand + rAF 애니메이션 루프
- gearReplayPreprocess: TripsLayer 전처리 + cursor O(1) 보간
- useGearReplayLayers: deck.gl 레이어 빌더 (10fps 스로틀)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 3: DeckGLOverlay에 overlayRef 추가, KoreaMap에서
리플레이 레이어 합성 (imperative setProps → React 렌더 우회)

Phase 4: 기존 MapLibre 리플레이 레이어 → deck.gl 전환
- FleetClusterLayer: 애니메이션 state/ref/timer 제거 → Zustand 스토어
- useFleetClusterGeoJson: 리플레이 useMemo 15개 제거 (618→389줄)
- FleetClusterMapLayers: MapLibre 재생 레이어 6개 제거 (492→397줄)
- HistoryReplayController: React refs → Zustand subscribe 바인딩

성능: React re-render 20회/초 → 0회/초 (재생 중)
      GeoJSON 직렬화 15개/프레임 → 0 (raw 배열 → deck.gl)
      트레일: 매 프레임 재생성 → TripsLayer GPU 셰이더

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CorrelationPanel: historyData prop 제거 → useGearReplayStore 직접 구독
재생 활성 시 bottom: 80→100 (컨트롤러 높이 60px 확보)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ScatterplotLayer → IconLayer (ship-triangle/gear-diamond SVG 정적 캐시)
- shipIconSvg.ts: MapLibre와 동일한 삼각형/마름모 SVG + mask 모드
- 선박 COG 회전 반영 (getAngle), 어구는 회전 없음
- 모델별 색상 배지 ScatterplotLayer 추가 (각 모델 offset)
- correlation 데이터 비동기 로드 후 store.updateCorrelation() 동기화
- CorrPosition에 cog 필드 추가 (세그먼트 방향 계산)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- loadHistory 완료 후 store.play() 호출 (자동 재생)
- correlation sync effect에 historyActive 의존 추가
  (history 로드 후 이미 도착한 correlation 데이터 재동기화)
- loadHistory 직후 즉시 updateCorrelation 호출 (병렬 로드 대응)
- 디버그 로그: renderFrame 첫 프레임 데이터 상태, correlationByModel 갱신

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
데이터 로딩:
- loadHistory: Promise.all로 history/correlation/tracks 병렬 fetch
  → 모든 응답 완료 후 store.loadHistory + play() 순차 실행
- 개별 fetch effect는 비재생 모드에서만 실행 (historyActive 가드)
- 타이밍 문제 원천 제거 (race condition 없음)

enabledModels 토글 제어:
- identity OFF → 멤버 폴리곤/마커/트레일 숨김
- 각 모델 OFF → 해당 모델의 연관 선박/트레일 숨김
- 모든 모델 OFF → 센터 트레일/점만 표시
- correlation trails도 활성 모델에 속하는 선박만 표시

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- useGearReplayLayers에 shipsRef 파라미터 추가
- corrPositions 계산: 트랙 보간 우선 → live 선박 위치 fallback
- KoreaMap: allShips → shipsRef에 매 렌더 동기화 (ref로 re-render 방지)
- globalThis.Map으로 react-map-gl Map 타입 충돌 해결

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prediction API:
- /correlation/{group}/tracks: is_default=TRUE 제거 → 모든 활성 모델 조회
- 응답에 models: {modelName: score} 딕셔너리 추가 (모델별 점수)
- MMSI 기준 중복 제거, 최고 점수 유지

Frontend:
- CorrelationVesselTrack 타입: models 필드 추가, type 필드 추가
- 오퍼레이셔널 폴리곤: enabledVessels 기반 on/off 제어
  (score 임계값 → 개별 체크박스 토글로 전환)
- identity OFF 시 폴리곤 base points에서 멤버 위치 제외

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 트랙 시간 범위 밖: 가장 가까운 끝점으로 clamp (기존: skip)
  → 트랙 시작 전 = 첫 점, 트랙 종료 후 = 마지막 점
- 디버그 로그: corrPositions 상세 (track/live 소스별, 모델별 위치확인 수)
- 기존 중복 로그 정리

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- kcgdb.get_conn()을 with문 없이 사용 → cursor 에러
- with kcgdb.get_conn() as conn: 으로 수정
- 디버그 로그 추가 (rows 수, track 매칭 수, vessel_store 크기)
- 결과: 47 vessels, 47 with track data (25567#1 그룹)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
/api/prediction → rewrite: '' → '/api'
기존: /api/prediction/v1/... → /v1/... (404 - FastAPI 라우트 불일치)
수정: /api/prediction/v1/... → /api/v1/... (정상 매칭)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
vite dev: /api/prediction/ → 192.168.1.18:8001 (rewrite /api/prediction → /api)
nginx 프로덕션: /api/prediction/ → redis-211:8001 (동일 rewrite)
디버그 로그: fetchCorrelationTracks URL/status, loadHistory fetch 결과

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
재생 컨트롤러:
- 항적 on/off → showTrails (TripsLayer + PathLayer + 센터도트)
- 이름 on/off → showLabels (TextLayer)
- 일치율 드롭다운 (50~90%) → enabledVessels 일괄 필터

패널 토글:
- 행 전체 클릭으로 체크박스 토글 (cursor: pointer)
- 체크박스 항상 표시, OFF 시 opacity 0.5
- correlationTracks prop 제거 (미사용)

enabledVessels OFF 효과:
- corrPositions 제외 → 아이콘/라벨/트레일/폴리곤 모두 제외

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
항적 토글 역할 변경:
- 항상 ON: TripsLayer (애니메이션 트레일) + 센터 트레일 + 도트
- "항적" 토글: 전체 24h 정적 항적 PathLayer (멤버 + 연관 선박)
  ON 시 회색/연파랑 배경 경로 위에 고채도 TripsLayer 애니메이션

색상 계층:
- 정적 항적: 회색 [180,180,180,80] / 연파랑 [100,140,200,60]
- TripsLayer: 고채도 노랑 [255,200,60,220] / 고채도 파랑 [100,180,255,220]

패널 레이아웃:
- 토글 패널: position: sticky left: 0 (항상 좌측 고정)
- 모델 카드: 가로 스크롤 (maxWidth: calc(100vw - 340px))
- 다중 토글 유지, 화면 초과 시 스크롤

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
패널 위치:
- left: 10 → left: calc(50% - 210px) (재생 컨트롤러 중앙 정렬 근처)

일치율 드롭다운 전역 적용:
- 기존: 현재 ON인 모델의 대상만 필터
- 수정: 모든 모델의 모든 대상에 전역 적용 (모델 on/off 무관)
- 동일 MMSI가 여러 모델에 있을 때 최고 score 기준 판단

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bottom: 100 → 120 (재생 활성 시)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
사전계산 (gearReplayPreprocess):
- buildModelCenterTrails(): 각 프레임에서 멤버+연관선박 위치 → 폴리곤 → 중심점
- 모델별 path[]/timestamps[] (PathLayer + 보간용)

스토어 (gearReplayStore):
- modelCenterTrails 필드 추가 (loadHistory/updateCorrelation에서 빌드)

렌더링 (useGearReplayLayers):
- PathLayer: 모델별 폴리곤 중심 경로 (연한 모델 색상, alpha 100)
- ScatterplotLayer: 현재 시간 중심점 (고채도 모델 색상, 흰 테두리)
- 모델 ON 시에만 표시 (enabledModels 체크)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- setEnabledVessels: rawCorrelationTracks로 modelCenterTrails 재빌드
- rawCorrelationTracks 필드 추가 (원본 트랙 보존)
- 선박/어구 on/off → 폴리곤 + 중심경로 + 중심점 동시 갱신

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
prediction/ 변경 시 ssh redis-211으로 수동 scp + restart
CI/CD는 Frontend + Backend만 자동 배포

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
이름 토글 ON 시 각 모델 폴리곤 중심점 위에 모델명 TextLayer 표시
모델 색상 + 검정 배경, 중심점 위 12px offset

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CorrelationPanel:
- identity 체크박스 disabled + '(고정)' 표시
- on/off 토글 불가

useGearReplayLayers z-index 재배치:
1. 정적 항적 PathLayer (배경)
2. Correlation TripsLayer + 아이콘/라벨
3. 모델별 폴리곤 + 중심경로/중심점 + 배지
4. Identity 폴리곤 + TripsLayer + 센터포인트 (최상위)
  → 다른 모델 레이어가 identity 구역을 가리지 않음

모든 enabledModels.has('identity') 체크 제거 (항상 true)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
claude-bot 이 변경사항을 승인하였습니다. 2026-03-31 10:12:08 +09:00
claude-bot left a comment
멤버

릴리즈 승인 (via /release skill)

릴리즈 승인 (via /release skill)
htlee merged commit 93ce2092d2 into main 2026-03-31 10:12:10 +09:00
"로그인하여 이 대화에 참여"
No reviewers
레이블 없음
마일스톤 없음
담당자 없음
참여자 2명
알림
마감일
기한이 올바르지 않거나 범위를 벗어났습니다. 'yyyy-mm-dd'형식을 사용해주십시오.

마감일이 설정되지 않았습니다.

의존성

No dependencies set.

Reference: gc/kcg-monitoring#210
No description provided.