kcg-ai-monitoring/docs/next-refactoring.md
htlee c0ce01eaf6 chore: 팀 워크플로우 기반 초기 프로젝트 구성
KCG AI 기반 불법조업 탐지·차단 플랫폼 프론트엔드.
React 19 + TypeScript 5.9 + Vite 8 + MapLibre + deck.gl + Zustand + Tailwind CSS.
SFR 20개 전체 UI 구현 완료, 백엔드 연동 대기.

- npm + Nexus 프록시 레지스트리 설정
- 팀 워크플로우 v1.6.1 부트스트랩 파일 배치
- .githooks (commit-msg, post-checkout)
- package.json name: kcg-ai-monitoring v0.1.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 14:11:29 +09:00

8.5 KiB

KCG AI Monitoring - 다음 단계 리팩토링 TODO

프론트엔드 UI 스캐폴딩 + 기반 인프라(상태관리, 지도 GPU, mock 데이터, CVA) 완료 상태. 백엔드 연동 및 운영 품질 확보를 위해 남은 항목을 순차적으로 진행한다.


1. 상태관리 도입 (Zustand 5.0) — COMPLETED

zustand 5.0.12 설치, src/stores/에 8개 독립 스토어 구현 완료.

  • vesselStore — 선박 목록, 선택, 필터
  • patrolStore — 순찰 경로/함정
  • eventStore — 탐지/경보 이벤트
  • kpiStore — KPI 메트릭, 추세
  • transferStore — 전재(환적)
  • gearStore — 어구 탐지
  • enforcementStore — 단속 이력
  • settingsStore — theme/language + localStorage 동기화, 지도 타일 자동 전환

AuthContext는 유지 (인증은 Context API가 적합, 마이그레이션 불필요로 결정)


2. API 서비스 계층 (Axios 1.14) — 구조 완성, 실제 연동 대기

현재 상태

  • src/services/에 7개 서비스 모듈 구현 (api, vessel, event, patrol, kpi, ws, index)
  • api.ts: fetch 래퍼 (apiGet, apiPost) — 향후 Axios 교체 예정
  • 각 서비스가 data/mock/ 모듈에서 mock 데이터 반환 (실제 HTTP 호출 0건)
  • ws.ts: STOMP WebSocket 스텁 존재, 미구현

남은 작업

  • axios 1.14 설치 → api.ts의 fetch 래퍼를 Axios 인스턴스로 교체
  • Axios 인터셉터:
    • Request: Authorization 헤더 자동 주입
    • Response: 401 → 로그인 리다이렉트, 500 → 에러 토스트
  • @tanstack/react-query 5.x 설치 → TanStack Query Provider 추가
  • 각 서비스의 mock 반환을 실제 API 호출로 교체
  • 로딩 스켈레톤, 에러 바운더리 공통 컴포넌트

3. 실시간 인프라 (STOMP.js + SockJS) — 스텁 구조만 존재

현재 상태

  • services/ws.tsconnectWs 스텁 함수 존재 (인터페이스 정의 완료)
  • STOMP.js, SockJS 미설치 — 실제 WebSocket 연결 없음
  • useStoreLayerSync hook으로 store→지도 실시간 파이프라인 준비 완료

남은 작업

  • @stomp/stompjs + sockjs-client 설치
  • ws.ts 스텁을 실제 STOMP 클라이언트로 구현
  • 구독 채널 설계:
    • /topic/ais-positions — 실시간 AIS 위치
    • /topic/alerts — 경보/이벤트
    • /topic/detections — 탐지 결과
    • /user/queue/notifications — 개인 알림
  • 재연결 로직 (지수 백오프)
  • store → useStoreLayerSync → 지도 마커 실시간 업데이트 연결
  • eventStore와 연동하여 알림 배너/뱃지 카운트 업데이트

4. 고급 지도 레이어 (deck.gl 9.2) — COMPLETED

deck.gl 9.2.11 + @deck.gl/mapbox 설치, MapLibre + deck.gl 인터리브 아키텍처 구현 완료.

  • BaseMap: forwardRef + memo, MapboxOverlayuseImperativeHandle로 외부 노출
  • useMapLayers: RAF 배치 레이어 업데이트, React 리렌더 0회
  • useStoreLayerSync: Zustand store.subscribe → RAF → overlay.setProps (React 우회)
  • STATIC_LAYERS: EEZ + NLL PathLayer 싱글턴 (GPU 1회 업로드)
  • createMarkerLayer: ScatterplotLayer + transitions 보간 + DataFilterExtension
  • createRadiusLayer: 반경 원 표시용 ScatterplotLayer
  • 레거시 GeoJSON 레이어(boundaries.ts)는 하위 호환으로 유지

성능 목표 40만척+ GPU 렌더링 달성. TripsLayer/HexagonLayer/IconLayer는 실데이터 확보 후 추가 예정.


5. 더미 데이터 통합 — COMPLETED

src/data/mock/에 7개 공유 mock 모듈 구현 완료. TypeScript 인터페이스 정의 포함.

