perf: 렌더링 성능 최적화 + 환적 Python 이관 + 중국어선감시 통합 #158

병합
htlee perf/rendering-optimization 에서 develop 로 9 commits 를 머지했습니다 2026-03-23 13:16:25 +09:00
소유자

변경 사항

성능 최적화

  • deck.gl updateTriggers 적용: 줌 변경 시 레이어 accessor 재평가 최소화 (정적 4개 sub-hook + 분석 + KoreaMap 인라인)
  • 선박 카테고리/국적 토글: JS-level 13K 배열 필터링 → MapLibre GPU-side filter 표현식 (GeoJSON 재생성 제거)
  • Ship.mtCategory/natGroup 사전 계산: getMarineTrafficCategory() 13K×N회 호출 → Set.has() O(1)
  • LIVE 모드 currentTime 의존성 분리: 매초 propagateShips(13K) + 하위 useMemo 연쇄 재실행 제거
  • 분석 레이어 데이터/스타일 useMemo 분리 + SVG 모듈 캐싱

환적탐지 Python 이관 (cross-stack)

  • prediction/algorithms/transshipment.py: 그리드 공간인덱스 O(n log n)
  • DB 마이그레이션 + Backend DTO + Frontend 소비 전환
  • 프론트엔드 O(n²)/초 → 서버사이드 5분 주기

기능 개선

  • 중국어선감시 KoreaFilters 통합 (다른 감시 탭과 동일 레벨)
  • 필터 배지 클릭 → 선박 목록 패널 + CSV 다운로드
  • 비허가 어구 그룹 2개 이상만 탐지
  • 필터별 개별 탐지 카운트
  • 헤더 1행 배치

테스트

  • 한국 탭: 선박 카테고리 토글 지연 없음 확인
  • 한국 탭: 불법어선/다크베셀 등 필터 시 해당 선박만 표시
  • 중국어선감시 탭: 어구그룹 표시 + 비관련 선박 비활성화
  • 배지 클릭 → 목록/CSV 정상 동작
  • 줌 인/아웃 시 아이콘 크기 정상 변동
  • 이란 탭: 헤더 LIVE/지도모드 1행 배치
## 변경 사항 ### 성능 최적화 - deck.gl `updateTriggers` 적용: 줌 변경 시 레이어 accessor 재평가 최소화 (정적 4개 sub-hook + 분석 + KoreaMap 인라인) - 선박 카테고리/국적 토글: JS-level 13K 배열 필터링 → MapLibre GPU-side `filter` 표현식 (GeoJSON 재생성 제거) - `Ship.mtCategory/natGroup` 사전 계산: `getMarineTrafficCategory()` 13K×N회 호출 → `Set.has()` O(1) - LIVE 모드 `currentTime` 의존성 분리: 매초 `propagateShips(13K)` + 하위 useMemo 연쇄 재실행 제거 - 분석 레이어 데이터/스타일 useMemo 분리 + SVG 모듈 캐싱 ### 환적탐지 Python 이관 (cross-stack) - `prediction/algorithms/transshipment.py`: 그리드 공간인덱스 O(n log n) - DB 마이그레이션 + Backend DTO + Frontend 소비 전환 - 프론트엔드 O(n²)/초 → 서버사이드 5분 주기 ### 기능 개선 - 중국어선감시 KoreaFilters 통합 (다른 감시 탭과 동일 레벨) - 필터 배지 클릭 → 선박 목록 패널 + CSV 다운로드 - 비허가 어구 그룹 2개 이상만 탐지 - 필터별 개별 탐지 카운트 - 헤더 1행 배치 ## 테스트 - [ ] 한국 탭: 선박 카테고리 토글 지연 없음 확인 - [ ] 한국 탭: 불법어선/다크베셀 등 필터 시 해당 선박만 표시 - [ ] 중국어선감시 탭: 어구그룹 표시 + 비관련 선박 비활성화 - [ ] 배지 클릭 → 목록/CSV 정상 동작 - [ ] 줌 인/아웃 시 아이콘 크기 정상 변동 - [ ] 이란 탭: 헤더 LIVE/지도모드 1행 배치
htlee added 9 commits 2026-03-23 13:16:00 +09:00
- deck.gl updateTriggers 적용: 정적 레이어(4개 sub-hook) + 분석 레이어 + KoreaMap 인라인 레이어
  → 줌 변경 시 accessor 재평가 최소화
- 선박 카테고리/국적 토글: JS-level 배열 필터링 → MapLibre GPU-side filter 표현식
  → 토글 시 13K GeoJSON 재생성 + GPU 재업로드 제거
