Spring Batch 기반
PostgreSQL → Oracle 데이터 이관 설계 구상안 정리
1. 작성 배경
대용량 PostgreSQL 테이블의 데이터를 Oracle로 이관해야 하는 상황에서,
**단순 일회성 마이그레이션이 아닌 “운영 중에도 안정적으로 이어갈 수 있는 구조”**가 필요했다.
특히 다음과 같은 조건이 있었다.
- 수백만 건 이상의 대용량 테이블
- 이관 중에도 신규 데이터가 지속적으로 INSERT
- 서버 중단 / 오류 발생 시 중단 지점부터 재개 가능
- 데이터 정합성 및 누락 여부를 명확히 확인 가능해야 함
이 글은 해당 요구사항을 바탕으로 Spring Batch 기반 데이터 이관 구조를 어떻게 설계했는지에 대한 구상 정리이다.
2. 구상안 요구 조건
- 데이터 이관 진행 상황을 기록할 로그 테이블 신규 생성
- 서버 재기동, 오류 발생 시에도 현재 진행 위치 파악 가능
- 중복 INSERT 방지
- 대용량 데이터 처리 시에도 안정적인 배치 처리
3. 사용 기술
- Spring Batch
- PostgreSQL (Source)
- Oracle (Target)
4. 현재 데이터 현황
대상 테이블 목록
TB_PLC11
- 데이터 수: 500만 건 이상
- 신규 데이터: 매 분 0 ~ 10건 INSERT
- 기준 컬럼: value40 (날짜/시간)
TB_PLC12
- 데이터 수: 300만 건 이상
- 기준 컬럼: value40
TB_PLC13
- 데이터 수: 300만 건 이상
- 기준 컬럼: value40
TB_PLC14
- 데이터 수: 877만 건 이상
- 기준 컬럼: value40
TB_PLC15
- 데이터 수: 약 900건
- 기준 컬럼: value200 (날짜/시간)
추후 컬럼 추가 가능성 있음
→ 기준 컬럼 또한 변경될 수 있으므로 하드코딩 배제 필요
5. 로그 테이블 설계 목적
이 로그 테이블은 단순 로그 용도가 아니라,
- 서버 중단 시 재시작 위치 판단
- 데이터 누락 / 실패 여부 판단
- 현재 이관 상태 파악
을 위한 상태 관리 테이블이다.
6. 로그 테이블 개요
테이블명
postgres_oracle_transfer_log
예상 Row 수
- 각 PLC 테이블(tb_plc1x) 당 1 row
- 총 row 수는 매우 적을 것으로 예상
7. 로그 테이블 컬럼 설계 (구상안)
기본 정보
- seq
- PK (시퀀스)
- reference_column
- 기준 컬럼명
- 예: value40, value200
기준 컬럼 값 관리
- current_ref_col_value
- 현재 처리 중인 기준 컬럼 값
- prev_ref_col_value
- 직전 처리한 기준 컬럼 값
- preprev_ref_col_value
- 전전 처리한 기준 컬럼 값
기준 컬럼 값 증가가 불연속적이기 때문에
단순 “마지막 값” 하나만 저장하면 정확한 재개가 어려움
→ 전 / 전전 값까지 함께 기록
데이터 개수 및 삽입 횟수 관리
- pre_ref_col_value_total_count
- 직전 기준 컬럼의 전체 데이터 수
- pre_ref_col_value_insert_count
- 직전 기준 컬럼에서 실제 INSERT 된 데이터 수
- preprev_ref_col_value_total_count
- 전전 기준 컬럼의 전체 데이터 수
- preprev_ref_col_value_insert_count
- 전전 기준 컬럼의 INSERT 된 데이터 수
활용 예시
- 전체 데이터 수: 8건
- INSERT 된 수: 5건
→ 정상적으로 이관되지 않았음을 즉시 판단 가능
처리 상태 및 결과
- prev_ref_col_value_success_yn
- 직전 기준 컬럼 처리 성공 여부
- insert_datetime
- 로그 입력 시각
- current_status
- 상태 값
- 대기중
- 진행중
- 완료
- 오류
- 실패
- 상태 값
- error_message
- 에러 발생 시 에러 내용 기록
8. 기준 컬럼 설계 의도 설명
기준 컬럼은 데이터 이관의 “포인터” 역할을 한다.
예시:
전전 기준 컬럼: 241204151100 전 기준 컬럼: 241204151125 현재 기준 컬럼: 241204151130
이 경우:
- 241204151125 값에 대해
- 전체 개수와 INSERT 개수가 같다면 → 완료
- 다르다면 → 아직 처리 중
- 다음 처리 대상은 241204151130임을 명확히 판단 가능
9. Java 애플리케이션 동작 로직
1️⃣ 로그 테이블 조회
a. 로그가 존재하는 경우
- 로그 테이블과 Oracle 실제 데이터 비교
- 전체 개수 / INSERT 개수 일치 여부 확인
결과에 따라:
- 일치 → 다음 기준 컬럼으로 진행
- 불일치 → 해당 기준 컬럼부터 이어서 진행
b. 로그가 없는 경우
- 최초 실행으로 판단
- 맨 처음 기준 컬럼부터 이관 시작
2️⃣ 이어서 진행하는 경우
- 로그 테이블 조회
- 직전 INSERT 기록 기준으로 처리 위치 결정
- 한 번에 처리할 데이터 수
- 500 / 1000 / 2000 단위 (환경에 따라 조절)
- 동일한 시간/날짜 기준으로 묶어서 로드
- 데이터 핸들링 단순화 목적
- Oracle INSERT 수행
- 결과 검증
- 로그 테이블 업데이트
3️⃣ 반복 실행
- 위 과정을 10분 단위로 반복 실행
- 신규 데이터 지속 반영 가능
10. 기준 컬럼 동적 관리
- 기준 컬럼을 코드에 하드코딩하지 않음
- 다음 중 하나에서 동적으로 로드
- env 설정
- DB 관리 테이블
이를 통해:
- 테이블별 기준 컬럼 변경 대응
- 향후 컬럼 추가 시 유연한 확장 가능
11. 개발 시 고려 사항
- 데이터 INSERT 정확성 검증
- 예외 처리 필수
- 중복 INSERT 방지
- 작업 실패 방지
- nssm 사용
- 프로세스 종료 / 에러 발생 시 자동 재시작
- try-catch를 통한 에러 로그 테이블 기록
- 롤백 상황에서도 현재 상태 추적 가능해야 함
12. 마무리
이 설계는 “한 번 돌리고 끝나는 배치”가 아니라,
- 운영 중에도 지속 가능한 이관
- 중단되어도 이어갈 수 있는 구조
- 데이터 정합성을 스스로 증명할 수 있는 구조
를 목표로 한 구상안이다.
실제 구현 과정에서 세부 로직은 변경될 수 있지만,
이관 시스템의 핵심 철학과 구조는 유지되어야 한다고 생각한다.
※ 본 글은 실제 운영 환경을 일반화하여 재구성한 설계 사례이며,
특정 고객사 또는 서비스의 실제 구조와는 무관합니다.
'[실무 설계와 판단]' 카테고리의 다른 글
| AWS 비용 최적화와 인프라 선택에 대한 현실적인 고민 (0) | 2025.12.26 |
|---|---|
| 현실적인 프로젝트 구조 설계 고민 (0) | 2025.12.26 |
| AWS 비용 최적화 실무 정리 (0) | 2025.12.26 |
| Kafka 기반 데이터 이관 트러블 슈팅 정리 (0) | 2025.12.26 |
| Kafka를 배우면서 가장 힘들었던 점 – 개념이 아니라 ‘맥락’이었다 (0) | 2025.12.26 |