data/mock/
├── vessels.ts       # VesselData — 선박 목록 (한국, 중국, 경비함)
├── events.ts        # EventRecord, AlertRecord — 탐지/단속 이벤트
├── transfers.ts     # 전재(환적) 데이터
├── patrols.ts       # PatrolShip — 순찰 경로/함정
├── gear.ts          # 어구 탐지 데이터
├── kpi.ts           # KpiMetric, MonthlyTrend, ViolationType
└── enforcement.ts   # 단속 이력 데이터
  • services/ 계층이 mock 모듈을 import하여 반환 → 향후 API 교체 시 서비스만 수정
  • 인터페이스가 API 응답 타입 계약 역할 수행

6. i18n 실적용 — 구조 완성, 내부 텍스트 미적용

현재 상태

  • 10 네임스페이스 리소스 완비: common, dashboard, detection, patrol, enforcement, statistics, ai, fieldOps, admin, auth
  • ko/en 각 10파일 (총 20 JSON)
  • settingsStore.toggleLanguage() + localStorage 동기화 구현 완료
  • 적용 완료: MainLayout 사이드바 메뉴명, 24개 페이지 제목, LoginPage
  • 미적용: 각 페이지 내부 텍스트 (카드 레이블, 테이블 헤더, 상태 텍스트 등) — 대부분 한국어 하드코딩 잔존

남은 작업

  • 각 feature 페이지 내부 텍스트를 useTranslation('namespace') + t() 로 교체
  • 날짜/숫자 포맷 로컬라이즈 (Intl.DateTimeFormat, Intl.NumberFormat)
  • 누락 키 감지 자동화 (i18next missing key handler 또는 lint 규칙)

7. Tailwind 공통 스타일 모듈화 (CVA) — COMPLETED

class-variance-authority 0.7.1 설치, src/lib/theme/variants.ts에 3개 CVA 변형 구현 완료.

  • cardVariants: default / elevated / inner / transparent — CSS 변수 기반 테마 반응
  • badgeVariants: 8 intent (critical~cyan) x 4 size (xs~lg) — 150회+ 반복 패턴 통합
  • statusDotVariants: 4 status (online/warning/danger/offline) x 3 size (sm/md/lg)
  • shared/components/ui/card.tsx, badge.tsx에 CVA 적용 완료
  • CSS 변수(surface-raised, surface-overlay, border) 참조로 Dark/Light 자동 반응

8. 코드 스플리팅 — 미착수

현재 상태

  • 단일 번들 ~3.2MB (모든 feature + deck.gl + MapLibre + ECharts 포함)
  • React.lazy 미적용, 모든 31개 페이지가 동기 import
  • 초기 로딩 시 사용하지 않는 페이지 코드까지 전부 다운로드

필요한 이유

  • 초기 로딩 성능 개선 (FCP, LCP)
  • 현장 모바일 환경 (LTE/3G)에서의 사용성 확보
  • 번들 캐싱 효율 향상 (변경된 chunk만 재다운로드)

구현 계획

  • React.lazy + Suspense로 feature 단위 동적 임포트:
    const Dashboard = lazy(() => import('@features/dashboard/Dashboard'));
    const RiskMap = lazy(() => import('@features/risk-assessment/RiskMap'));
    
  • App.tsx 라우트 전체를 lazy 컴포넌트로 교체
  • 로딩 폴백 컴포넌트 (스켈레톤 또는 스피너) 공통화
  • Vite build.rollupOptions.output.manualChunks 설정:
    manualChunks: {
      'vendor-react': ['react', 'react-dom', 'react-router-dom'],
      'vendor-map': ['maplibre-gl', 'deck.gl', '@deck.gl/mapbox'],
      'vendor-chart': ['echarts'],
    }
    
  • 목표: 초기 번들 < 300KB (gzip), 각 feature chunk < 100KB
  • vite-plugin-compression으로 gzip/brotli 사전 압축 검토

9. Light 테마 하드코딩 정리

현재 상태

  • Dark/Light 테마 전환 구조 완성 (CSS 변수 + .light 클래스 + settingsStore)
  • 시맨틱 변수(surface-raised, text-heading 등) + CVA 변형은 정상 작동
  • 문제: 일부 alert/status 색상이 Tailwind 하드코딩 (bg-red-500/20, text-red-400, border-red-500/30 등)
    • Dark에서는 자연스러우나, Light 전환 시 대비/가독성 부족

구현 계획

  • 하드코딩 alert 색상을 CSS 변수 또는 CVA intent로 교체
  • badgeVariants의 intent 색상도 CSS 변수 기반으로 전환 검토
  • Light 모드 전용 대비 테스트 (WCAG AA 기준)

우선순위 및 의존관계

✅ 완료 ─────────────────────────────────────
[1. Zustand]  [4. deck.gl]  [5. mock 데이터]  [7. CVA]

진행 중 / 남은 작업 ──────────────────────────
[6. i18n 내부 텍스트] ──┐
                         ├──▶ [2. API 실제 연동] ──▶ [3. 실시간 STOMP]
[9. Light 테마 정리] ───┘

[8. 코드 스플리팅] ← 독립 작업, 언제든 착수 가능 (~3.2MB → 목표 <300KB)

권장 진행 순서

  1. Phase A (품질): i18n 내부 텍스트 적용 (6) + Light 테마 하드코딩 정리 (9) + 코드 스플리팅 (8)
  2. Phase B (연동): Axios 설치 + API 실제 연동 (2)
  3. Phase C (실시간): STOMP.js + SockJS 실시간 인프라 (3)