안녕하세요. 이번에는 지난번 글에 이어서 BATCH_JOB_EXECUTION 에 대해서 설명해보고자 합니다.
우선 BATCH_JOB_EXECUTION 테이블을 조회해 보겠습니다.

해당 테이블에는 여러가지 row 가 보입니다. 그중에서도 빨간색 칠한 곳은 이전 시간에 저희가 테스트 했던, 파라미터가 없는 simpleJob, requestDate=20250622 파라미터로 실행했던 simpleJob, requestDate=20250623 파라미터로 실행했던 simpleJob 까지 이렇게 3개의 실행 데이터입니다.

이렇게 보면 BATCHJOB_INSTANCE와 크게 차이가 없어 보이니다. 그런데 첫번째 사진을 보면서 눈치 채신 분들고 계시겠지만, BATCH_JOB_EXECUTION 테이블은 JOB_INSTACNE가 성공/실패 한 모든 내역을 가지고 있습니다. 즉, JOB_EXECUTION와 JOB_INSTANCE는 부모-자식 관계입니다.
그러다면, 진짜 그러한지 실습을 통해서 한번 확인해보겠습니다.
simpleJob 코드를 아래와 같이 변경해보겠습니다.
// Job 정의
@Bean
public Job simpleJob(JobRepository jobRepository, Step simpleStep1, Step simpleStep2) {
return new JobBuilder("simpleJob", jobRepository)
.start(simpleStep1)
.next(simpleStep2)
.build();
}
// Step1 정의
@Bean
@JobScope
public Step simpleStep1(JobRepository jobRepository,
PlatformTransactionManager transactionManager,
@Value("#{jobParameters[requestDate]}") String requestDate) {
return new StepBuilder("simpleStep1", jobRepository)
.tasklet((contribution, chunkContext) -> {
throw new IllegalArgumentException("step1에서 실패합니다.");
}, transactionManager)
.build();
}
// Step2 정의
@Bean
@JobScope
public Step simpleStep2(JobRepository jobRepository,
PlatformTransactionManager transactionManager,
@Value("#{jobParameters[requestDate]}") String requestDate) {
return new StepBuilder("simpleStep2", jobRepository)
.tasklet((contribution, chunkContext) -> {
log.info(">>>>> This is Step2");
log.info(">>>>> requestDate = {}", requestDate);
return RepeatStatus.FINISHED;
}, transactionManager)
.build();
}
이제 intelliJ 에서 requestDate=20250624 로 바꿔주고 Job을 실행해 보겠습니다.

보시는거와 같이 발생시킨 Exception 이 발생 하였고, Job 이 실패했습니다. 자 그럼 BATCH_JOB_EXECUTION 테이블은 어떻게 변화되었는지 볼까요? 유추해보자면, 실패 로우 1건만 있어야 하는데 과연 있을까요?

보시는 것처럼 실패한 row 가 하나 생겼습니다. 데이터를 들여다 보면, 4번째 JOB_INSTACNE를 FK로 물고 있는 EXECUTION이 FAILED 라는 것을 확인할 수 있습니다.
소스를 수정해서 Job을 성공 시켜보겠습니다.
// Job 정의
@Bean
public Job simpleJob(JobRepository jobRepository, Step simpleStep1, Step simpleStep2) {
return new JobBuilder("simpleJob", jobRepository)
.start(simpleStep1)
.next(simpleStep2)
.build();
}
// Step1 정의
@Bean
@JobScope
public Step simpleStep1(JobRepository jobRepository,
PlatformTransactionManager transactionManager,
@Value("#{jobParameters[requestDate]}") String requestDate) {
return new StepBuilder("simpleStep1", jobRepository)
.tasklet((contribution, chunkContext) -> {
log.info(">>>>> This is Step1");
log.info(">>>>> requestDate = {}", requestDate);
return RepeatStatus.FINISHED;
}, transactionManager)
.build();
}
// Step2 정의
@Bean
@JobScope
public Step simpleStep2(JobRepository jobRepository,
PlatformTransactionManager transactionManager,
@Value("#{jobParameters[requestDate]}") String requestDate) {
return new StepBuilder("simpleStep2", jobRepository)
.tasklet((contribution, chunkContext) -> {
log.info(">>>>> This is Step2");
log.info(">>>>> requestDate = {}", requestDate);
return RepeatStatus.FINISHED;
}, transactionManager)
.build();
}

Job 정상적으로 실행이 되었습니다. BATCH_JOB_EXECUTION 테이블을 볼까요?

정상적으로 성공한 상태가 COMPLETE 인 row 가 생긴 것을 볼 수 있습니다.
BATCH_JOB_EXECUTION 와 BATCH_JOB_INSTANCE 의 차이가 보이시나요?
BATCH_JOB_EXECUTION의 JOB_INSTANCE_ID 컬럼을 보시면 같은 ID (4) 를 가진 2개의 ROW가 보입니다.
그 중 첫번째 ROW는 STATUS 가 FAILED 이지만, 2번째 ROW는 COMPLETED 입니다.
Job Parameter requestDate=20250624 생성된 BATCH_JOB_INSTACNE (id=4) 가 2번 실행되었고, 첫번째는 실패, 두번째는 성공했다는 것을 알 수 있습니다.
여기서 우리가 꼭 알아야 할 것은 동일한 Job Parameter로 2번 실행했는데 같은 파라미터로 실행되었다는 에러가 발생하지 않았다는 것 입니다.
Spring Batch는 동일한 Job Parameter로 성공한 기록이 있을때만 재수행이 안된다는 것을 알 수 있습니다.
이 외에도 Spring Batch 에서 제공하는 여러가지 테이블이 있지만, 하나만 더 보자면, 우리가 Job Parameter 로 넘긴 파라미터들이 저장되는 테이블이 있는데요 BATCH_JOB_EXECUTION_PARAMS 테이블 입니다.
해당 테이블을 조회해 볼까요? 보시는 거와 같이 우리가 테스트 할 때 넘긴 Parameter Value 들이 담긴 것을 볼 수 있습니다.

이외에도 STEP 에 관련 된 테이블이 있습니다. 꼭 조회해서 확인해 보시면, 좋을 것 같습니다.
Reference
https://jojoldu.tistory.com/325
https://docs.spring.io/spring-batch/reference/job/configuring.html