# Signal Batch - Vessel Signal Batch Aggregation System

## 빌드 및 실행

```bash
# 빌드 (Maven)
mvn clean package -DskipTests

# 프로파일별 실행
java -jar target/vessel-batch-aggregation.jar --spring.profiles.active=prod
java -jar target/vessel-batch-aggregation.jar --spring.profiles.active=prod-mpr
java -jar target/vessel-batch-aggregation.jar --spring.profiles.active=dev
java -jar target/vessel-batch-aggregation.jar --spring.profiles.active=local
java -jar target/vessel-batch-aggregation.jar --spring.profiles.active=query
```

## 프로젝트 개요

- **설명**: 선박 항적(Track) 실시간 수집 및 배치 집계 시스템
- **Java**: 17
- **Spring Boot**: 3.2.5
- **DB**: PostgreSQL + PostGIS
- **빌드도구**: Maven (pom.xml)

## 프로파일 구성

| 프로파일 | 용도 | 배치 | DataSource | 포트 |
|---------|------|-----|-----------|------|
| **prod** | 운영환경 | 활성화 | 3개 분리 | 18090 |
| **prod-mpr** | 운영환경(MPR) | 활성화 | 3개 분리 | 18090 |
| **dev** | 개발환경 | 활성화 | 3개 분리 | 18090 |
| **local** | 로컬개발 | 비활성화 | 단일 | 8090 |
| **query** | 조회전용 | 비활성화 | 단일 | 8090 |

## 핵심 패키지 구조

```
gc.mda.signal_batch/
├── batch/              # 배치 처리 (Job, Processor, Reader, Writer)
│   ├── job/            # Job 설정 및 스케줄러
│   ├── reader/         # ItemReader (파티션, 메모리)
│   ├── processor/      # ItemProcessor (항적 변환, 비정상 검출)
│   ├── writer/         # ItemWriter (Bulk Insert, Upsert)
│   └── listener/       # 배치 리스너
├── domain/
│   ├── gis/            # GIS API (해구, 구역, 타일)
│   ├── vessel/         # 선박 항적/위치 조회, 필터링
│   ├── track/          # 비정상 항적 검출 API
│   ├── passage/        # 순차 영역 통과 조회
│   ├── ship/           # 선박 이미지 API
│   └── debug/          # 디버그 API
├── global/
│   ├── config/         # DataSource, WebSocket, Batch 설정
│   ├── util/           # 공통 유틸리티
│   ├── websocket/      # WebSocket STOMP 스트리밍
│   └── tool/           # 배치 진단 도구
├── migration/          # 데이터 마이그레이션
└── monitoring/         # 모니터링, 메트릭, 성능 최적화
```

## DataSource 구성 (3개)

1. **CollectDataSource**: 원본 신호 수집 (읽기 전용)
2. **QueryDataSource**: 집계 데이터 조회/쓰기
3. **BatchDataSource**: Spring Batch 메타데이터

설정 클래스:
- `DevDataSourceConfig.java` (dev)
- `ProdDataSourceConfig.java` (prod/prod-mpr)
- `LocalDataSourceConfig.java` (local)
- `QueryDataSourceConfig.java` (query)

## 주요 API 엔드포인트

### REST API V1 (WKT 응답)
| 메서드 | 경로 | 설명 |
|--------|------|------|
| GET | `/api/v1/haegu/boundaries` | 해구 경계 |
| GET | `/api/v1/haegu/vessel-stats` | 해구별 선박 통계 |
| GET | `/api/v1/tracks/haegu/{no}` | 해구별 항적 |
| GET | `/api/v1/tracks/area/{areaId}` | 영역별 항적 |
| POST | `/api/v1/tracks/vessels` | 선박별 항적 조회 (일괄) |
| GET | `/api/v1/vessels/recent-positions` | 최근 위치 업데이트 선박 |

### REST API V2 (JSON/CompactVesselTrack)
| 메서드 | 경로 | 설명 |
|--------|------|------|
| POST | `/api/v2/tracks/vessels` | 선박별 항적 (JSON 배열 응답) |
| GET | `/api/v2/tracks/haegu/{no}` | 해구별 항적 (JSON) |

### 비정상 항적 API
| 메서드 | 경로 | 설명 |
|--------|------|------|
| GET | `/api/v1/abnormal-tracks/recent` | 최근 비정상 항적 |
| GET | `/api/v1/abnormal-tracks/vessel/{sigSrcCd}/{targetId}` | 특정 선박 비정상 이력 |
| GET | `/api/v1/abnormal-tracks/statistics` | 비정상 통계 |
| POST | `/api/v1/abnormal-tracks/detect` | 사용자 정의 기준 검출 |

