배치 작업에서 실패는 피할 수 없는 현실이다. 파일에 일부 잘못된 데이터가 저장되었을 수도 있고, 데이터베이스와의 토잇ㄴ이 일시적으로 실패할 수도이 있다. 그렇다고 해서 배치 작업이 중단되어도 괜찮을까?
스텝 실행 중 단 하나의 예외라도 발생하면?
ItemReader에서 읽는 중이든, ItemProcessor에서 처리 중이든, ItemWriter에서 쓰는 중이든 Spring Batch는 즉시 모든 실행을 중단하고 배치 잡 전체를 실패로 처리한다.
하지만 생각해보자.
적절한 예외 처리 방법으로 재시도 가능한 예외는 재시도하고, 무시해도 되는 예외는 무시할 수 있어야 한다.
그러나 이게 구조적으로 쉽지만은 않다. 우리가 지금까지 살펴본 청크 지향 처리의 구조를 생각해보자.
개발자는 ItemReader, ItemProcessor, ItemWriter 구현체를 스텝에 구성만할 뿐, 실제 실행은 Spring Batch의 Step이 담당한다. 즉, 아이템 처리 중 예외가 ㅂ라생해도 우리가 직접 개입할 기회가 없다.
다행이 이런 구조적 한계를 보완하기 위해 Spring Batch는 내결함성(FaultTolerance)기능을 제공한다.
이를 활용하면 간단한 구성만으로도 **재시도(Retry)**와 **건너뛰기(Skip)**로 청크 지향 처리에서 발생할 수 있는 다양한 예외 상황을 다룰 수 있다.
예를 들어,
참고 : 태크스릿 지향 처리는 내결함성(FaultTolerance)를 지원하지 않는다.
우리가 작성한 코드 내에서try-catch를 사용해 발생 가능한 예외를 원하는 대로 처리할 수 있기 때문이다.
말 그대로 실패한 작업을 다시 시도하는 것이다.
예를 들어 쓰기 중 데이터베이스 커넥션이 순간적으로 끊기거나 ItemProcessor의 외부 API 호출에서 일시적으로 타임아웃이 발생했을 떄, 잠시 후 다시 시도하면 정상적으로 처리될 가능성이 높다.
내결함성 기능을 활성화하면 스텝은 RetryTemplate이라는 무기를 장착하게 된다.
RetryTemplate은 Spring Retry 프로젝트의 핵심 컴포넌트로, 쉽게 말해 작업이 실패하면 정해진 정책에 따라 다시 시도하는 컴포넌트다.
RetryTemplate의 메커니즘을 들여다보자. 다음 다이어 그램은 RetryTemplate.execute() 메서드가 내부적으로 어떻게 동작하는지를 단순화해서 보여준다.
RetryTemplate.execute()
|
v
canRetry()? <-- RetryPolicy 판단
/ \
/ \
YES NO
| |
v v
retryCallback() recoveryCallback()
(재시도 수행) (복구 로직 수행)
이 메커니즘이 Spring Batch Step에 장착되면 어떤 일이 벌어질까?
그렇다면 canRetry() 메서드에서는 재시도 가능 여부를 어떻게 판단할까?