홈 › 실무 배치 › 05 / 6

Skip과 Retry 로직 구현

섹션 7진행 0 / 6

스킵과 재시도 — 실패를 분류하고 격리하기

실패를 일시적/영구적/치명적으로 분류해, 재시도할 것은 백오프와 함께 재시도하고, 건너뛸 것은 한도 안에서 건너뛰며 데드 레터에 남기고, 멈춰야 할 것은 즉시 멈추는 배치를 순수 자바로 구현하고 최종 리포트까지 출력할 수 있게 됩니다.

1. 왜 배우는가

100만 건 회원에게 알림을 보내는 배치가 있습니다. 999,999건은 정상인데 한 건의 전화번호가 010-abcd-1234 입니다. 이 한 건 때문에 배치 전체가 죽어야 할까요? 그러면 새벽에 운영자가 불려 나와 그 행을 손으로 고치고 재실행해야 합니다. 반대로 외부 알림 API 가 0.1% 확률로 타임아웃을 낸다면, 그 1,000건을 실패로 기록하고 끝내야 할까요? 다시 한 번만 호출하면 대부분 성공할 텐데요.

실패는 한 종류가 아닙니다. 다시 하면 되는 실패(네트워크 타임아웃, DB 락 대기), 다시 해도 안 되는 실패(데이터 형식 오류, 존재하지 않는 계좌), 더 진행하면 안 되는 실패(DB 접속 불가, 디스크 꽉 참). 세 가지를 같은 catch (Exception e) 로 다루면 어느 쪽으로든 사고가 납니다.

재시도해야 할 것을 스킵하면 데이터가 빠지고, 스킵해야 할 것을 재시도하면 시간만 낭비하고, 중단해야 할 것을 스킵하면 "입력 파일이 통째로 깨졌는데 정상 종료"가 됩니다.

Spring Batch 의 retry(), skip(), skipLimit(), noRollback() 은 이 분류를 설정으로 표현한 것입니다. 이 레슨에서는 그 밑에 있는 RetryTemplate 과 SkipPolicy 를 직접 만들어 04 레슨의 청크 처리에 통합하고, 04 에서 "청크 전체 롤백"으로 남겨 둔 문제를 "실패 건만 제외하고 나머지 커밋"으로 완성합니다.