SNP Sync Batch
S&P Global 해양 데이터를 수집하여 PostgreSQL에 동기화하는 Spring Batch 시스템입니다.
기술 스택
| 구분 |
기술 |
| Language |
Java 17 |
| Framework |
Spring Boot 3.2.1, Spring Batch 5.1.0 |
| Scheduler |
Quartz 2.5.0 (JDBC Store) |
| Database |
PostgreSQL (dual datasource) |
| Cache |
Caffeine |
| Frontend |
React + TypeScript (Vite) |
| Build |
Maven (frontend-maven-plugin 통합) |
| CI/CD |
Gitea Actions → systemd 자동 배포 |
아키텍처
┌─────────────────────────────────────────────────────────────────┐
│ SNP Sync Batch │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Quartz │───►│ Reader │───►│ Processor │───►│ Writer │ │
│ │ Scheduler │ │(BaseSyncR)│ │(DTO→Entity)│ │(SubChunk) │ │
│ └──────────┘ └────┬─────┘ └──────────┘ └────┬─────┘ │
│ │ │ │
│ ┌────────▼────────┐ ┌───────▼───────┐ │
│ │ Source DB │ │ Target DB │ │
│ │ (std_snp_data) │ │ (std_snp_svc) │ │
│ │ batch_flag 관리 │ │ UPSERT 저장 │ │
│ └─────────────────┘ └───────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ React Frontend (포트 8051, /snp-sync) │ │
│ │ 대시보드 │ 동기화현황 │ 실행이력 │ 스케줄 │ 타임라인 │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
데이터베이스 구조
Dual Datasource
| Datasource |
스키마 |
용도 |
| batchDataSource (Primary) |
snp_batch |
Spring Batch 메타데이터, Quartz 스케줄 |
| businessDataSource |
std_snp_data / std_snp_svc |
비즈니스 데이터 (소스/타겟) |
동기화 대상 테이블
| 도메인 |
소스 테이블 수 |
주요 내용 |
| Ship |
25개 |
선박 제원, 이력, 관계 |
| Company |
1개 |
회사 상세 정보 |
| Event |
4개 |
해양 사건/사고 |
| Facility |
1개 |
항구 시설 |
| PSC |
3개 |
PSC 검사 |
| Movements |
8개 |
선박 이동 (항적) |
| Code |
2개 |
코드 (선종, 국적) |
| Risk |
1개 |
위험 지표 (+ 값 변경 이력) |
| Compliance |
2개 |
컴플라이언스 (+ 값 변경 이력) |
동기화 프로세스
batch_flag 상태 흐름
[N] 대기 ──── Reader ────► [P] 진행 ──── Writer 성공 ────► [S] 완료
│ │
│ Writer 실패 시
│ P 상태 고착 (수동 리셋 필요)
│
batch_job_execution.status = 'COMPLETED' 인 데이터만 대상
Reader → Writer 흐름
BaseSyncReader (while 루프)
│
├─ fetchNextGroup(11284): MIN(batch_flag='N') → 데이터 로드 → N→P
├─ fetchNextGroup(11286): 다음 그룹 연속 로드 → N→P
├─ fetchNextGroup(11317): 다음 그룹 연속 로드 → N→P
└─ fetchNextGroup(): 데이터 없음 → return null → Step 종료
│
▼
BaseChunkedWriter (sub-chunk 5000건 단위)
│
├─ Sub-Chunk 1: [1~5000건] → 독립 트랜잭션 커밋
├─ Sub-Chunk 2: [5001~10000건] → 독립 트랜잭션 커밋
└─ ...
│
▼
BatchWriteListener.afterWrite()
└─ 청크 내 모든 고유 job_execution_id → P→S 업데이트
값 변경 이력 관리 (Risk, Compliance)
데이터 동기화 Job과 값 변경 이력 Job이 분리되어 운영됩니다:
riskDataSyncJob (데이터 동기화)
Source → Reader → Writer
├─ UPSERT → tb_ship_risk_detail_info (최신 데이터)
└─ UPSERT → tb_ship_risk_detail_hstry (스냅샷 이력)
riskDetailChangeDataSyncJob (값 변경 이력)
tb_ship_risk_detail_hstry (스냅샷)
→ imo_no별 시계열 비교
→ indicator 컬럼 변경분 감지
→ INSERT → tb_ship_risk_detail_info_hstry (컬럼명, 이전값, 이후값)
배치 Job 목록
데이터 동기화 Job
| Job 이름 |
도메인 |
설명 |
| snpMdaDataSyncJob |
Ship + Company |
선박/회사 데이터 동기화 (26 Step) |
| eventDataSyncJob |
Event |
사건 데이터 동기화 (4 Step) |
| facilitySyncJob |
Facility |
항구 시설 동기화 |
| pscDataSyncJob |
PSC |
PSC 검사 동기화 (3 Step) |
| anchorageCallDataSyncJob |
Movements |
정박지 기항 |
| berthCallDataSyncJob |
Movements |
부두 기항 |
| currentlyAtDataSyncJob |
Movements |
현재 위치 |
| destinationDataSyncJob |
Movements |
목적지 |
| portCallDataSyncJob |
Movements |
항구 기항 |
| stsOperationDataSyncJob |
Movements |
STS 작업 |
| terminalCallDataSyncJob |
Movements |
터미널 기항 |
| transitDataSyncJob |
Movements |
통과 |
| codeDataSyncJob |
Code |
코드 동기화 (2 Step) |
| riskDataSyncJob |
Risk |
위험 지표 동기화 |
| shipComplianceDataSyncJob |
Compliance |
선박 컴플라이언스 |
| companyComplianceDataSyncJob |
Compliance |
회사 컴플라이언스 |
값 변경 이력 Job
| Job 이름 |
설명 |
| riskDetailChangeDataSyncJob |
Risk indicator 값 변경 이력 |
| shipComplianceChangeDataSyncJob |
선박 컴플라이언스 값 변경 이력 |
| companyComplianceChangeDataSyncJob |
회사 컴플라이언스 값 변경 이력 |
유지보수 Job
| Job 이름 |
설명 |
| batchLogCleanupJob |
배치 로그 정리 (90일 보관) |
프론트엔드
| 메뉴 |
경로 |
설명 |
| 대시보드 |
/ |
통계, 실행 중 작업, 최근 실행/실패 |
| 동기화 현황 |
/sync-status |
테이블별 N/P/S 건수, 데이터 미리보기, P 리셋 |
| 실행 이력 |
/executions |
배치 실행 검색, 필터, 상세 |
| 작업 |
/jobs |
Job 목록, 수동 실행 |
| 스케줄 |
/schedules |
Quartz 스케줄 CRUD, Cron 미리보기 |
| 타임라인 |
/schedule-timeline |
일/주/월별 실행 시각화 |
CI/CD
develop → main 머지
→ Gitea Actions (빌드 + JAR 배포)
→ systemd path watcher (.deploy-trigger 감지)
→ restart.sh → 서비스 재시작
배포 확인
# 배포 로그
cat /devdata/services/snp-sync-batch/backend/deploy.log
# 서비스 상태
systemctl status snp-sync-batch
# 실시간 로그
journalctl -u snp-sync-batch -n 100 -f
빌드 및 실행
# 개발 환경 실행
mvn spring-boot:run
# 패키징
mvn clean package -DskipTests
# 서버 포트: 8051
# Context Path: /snp-sync
# Swagger: /snp-sync/swagger-ui.html