# 프로젝트 개요

- **이름**: KCG 모니터링 대시보드 (kcg-monitoring)
- **구조**: 모노레포 (Frontend + Backend + Prediction)
- **도메인**: https://kcg.gc-si.dev
- **Gitea**: https://gitea.gc-si.dev/gc/kcg-monitoring

## 기술 스택

| 패키지 | 스택 | 비고 |
|--------|------|------|
| **Frontend** | React 19 + TypeScript 5.9 + Vite 7 + Tailwind CSS 4 | i18n(ko/en), 테마(dark/light), MapLibre GL + deck.gl GPU |
| **Backend** | Spring Boot 3.2.5 + Java 21 + PostgreSQL + PostGIS | Google OAuth + JWT, Caffeine 캐시 |
| **Prediction** | FastAPI + Python 3.9 + Shapely + APScheduler | 5분 주기 해양 분석 파이프라인 |
| **DB** | PostgreSQL 16 + PostGIS (211.208.115.83:5432/kcgdb, 스키마: kcg) | |
| **궤적 DB** | PostgreSQL (snpdb, 211.208.115.83:5432/snpdb, 스키마: signal) | LineStringM 궤적 |
| **CI/CD** | Gitea Actions → nginx + systemd | main merge 시 자동 배포 |

## 빌드 및 실행

### Frontend
```bash
cd frontend
npm install
npm run dev      # 개발서버 (포트 5173)
npm run build    # 프로덕션 빌드
npm run lint     # ESLint 검증
```

### Backend
```bash
cd backend
sdk use java 21.0.9-amzn   # JDK 21 필수
mvn spring-boot:run -Dspring-boot.run.profiles=local  # 개발서버 (포트 8080)
mvn compile      # 컴파일 검증
mvn package      # JAR 빌드 (target/kcg.jar)
```

### Prediction
```bash
cd prediction
pip install -r requirements.txt   # shapely, scikit-learn, apscheduler 등
uvicorn main:app --host 0.0.0.0 --port 8001
```

### Database
```bash
# kcgdb (분석 결과)
psql -h 211.208.115.83 -U kcg_app -d kcgdb -f database/migration/009_group_polygons.sql
# snpdb (궤적 원본) — 읽기 전용, 별도 관리
```

## 프로젝트 구조