- Ship.mtCategory/natGroup 사전 계산: propagateShips 후 1회 계산, 이후 Set.has() O(1)
  → getMarineTrafficCategory() 13K×N회 호출 제거
- onPick useCallback 안정화: 매 렌더마다 28개 정적 레이어 불필요 재생성 방지
- SVG 데이터 URI 모듈 레벨 캐싱: 함수 호출 간 캐시 유지
- useAnalysisDeckLayers 데이터/스타일 분리: 줌 변경 시 ships 필터링 스킵

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- prediction/algorithms/transshipment.py 신규: 그리드 공간인덱스 O(n log n) 환적 쌍 탐지
  → 후보 필터(sog<2, tanker/cargo/fishing, 외국해안 제외) + 110m 근접 + 60분 지속
- prediction/scheduler.py: 8단계 환적탐지 사이클 추가, pair_history 영속화
- prediction/models/result.py: is_transship_suspect, transship_pair_mmsi, transship_duration_min
- prediction/db/kcgdb.py: UPSERT 쿼리에 3개 컬럼 추가
- database/migration/008_transshipment.sql: ALTER TABLE 3개 컬럼 추가
- backend VesselAnalysisResult + VesselAnalysisDto: TransshipInfo 중첩 DTO 추가
- frontend types.ts: algorithms.transship 타입 추가
- frontend useKoreaFilters.ts: O(n²) 65줄 → analysisMap 소비 8줄
  → currentTime 매초 의존성 제거, proximityStartRef 제거

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- LIVE 모드: enrichedShipsRef 동일 참조 반환
  → currentTime 매초 변경 시에도 visibleShips/filteredShips/shipGeoJson 재실행 안 함
- mtCategory/natGroup: baseShipsKorea 변경 시 1회 새 배열 생성 (useState 불변성 준수)
- REPLAY 모드: propagateShips로 위치 보간 유지 (mtCategory는 spread로 상속)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- liveShips: baseShipsKorea 변경(5분 polling) 시에만 계산. currentTime 의존성 없음.
- replayShips: REPLAY 모드에서만 currentTime으로 위치 보간.
- LIVE 모드: 매초 useMemo 실행 자체가 발생하지 않음.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- anyKoreaFilterOn 시 filteredShips(필터 결과) 전달, 비활성 시 allShips(전체) 전달
- 상단 배너: 합산 "N척 탐지" → 필터별 개별 카운트 (불법어선 3척, 다크베셀 5척 등)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- cnFishing을 KoreaFilters 인터페이스에 통합 (koreaLayers → koreaFilters)
  → 다른 필터 탭과 동일한 선박 비활성화/상단 배지/카운트 동작
- 상단 필터 배지 클릭 → 대상 선박 목록 패널 (MMSI/이름/국적/유형/속도)
  → 선박 클릭 시 flyTo, 200척까지 표시
- CSV 다운로드: BOM 포함 UTF-8, 필터별 파일명 (e.g. cnFishing_2026-03-23.csv)
- cnFishingSuspects Set 추가 (useKoreaFilters 반환값)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 헤더 mode-toggle: flex-wrap:nowrap + overflow-x:auto → 1행 가로 스크롤
- 비허가 어구 그룹: 어구 2개 이상일 때만 그룹 탐지/폴리곤 생성 (1개는 제외)
  → 조업구역내 어구 + 선단 현황은 현행 유지
- cnFishing 배지: '중국 어구그룹 감시 N개' (어구그룹 수=고유 모선명 수)
  → 어구 패턴 매칭 선박만 집계 (중국 어선 단독은 제외)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- #dashboard-header-slot: flex + justify-content:center 기본 중앙 배치
- 이란 mode-toggle-left: position:absolute left:0 → 탭 오른쪽 배치
- 한국 필터 탭: 중앙 배치 유지
- 감시 목록 Flag 빈값: '??' → '-'

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

MR 승인 (via /mr skill)

MR 승인 (via /mr skill)
htlee merged commit 2511a33444 into develop 2026-03-23 13:16:25 +09:00
htlee 삭제된 브랜치 perf/rendering-optimization 2026-03-23 13:16:25 +09:00
"로그인하여 이 대화에 참여"
No reviewers
레이블 없음
마일스톤 없음
담당자 없음
참여자 2명
알림
마감일
기한이 올바르지 않거나 범위를 벗어났습니다. 'yyyy-mm-dd'형식을 사용해주십시오.

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

의존성

No dependencies set.

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