### 기타 API
| 메서드 | 경로 | 설명 |
|--------|------|------|
| POST | `/api/v1/passages/sequential` | 순차 구역 통과 조회 |
| GET | `/api/v1/shipimg/{imo}` | 선박 이미지 조회 |
| GET | `/api/v1/tiles/{z}/{x}/{y}` | 타일 집계 데이터 |

### WebSocket (STOMP)
- **엔드포인트**: `/ws-tracks` (네이티브), `/ws-tracks` + SockJS
- **쿼리 요청**: `/app/tracks/query`
- **쿼리 취소**: `/app/tracks/cancel/{queryId}`
- **응답 수신**: `/user/queue/tracks/response`
- **청크 데이터**: `/user/queue/tracks/chunk`
- **상태 업데이트**: `/user/queue/tracks/status`

## 배치 Job

| Job | Cron | 지연 | 역할 |
|-----|------|-----|------|
| **incremental** | 매 5분 (3,8,13...) | 3분 | 수집 DB → 위치 집계 |
| **track** | 매 5분 (4,9,14...) | 4분 | 위치 → 항적(LineStringM) 변환 |
| **hourly** | 매시 10분 | - | 5분 → 시간 집계, 비정상 검출 |
| **daily** | 매일 01:00 | - | 시간 → 일 집계, 비정상 검출 |

### 배치 처리 흐름
```
CollectDB (신호)
    → incremental Job (5분 버킷 집계)
    → track Job (LineStringM 항적 생성)
    → hourly Job (시간 병합 + 비정상 검출)
    → daily Job (일 병합 + 비정상 검출)
```

## 코드 스타일

- Lombok 사용 (@Data, @Builder, @Slf4j)
- JdbcTemplate 직접 사용 (JPA 미사용)
- PostGIS 공간 쿼리 활용
- 청크 기반 배치 처리 (기본 10,000건)
- UPSERT/Bulk Insert 최적화

## 주요 DTO

- `CompactVesselTrack`: WebSocket/REST V2 응답 (geometry[], timestamps[], speeds[], nationalCode, shipKindCode)
- `TrackResponse`: REST V1 응답 (WKT 기반)
- `VesselTracksRequest`: 항적 조회 요청
- `AbnormalTrackResponse`: 비정상 항적 응답
- `SequentialPassageRequest/Response`: 순차 통과 조회

## 최근 작업 이력

### 2026-01-20
- V2 REST API 추가 (WebSocket 응답 호환)
  - `GisControllerV2.java`, `GisServiceV2.java`
- CompactVesselTrack 확장: nationalCode, shipKindCode, integrationTargetId 추가
- WebSocket 청크 스트리밍 구현 (`ChunkedTrackStreamingService`)
- 선박 최신 위치 캐시 갱신 스케줄러 추가
- DateTime 파싱 유연화 (`FlexibleLocalDateTimeDeserializer`)
- Swagger 9개 API 그룹 체계화

## 주의사항

- 빌드: `mvn` 사용 (Gradle 아님)
- 프로파일별 DataSource 설정이 다름
- WebSocket은 STOMP 프로토콜 사용
- LineStringM 형식: `LINESTRING M(lon lat unixTimestamp, ...)`
- 비정상 항적 검출: 시간/일 집계 시 자동 수행

## 성능 설정 (prod)

```yaml
batch:
  chunk-size: 10000
  partition-size: 12
  fetch-size: 200000
  bulk-insert:
    batch-size: 10000
    parallel-threads: 8

cache:
  latest-position:
    ttl-minutes: 60
    max-size: 60000

abnormal-detection:
  5min-speed-threshold: 500 knots
  hourly-daily-speed-limit: 500 knots
```

## Swagger 문서

- **접근**: `http://localhost:{port}/swagger-ui.html`
- **API 그룹**: 항적조회, 비정상항적, 타일, 선박이미지, 성능최적화, 관리자, 모니터링, 마이그레이션, 디버그

## 팀 규칙

- 코드 스타일: `.claude/rules/code-style.md` 참조
- 네이밍 규칙: `.claude/rules/naming.md` 참조
- 테스트 규칙: `.claude/rules/testing.md` 참조
- Git 워크플로우: `.claude/rules/git-workflow.md` 참조
- 팀 정책: `.claude/rules/team-policy.md` 참조
