커밋 그래프

339 커밋

작성자 SHA1 메시지 날짜
5c85afea22 docs: 릴리즈 노트 업데이트 (1h 활성 판정 수정)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 16:47:22 +09:00
b04e96c457 fix: 1h 활성 판정을 parent_name 전체 합산 기준으로 변경
서브클러스터 분리 후 개별 서브그룹의 1h 멤버가 2개 미만이더라도,
parent_name 전체(모든 서브클러스터 합산)에서 1h 활성 멤버 >= 2이면
resolution='1h'로 저장하여 라이브 현황에 표시.

결과: 라이브 1h 그룹 5개 → 927개 정상 복구

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 16:47:01 +09:00
b320aeb3fd Merge pull request 'docs: 릴리즈 노트 정리 (2026-04-01.2)' (#217) from release/2026-04-01.2 into develop 2026-04-01 15:04:51 +09:00
e9cbeaa0d8 docs: 릴리즈 노트 정리 (2026-04-01.2) 2026-04-01 15:04:34 +09:00
acef08fca9 Merge pull request 'fix: 라이브 어구 현황 fallback 제외 + FLEET resolution' (#216) from bugfix/fleet-resolution-fix into develop 2026-04-01 15:03:11 +09:00
d44837e64a Merge pull request 'feat: 한국 현황 위성지도/ENC 토글 + ENC 스타일 설정' (#215) from feature/enc-map-toggle into develop 2026-04-01 15:02:56 +09:00
fc6f696d1f fix: 라이브 어구 현황 fallback 제외 + FLEET resolution + DB VARCHAR(8)
- 1h 실제 활성 멤버 < 2일 때 resolution='1h-fb' (fallback)로 저장
- LATEST_GROUPS_SQL은 resolution='1h'만 필터 → fallback 자동 제외
- FLEET 타입에 resolution='1h' 추가 (이전 누락)
- DB resolution 컬럼: VARCHAR(4) → VARCHAR(8) 확장
- 프론트 리플레이: '1h' + '1h-fb' 모두 1h 프레임으로 처리

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 15:00:16 +09:00
98d173701e fix: 라이브 어구 현황에서 fallback 그룹 제외
- 1h 실제 활성 멤버 < 2일 때 resolution='1h-fb' (fallback)로 저장
- LATEST_GROUPS_SQL은 resolution='1h'만 필터 → fallback 자동 제외
- 리플레이 history API는 1h-fb 포함 (리플레이/일치율 추적 유지)
- 프론트 리플레이: '1h' + '1h-fb' 모두 1h 프레임으로 처리

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:22:59 +09:00
a7eb706839 fix: FLEET 타입에 resolution='1h' 누락 — 라이브 현황 API에서 선단 그룹 미표시
FLEET 스냅샷에 resolution 필드를 설정하지 않아 DB default '6h'로 저장됨.
LATEST_GROUPS_SQL이 resolution='1h' 필터를 사용하므로 FLEET 전부 누락.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:17:27 +09:00
650c027013 feat: 한국 현황 위성지도/ENC 토글 + ENC 스타일 설정
- ENC 전자해도: gcnautical 벡터 타일 연동 (gc-wing-dev 이식)
- 상단 위성/ENC 토글 버튼 + ⚙ 드롭다운 설정 패널
- 12개 심볼 토글 + 8개 색상 수정 + 초기화
- mapMode/encSettings localStorage 영속화
- style.load 대기 패턴으로 스타일 전환 시 설정 자동 적용

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:08:41 +09:00
71a2188273 Merge pull request 'docs: 릴리즈 노트 정리 (2026-04-01)' (#213) from release/2026-04-01 into develop 2026-04-01 12:35:53 +09:00
138a1b82de docs: 릴리즈 노트 정리 (2026-04-01) 2026-04-01 12:35:26 +09:00
c59b38f913 Merge pull request 'feat: 어구 1h/6h 듀얼 폴리곤 + 리플레이 컨트롤러 개선 + 심볼 스케일' (#212) from feature/gear-replay-cleanup into develop 2026-04-01 12:33:00 +09:00
9200f45cb2 docs: 릴리즈 노트 업데이트 2026-04-01 12:32:08 +09:00
77efab8652 feat: 항공기 줌 스케일 + 선박/항공기 심볼 크기 조정 패널
- 항공기 아이콘에 정수레벨 줌 기반 스케일 적용 (getZoomScale export)
- 심볼 크기 조정: SymbolScaleContext + SymbolScalePanel (0.5~2.0x)
- LayerPanel에 '심볼 크기' 섹션 추가 (선박/항공기 개별 조정)
- localStorage 영속화 (mapSymbolScale)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 12:29:22 +09:00
71d607e499 feat: 어구 그룹 1h/6h 듀얼 폴리곤 + 리플레이 컨트롤러 개선
- Python: 1h/6h 듀얼 스냅샷 생성 (polygon_builder), 1h 멤버 기반 일치율 후보 (gear_correlation)
- DB: resolution 컬럼 추가 (011_polygon_resolution.sql)
- Backend: resolution 필드 지원 (DTO/Service/Controller)
- Frontend: 6h identity 레이어 독립 구현 (폴리곤/아이콘/라벨/항적/센터)
- 리플레이 컨트롤러: 프로그레스바 통합, 1h/6h 스냅샷 표시, A-B 구간 반복
- 리치 툴팁: 클릭 고정 + 멤버 호버 강조 + 선박/어구/모델 소속 표시

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 11:52:38 +09:00
f09186a187 feat: 어구 리플레이 서브클러스터 분리 렌더링 + 일치율 감쇠 개선
- 서브클러스터별 독립 폴리곤/센터/center trail 렌더링
- 반경 밖 이탈 선박 강제 감쇠 (OUT_OF_RANGE)
- Backend correlation API에 sub_cluster_id 추가
- 모델 패널 5개 항상 표시, 드롭다운 기본값 70%
- DISPLAY_STALE_SEC (time_bucket 기반) 폴리곤 노출 필터
- AIS 수집 bbox 122~132E/31~39N 확장
- historyActive 시 deck.gl 이중 렌더링 수정

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 09:01:03 +09:00
ce4cde56b8 Merge pull request 'feat: MapLibre → deck.gl 전면 전환 + 어구 서브클러스터 구조 개선' (#211) from feature/deckgl-ship-migration into develop 2026-03-31 15:59:06 +09:00
6f8e8cb6cc docs: 릴리즈 노트 업데이트
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 15:55:58 +09:00
313b5d9af8 chore: .claude/worktrees 제거 (로컬 전용)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 15:48:16 +09:00
b0ac1590f2 Revert "docs: Backend JAR 배포 경로 정확히 명시"
This reverts commit 9eac614910.
2026-03-31 15:48:03 +09:00
9eac614910 docs: Backend JAR 배포 경로 정확히 명시
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 15:46:40 +09:00
6f4044ce39 feat: MapLibre → deck.gl 전면 전환 + 어구 서브클러스터 구조 개선
- 실시간 선박 13K: MapLibre symbol → deck.gl IconLayer (useShipDeckLayers + shipDeckStore)
- 선단/어구 폴리곤: MapLibre Source/Layer → deck.gl GeoJsonLayer (useFleetClusterDeckLayers)
- 선박 팝업: MapLibre Popup → React 오버레이 (ShipPopupOverlay + ShipHoverTooltip)
- 리플레이 집중 모드 (focusMode), 라벨 클러스터링, fontScale 연동
- Python: group_key 고정 + sub_cluster_id 분리, 한국 국적 어구 오탐 제외
- DB: sub_cluster_id 컬럼 추가 + 기존 '#N' 데이터 마이그레이션
- Backend: DISTINCT ON CTE로 서브클러스터 중복 제거, subClusterId DTO 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 15:44:09 +09:00
1b14aacd89 Merge pull request 'docs: 릴리즈 노트 정리 (2026-03-31)' (#209) from release/2026-03-31 into develop 2026-03-31 10:11:33 +09:00
b88c9c28ee docs: 릴리즈 노트 정리 (2026-03-31) 2026-03-31 10:11:05 +09:00
b14df41da7 Merge pull request 'fix: 이름 기반 레이어 항상 ON + 최상위 z-index' (#208) from feature/identity-layer-fix into develop 2026-03-31 10:09:41 +09:00
867ece0a39 docs: 릴리즈 노트 업데이트 2026-03-31 10:08:46 +09:00
9f3d53d2e8 fix: 이름 기반 레이어 항상 ON + 최상위 z-index
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>
2026-03-31 10:08:09 +09:00
588e61c941 Merge pull request 'feat: 어구 연관성 멀티모델 + deck.gl 리플레이 전환' (#207) from feature/gear-correlation-tracking into develop 2026-03-31 10:04:08 +09:00
7e8a5bb39a docs: 릴리즈 노트 업데이트 2026-03-31 10:03:21 +09:00
30f1956ca6 feat: 모델 중심점에 모델명 라벨 표시 (showLabels 연동)
이름 토글 ON 시 각 모델 폴리곤 중심점 위에 모델명 TextLayer 표시
모델 색상 + 검정 배경, 중심점 위 12px offset

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 10:01:15 +09:00
89b81bc241 ci: Prediction 자동 배포 제거 — 수동 배포로 전환
prediction/ 변경 시 ssh redis-211으로 수동 scp + restart
CI/CD는 Frontend + Backend만 자동 배포

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 09:59:33 +09:00
bf412cc897 fix: enabledVessels 토글 시 모델 중심 경로 재계산
- setEnabledVessels: rawCorrelationTracks로 modelCenterTrails 재빌드
- rawCorrelationTracks 필드 추가 (원본 트랙 보존)
- 선박/어구 on/off → 폴리곤 + 중심경로 + 중심점 동시 갱신

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 09:56:46 +09:00
c97f964f93 feat: 모델별 폴리곤 중심 경로 + 현재 중심점 렌더링
사전계산 (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>
2026-03-31 09:52:17 +09:00
5afa5d4be9 fix: 모델 패널 위치 상향 — 확장된 재생 컨트롤러와 겹침 해소
bottom: 100 → 120 (재생 활성 시)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 09:45:36 +09:00
e8187b3a6c fix: 토글 패널 위치 재생 컨트롤러 정렬 + 일치율 필터 전역 적용
패널 위치:
- left: 10 → left: calc(50% - 210px) (재생 컨트롤러 중앙 정렬 근처)

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

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 09:44:15 +09:00
6789f82e3b fix: 항적 토글 + 패널 레이아웃 + TripsLayer 색상 분리
항적 토글 역할 변경:
- 항상 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>
2026-03-31 09:40:06 +09:00
5002105d18 feat: 재생 컨트롤 확장 — 항적/이름 토글 + 일치율 필터 + 개별 on/off
재생 컨트롤러:
- 항적 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>
2026-03-31 09:26:41 +09:00
21df325010 fix: prediction API 프록시 경로 수정 + nginx 라우팅 추가
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>
2026-03-31 09:13:52 +09:00
dddb978dea fix: prediction proxy rewrite 경로 수정
/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>
2026-03-31 09:07:33 +09:00
8631546142 fix: 트랙 API DB 접속 버그 수정 (context manager)
- 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>
2026-03-31 09:03:33 +09:00
6ea394d120 fix: 트랙 끝점 clamp + 연관 선박 위치 디버그 강화
- 트랙 시간 범위 밖: 가장 가까운 끝점으로 clamp (기존: skip)
  → 트랙 시작 전 = 첫 점, 트랙 종료 후 = 마지막 점
- 디버그 로그: corrPositions 상세 (track/live 소스별, 모델별 위치확인 수)
- 기존 중복 로그 정리

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 08:55:00 +09:00
8eacbb2c91 feat: 트랙 API 전체 모델 확장 + 개별 선박 on/off → 폴리곤 반영
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>
2026-03-31 08:40:31 +09:00
c4186a327d fix: 연관 선박 위치 live fallback — 트랙 데이터 없을 때 ships 배열 사용
- 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>
2026-03-31 08:26:07 +09:00
6ba3db5cee fix: 순차 데이터 로딩 + enabledModels 토글 제어
데이터 로딩:
- 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>
2026-03-31 08:17:53 +09:00
e68f314093 fix: correlation 동기화 타이밍 수정 + 자동 재생 + 디버그 로그
- 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>
2026-03-31 08:13:52 +09:00
242fdb8034 fix: 리플레이 IconLayer 전환 + 모델 배지 + correlation 동기화
- 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>
2026-03-31 08:08:39 +09:00
4cf29521a9 fix: 모델 패널 위치 상향 — 재생 컨트롤러와 겹침 해소
CorrelationPanel: historyData prop 제거 → useGearReplayStore 직접 구독
재생 활성 시 bottom: 80→100 (컨트롤러 높이 60px 확보)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 08:01:23 +09:00
87d1b31ef3 feat: 어구 리플레이 deck.gl + Zustand 전환 완료
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>
2026-03-31 07:54:50 +09:00
bbbc326e38 refactor: FleetClusterLayer 10파일 분리 + deck.gl 리플레이 기반 구축
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>
2026-03-31 07:44:07 +09:00