- .claude/rules: team-policy, git-workflow, code-style, naming, testing - .claude/skills: init-project, sync-team-workflow, create-mr, fix-issue - .claude/scripts: on-pre-compact, on-post-compact, on-commit (v1.2.0) - .claude/settings.json: 팀 표준 권한 allow/deny + script hooks - .githooks: commit-msg, pre-commit (mvn compile), post-checkout - .mvn/settings.xml: Nexus 미러 설정 - .editorconfig: 팀 표준 포맷 - CLAUDE.md: 팀 규칙 참조 섹션 추가 - .gitignore: !.claude/ negation 추가 (글로벌 gitignore override) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
200 lines
7.2 KiB
Markdown
200 lines
7.2 KiB
Markdown
# 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` 참조
|