[Spring Batch 실전] Day 3: Retry·Skip·Rollback - 실패를 분류하는 법
[Spring Batch 실전] Day 3: Retry·Skip·Rollback - 실패를 분류하는 법
이 글은 AI(Claude)의 도움을 받아 작성하고, 작성자가 검토·편집했습니다.
서론: 재시도할 실패와 건너뛸 실패
네트워크 타임아웃은 잠시 뒤 성공할 수 있지만 잘못된 주민번호 형식은 백 번 재시도해도 성공하지 않는다. 모든 예외를 재시도하면 작업 시간이 폭증하고, 모든 예외를 Skip하면 데이터가 조용히 빠진다. 실패를 분류하는 것이 fault-tolerant 배치의 핵심이다.
1. 실패 분류표
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
일시적 인프라 오류:
연결 초기화, 일부 타임아웃, 일시적 락 충돌
→ 제한된 Retry 후보
데이터 품질 오류:
필수값 누락, 파싱 실패, 허용되지 않은 코드
→ 격리·Skip 또는 전체 실패
프로그래밍/불변식 오류:
NullPointerException, 예상 불가능 상태
→ 즉시 실패하고 수정
업무 거절:
이미 마감, 대상 아님
→ 명시적 필터 또는 결과 상태
2. Retry에는 상한과 백오프가 있다
1
2
3
4
5
6
7
8
9
10
new StepBuilder("import", jobRepository)
.<Input, Output>chunk(100)
.transactionManager(transactionManager)
.reader(reader())
.processor(processor())
.writer(writer())
.faultTolerant()
.retry(TransientDataAccessException.class)
.retryLimit(3)
.build();
재시도 대상 예외를 좁히고 전체 소요 시간과 하위 시스템 부하를 고려한다. 외부 호출은 멱등해야 하며 백오프·지터가 없으면 장애를 증폭할 수 있다.
3. Skip은 데이터 손실 정책이다
1
2
3
4
Skip 허용 전 질문:
이 행이 빠져도 업무 결과가 유효한가?
누가 언제 수정하고 재처리하는가?
Skip 수가 임계치를 넘으면 전체 실패해야 하는가?
1
2
.skip(InvalidRowException.class)
.skipLimit(20)
Skip된 원문, 오류 코드, 입력 파일/행 번호, 실행 ID를 격리 저장소에 남긴다. 로그 한 줄만 남기면 재처리할 수 없다.
4. Chunk 롤백과 재처리
Writer가 Chunk 100건 중 마지막에 실패하면 일반적으로 해당 Chunk의 트랜잭션이 롤백되고 항목들이 다시 읽히거나 처리될 수 있다. Processor가 외부 부작용을 만들면 DB 롤백과 불일치가 생긴다.
1
2
3
Processor: 결정적 변환
Writer: 트랜잭션 가능한 자원에 일괄 반영
외부 부작용: 별도 Step/Outbox로 분리
5. Listener는 관찰과 격리에 사용한다
1
2
3
4
5
6
7
8
SkipListener:
건너뛴 항목과 이유 저장
RetryListener:
재시도 횟수·예외·소요 시간 메트릭
Job/StepExecutionListener:
시작·종료·요약 알림, 업무 리포트
Listener 안에서 핵심 업무 상태를 몰래 바꾸면 재시작 의미가 복잡해진다. 관찰·감사·격리에 집중한다.
6. 오류 예산을 업무 기준으로
1
2
3
4
5
주소 정제 배치:
0.1% 오류 격리 후 완료 가능
급여 지급 배치:
단 한 건 불일치도 전체 승인 중단
기술 예외 타입뿐 아니라 결과의 완전성 요구에 따라 Skip 정책을 정한다. 완료 상태도 COMPLETED_WITH_SKIPS 같은 업무 신호로 별도 집계할 수 있다.
7. Day 3 체크리스트
- 일시 오류·데이터 오류·코드 오류·업무 거절을 구분했다.
- 좁은 예외와 상한·백오프로 Retry를 제한했다.
- Skip을 명시적인 데이터 손실·재처리 정책으로 다뤘다.
- Chunk 롤백 안에서 외부 부작용이 발생하지 않게 분리했다.
- Listener와 격리 저장소로 실패 항목을 추적 가능하게 만들었다.
다음 편 예고
정확하게 동작하는 단일 프로세스가 목표 시간을 넘길 때만 병렬화를 고려한다. Day 4에서는 Parallel Step·Partitioning·Remote Chunking의 선택 기준과 함정을 살펴본다.
This post is licensed under CC BY 4.0 by the author.