```
frontend/                         # React 19 + Vite 7 + Tailwind CSS 4 + deck.gl
├── src/
│   ├── App.tsx                   # 인증가드 → SharedFilterProvider → FontScaleProvider
│   ├── contexts/                 # SharedFilterContext, FontScaleContext
│   ├── styles/
│   │   ├── tokens.css            # 테마 토큰 (dark/light), Tailwind @theme
│   │   ├── fonts.ts              # FONT_MONO/FONT_SANS 상수 (@fontsource-variable)
│   │   └── tailwind.css
│   ├── components/
│   │   ├── common/               # LayerPanel, EventLog, FontScalePanel, ReplayControls
│   │   ├── layers/               # DeckGLOverlay, ShipLayer, AircraftLayer, SatelliteLayer
│   │   ├── iran/                 # IranDashboard, ReplayMap, SatelliteMap, GlobeMap
│   │   │                         # createIranOil/Airport/MEFacility/MEEnergyHazard Layers
│   │   ├── korea/                # KoreaDashboard, KoreaMap + 25개 레이어/패널
│   │   │                         # FleetClusterLayer (API GeoJSON 렌더링)
│   │   │                         # AnalysisStatsPanel, FieldAnalysisModal
│   │   └── auth/                 # LoginPage
│   ├── hooks/
│   │   ├── useReplay, useMonitor, useAuth, useTheme
│   │   ├── useIranData (더미↔API 토글), useKoreaData, useKoreaFilters
│   │   ├── useVesselAnalysis (5분 폴링, mmsi별 분석 DTO)
│   │   ├── useGroupPolygons (5분 폴링, 선단/어구 폴리곤)
│   │   ├── useStaticDeckLayers (4개 서브훅 조합)
│   │   ├── useAnalysisDeckLayers (위험도/다크/스푸핑 마커)
│   │   ├── useFontScale, useLocalStorage, usePoll
│   │   └── layers/               # createPort/Navigation/Military/FacilityLayers
│   ├── services/                 # API 클라이언트 (ships, aircraft, osint, vesselAnalysis 등)
│   ├── data/                     # 정적 데이터 (공항, 유전, 샘플, 어업수역 GeoJSON)
│   └── i18n/                     # i18next (ko/en)
├── package.json
└── vite.config.ts                # Vite + 프록시 (/api/kcg → backend)

backend/                          # Spring Boot 3.2 + Java 21
├── src/main/java/gc/mda/kcg/
│   ├── auth/                     # Google OAuth + JWT (AuthFilter: 인증 예외 경로 관리)
│   ├── config/                   # CORS, Security, CacheConfig (Caffeine)
│   ├── domain/
│   │   ├── analysis/             # VesselAnalysisController/Service/Dto/Repository
│   │   ├── fleet/                # FleetCompanyController, GroupPolygonController/Service/Dto
│   │   ├── event/                # EventController/Service (이란 리플레이)
│   │   ├── aircraft/             # AircraftController/Service (시점 조회)
│   │   └── osint/                # OsintController/Service (시점 조회)
│   └── collector/                # GDELT, GoogleNews, CENTCOM (placeholder)
└── pom.xml

prediction/                       # FastAPI + Python 3.9 + APScheduler
├── main.py                       # FastAPI app + 스케줄러 초기화
├── scheduler.py                  # 5분 주기 분석 사이클 (7단계 파이프라인 + 폴리곤 생성)
├── fleet_tracker.py              # 등록 선단 매칭 + 어구 정체성 추적
├── config.py                     # Settings (snpdb/kcgdb 접속정보)
├── cache/
│   └── vessel_store.py           # 인메모리 AIS 캐시 (14K선박, 24h 윈도우)
├── algorithms/
│   ├── polygon_builder.py        # Shapely 폴리곤 생성 (선단/어구 그룹)
│   ├── fleet.py                  # 선단 패턴 탐지 (PT/FC/PS)
│   ├── transshipment.py          # 환적 탐지 (그리드 O(n log n))
│   ├── location.py               # 특정어업수역 판정 (Point-in-Polygon)
│   └── ...                       # dark_vessel, spoofing, risk, fishing_pattern
├── pipeline/                     # 7단계 분석 파이프라인
├── models/                       # AnalysisResult
├── db/
│   ├── snpdb.py                  # 궤적 DB (읽기 전용)
│   └── kcgdb.py                  # 분석 결과 DB (UPSERT + 폴리곤 저장)
├── data/zones/                   # 특정어업수역 GeoJSON (EPSG:3857)
└── requirements.txt              # shapely, scikit-learn, apscheduler, pandas, numpy

database/                         # PostgreSQL 마이그레이션
├── init.sql
└── migration/
    ├── 001_initial_schema.sql    # events, news, osint, users
    ├── 002_aircraft_positions.sql # PostGIS 활성화
    ├── 005_vessel_analysis.sql   # vessel_analysis_results
    ├── 007_fleet_registry.sql    # fleet_companies, fleet_vessels, gear_identity_log
    ├── 008_transshipment.sql     # 환적 탐지 칼럼 추가
    └── 009_group_polygons.sql    # group_polygon_snapshots (PostGIS Polygon)

deploy/                           # systemd + nginx 배포 설정
.gitea/workflows/deploy.yml       # CI/CD (main merge → 자동 빌드/배포)
```

## 주요 기능

### 한국 현황 대시보드
- **선박 모니터링**: 13K+ AIS 선박, MapLibre GPU-side filter, 카테고리/국적 토글
- **감시 탭**: 불법어선, 환적, 다크베셀, 해저케이블, 독도감시, 중국어선감시
- **선단/어구 폴리곤**: Python 서버사이드 생성 (Shapely + PostGIS) → API GeoJSON 렌더링
  - FLEET 15개, GEAR_IN_ZONE 57개, GEAR_OUT_ZONE 45개 (5분 주기 갱신, 7일 히스토리)
  - 가상 선박 마커 (ship-triangle + COG 회전 + zoom interpolate)
  - 겹침 해결: queryRenderedFeatures → 다중 선택 팝업 + 호버 하이라이트
- **AI 분석**: Python 7단계 파이프라인, 위험도/다크베셀/스푸핑 deck.gl 오버레이
- **현장분석**: FieldAnalysisModal (어구/선단 분석 대시보드)
- **시설 레이어**: deck.gl IconLayer(SVG) + TextLayer, 줌 스케일 연동

### 이란 상황 대시보드
- **공습 리플레이**: 실데이터 Backend DB 기반 (더미↔API 토글)
- **유전/공항/군사시설**: deck.gl SVG 아이콘, 사막 대비 고채도 팔레트
- **센서 그래프**: 지진, 기압, 소음/방사선
- **위성지도/평면/3D Globe**: 3개 맵 모드

### 공통
- **웹폰트**: @fontsource-variable Inter, Noto Sans KR, Fira Code 자체 호스팅
- **글꼴 크기 커스텀**: FontScalePanel (시설/선박/분석/지역 4그룹 × 0.5~2.0x)
- **LayerPanel**: 공통 트리 구조 (LayerTreeRenderer 재귀, 부모 캐스케이드)
- **인증**: Google OAuth + DEV LOGIN
- **localStorage**: 13개+ UI 상태 영속화

