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 → 서비스 재시작 ``` ### 배포 확인 ```bash # 배포 로그 cat /devdata/services/snp-sync-batch/backend/deploy.log # 서비스 상태 systemctl status snp-sync-batch # 실시간 로그 journalctl -u snp-sync-batch -n 100 -f ``` ## 빌드 및 실행 ```bash # 개발 환경 실행 mvn spring-boot:run # 패키징 mvn clean package -DskipTests # 서버 포트: 8051 # Context Path: /snp-sync # Swagger: /snp-sync/swagger-ui.html ```