
Spring Batch의 강력한 기능 중 하나는 실패한 Job을 이어서 실행할 수 있는 '재시작(Restart)' 기능입니다.
하지만 경우에 따라 재시작을 허용하면 데이터가 중복되거나 시스템이 꼬여버리는 심각한 문제가 발생할 수 있습니다.
이번 글에서는 Job의 재시작을 의도적으로 막는 preventRestart() 옵션의 역할과, 멱등성이라는 개념을 중심으로 언제 이 옵션을 사용해야 하는지 알아보겠습니다.
preventRestart를 이해하려면, 먼저 Spring Batch가 기본적으로 재시작을 허용한다는 점을 알아야 하며, Spring Batch의 아주 중요한 특징 중 하나입니다.
다음과 같은 3단계로 구성된 Job이 있다고 가정해 보겠습니다.
이 Job이 실행되다가 Step 3에서 메일 서버 문제로 실패했다면 어떻게 될까요?
개발자가 메일 서버 문제를 해결한 뒤, 동일한 파라미터로 Job을 다시 실행하면 Spring Batch는 데이터베이스에 기록된 이전 실행 상태(JobExecution)를 확인합니다. 그리고 다음과 같이 동작합니다.
COMPLETED 상태인 것을 보고 건너뜁니다.FAILED 상태였던 Step 3부터 실행을 다시 시작합니다.preventRestart() 옵션의 역할과 사용법preventRestart() 옵션의 역할은 이름 그대로 아주 직관적입니다. 바로 Job의 재시작을 막는 기능입니다.
이 옵션을 설정하면, 해당 Job은 재시작이 불가능한 '일회성' 작업이 됩니다.
만약 preventRestart()가 설정된 Job이 실행되다가 FAILED 상태가 되면, 해당 JobInstance(Job 이름 + 파라미터)의 생명주기는 거기서 종료됩니다.
동일한 파라미터로 다시 실행하려고 시도하면 Spring Batch는 즉시 JobRestartException 예외를 발생시키며 실행을 거부합니다. 단, 파라미터를 변경하여 실행하는 것은 새로운 JobInstance로 간주되므로 정상적으로 실행됩니다.
사용법은 매우 간단합니다. Job 설정에 단 한 줄만 추가하면 됩니다.
@Bean
public Job myJob() {
return new JobBuilder("myJob", jobRepository)
.start(step1())
.preventRestart() // <-- 이렇게 한 줄만 추가하면 됩니다!
.build();
}
preventRestart()는 언제 사용할까?결론부터 말하면, preventRestart()는 Job의 동작이 멱등성(Idempotent)을 보장하지 않을 때 사용합니다. 멱등성이란, 연산을 여러 번 수행해도 그 결과가 한 번 수행한 것과 동일한 성질을 의미합니다.
재시작을 했을 때 데이터가 중복되거나 꼬일 위험이 있는 Job에 이 옵션을 사용해 재시작을 차단합니다.
데이터를 덮어쓰지 않고 추가(Append)하는 Job
.preventRestart()를 설정해 실패 시 Job을 중단시키고, 개발자가 직접 원인을 파악하고 수동으로 조치하도록 합니다.한 번만 실행되어야 하는 외부 API 호출 Job
.preventRestart()로 재시작을 막아 중복 발송의 위험을 없애고, 실패 시 어디까지 작업이 성공했는지 수동으로 확인하고 조치합니다.Job 실행 시마다 고유한 리소스를 생성하는 Job
.preventRestart()를 걸어두면, 실패 후 재시작 시도를 막고 개발자가 직접 남아있는 임시 디렉터리를 정리하고 새 파라미터로 다시 실행하도록 유도할 수 있습니다.결론적으로 preventRestart()는 단순한 기능이 아니라, 개발자가 "해당 Job은 멱등성을 보장하는가?"를 스스로 묻게 만드는 중요한 장치입니다.
재시작 시 데이터가 꼬일 위험이 조금이라도 있다면, preventRestart()를 설정하여 의도치 않은 동작을 방지 하는 것이 좋습니다.