## 팀 스킬 사용 지침

### 중요: 스킬 실행 시 반드시 따라야 할 규칙

**`/push`, `/mr`, `/release` 스킬은 SKILL.md에 정의된 절차를 순서대로 엄격히 따라야 한다.**

특히 다음 단계를 절대 건너뛰지 말 것:

1. **Step 0.5 해시 비교**: 서버 해시와 로컬 해시를 실제로 bash 실행하여 비교.
   불일치 시 `/sync-team-workflow` 자동 실행 후 원래 작업 계속.
2. **AskUserQuestion 사용자 확인**: 커밋 메시지, MR 타겟, 릴리즈 노트 초안을
   반드시 사용자에게 보여주고 승인/수정/취소를 물어야 한다.
   자의적으로 진행하지 말 것.
3. **API 응답 검증**: MR 생성, 봇 승인, 머지 API 호출 후 반드시 상태를 확인.
   실패 시 사용자에게 알리고 중단.

### 스킬 목록
- `/push` — 커밋 + 푸시 (해시 비교 → 커밋 메시지 확인 → 푸시)
- `/mr` — 커밋 + 푸시 + MR 생성 (릴리즈 노트 갱신 포함)
- `/release` — develop → main 릴리즈 MR (릴리즈 노트 날짜 전환)
- `/version` — VERSION-HISTORY.md 생성
- `/create-mr` — MR 생성만 (세부 옵션)
- `/fix-issue` — 이슈 기반 작업 브랜치 생성

### 환경변수
- `GITEA_TOKEN`: `.claude/settings.local.json`의 `env`에 설정 (gitignored)
- `CLAUDE_BOT_TOKEN`: `.claude/settings.json`의 `env`에 설정 (gitignored by .claude/ rule)

## 배포

| 서버 | 역할 | 경로/설정 |
|------|------|----------|
| **rocky-211** (192.168.1.20) | Frontend + Backend | `/devdata/services/kcg/` |
| | Frontend | nginx 정적 파일 (`/deploy/kcg/`) |
| | Backend | systemd `kcg-backend` (JDK 21, 2~4GB 힙) |
| | CI/CD | act runner Docker (node:24) |
| **redis-211** (192.168.1.18:32023) | Prediction | `/home/apps/kcg-prediction/` |
| | | systemd `kcg-prediction` (uvicorn 8001, venv) |
| **도메인** | | https://kcg.gc-si.dev |
| **nginx** | | `/etc/nginx/conf.d/kcg.conf` (SSL + SPA + API 프록시) |
| **DB** | kcgdb | 211.208.115.83:5432/kcgdb (유저: kcg_app, pw: Kcg2026monitor) |
| **DB** | snpdb | 211.208.115.83:5432/snpdb (유저: snp, pw: snp#8932, 읽기 전용) |

## 디버그 도구 가이드

### 원칙
- 디버그/개발 전용 기능은 `import.meta.env.DEV` 가드로 감싸서 **프로덕션 빌드에서 코드 자체가 제거**되도록 구현
- Vite production 빌드 시 `import.meta.env.DEV = false` → dead code elimination → 번들 미포함
- 무거운 DB 조회, 통계 계산 등도 DEV 가드 안이면 프로덕션에 영향 없음

### 파일 구조
- 디버그 컴포넌트: `frontend/src/components/{도메인}/debug/` 디렉토리에 분리
- 메인 컴포넌트에서는 import + DEV 가드로만 연결:
```tsx
import { DebugTool } from './debug/DebugTool';
const debug = import.meta.env.DEV ? useDebugHook() : null;
// JSX:
{debug && <DebugTool ... />}
```

### 기존 디버그 도구
| 도구 | 위치 | 기능 |
|------|------|------|
| CoordDebugTool | `korea/debug/CoordDebugTool.tsx` | Ctrl+Click 좌표 표시 (DD/DMS, 다중 포인트) |

### 디버그 도구 분류 기준
다음에 해당하면 디버그 도구로 분류하고, 불확실하면 사용자에게 확인:
- 개발/검증 목적의 좌표/데이터 표시 도구
- 프로덕션 사용자에게 불필요한 진단 정보
- 임시 데이터 시각화, 성능 프로파일링
- 특정 조건에서만 활성화되는 테스트 기능

## 팀 규칙

- 코드 스타일: `.claude/rules/code-style.md`
- 네이밍: `.claude/rules/naming.md`
- 테스트: `.claude/rules/testing.md`
- Git 워크플로우: `.claude/rules/git-workflow.md`
- 팀 정책: `.claude/rules/team-policy.md`
- 릴리즈 노트 가이드: `.claude/rules/release-notes-guide.md`
- 서브에이전트 정책: `.claude/rules/subagent-policy.md`
