안녕하세요.
Spring Batch를 단순히 ‘쓰는’ 단계를 넘어 ‘설계’하는 단계가 되면, 필연적으로 건드려야 하는 두 가지 빈(Bean)이 있습니다.
바로 배치를 실행하는 녀석(JobLauncher)과 저장하는 녀석(JobRepository)입니다.
기본 설정을 그대로 써도 되지만, “배치를 비동기로 실행하고 싶다”거나 “트랜잭션 격리 수준을 바꾸고 싶다”면 이 둘을 커스터마이징해야 합니다.

1. JobLauncher: 동기 vs 비동기
기본적으로 JobLauncher는 동기(Synchronous) 방식입니다. 즉, 배치가 끝날 때까지 요청한 스레드(main이나 HTTP 요청 스레드)가 대기합니다.
하지만 웹 API를 통해 배치를 실행시켰는데, 배치가 1시간 동안 돈다면? 클라이언트는 타임아웃 에러를 받게 될 겁니다. 이럴 때 비동기(Asynchronous) 실행이 필요합니다.
비동기 JobLauncher 설정
@Configuration
public class BatchConfig {
@Bean
public JobLauncher asyncJobLauncher(JobRepository jobRepository) throws Exception {
TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
jobLauncher.setJobRepository(jobRepository);
// 핵심: 비동기 TaskExecutor 설정
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
}
이렇게 설정된 asyncJobLauncher를 주입받아 run()을 호출하면, 배치는 별도 스레드에서 돌고 run() 메서드는 즉시 JobExecution 객체를 반환하며 리턴됩니다. (ExitStatus는 ‘UNKNOWN’ 상태로 반환됨)
2. JobRepository: 메타 데이터 저장소
JobRepository는 배치의 모든 실행 이력(CRUD)을 담당합니다. Spring Boot가 자동으로 만들어주지만, 트랜잭션 매니저나 격리 수준을 조정해야 할 때가 있습니다.
커스텀 JobRepository 설정 (Spring Batch 5)
Spring Batch 5부터는 BatchConfigurer를 상속받는 방식이 아니라, 직접 빈을 등록하는 방식이 권장됩니다.
@Configuration
public class BatchRepoConfig {
@Bean
public JobRepository jobRepository(DataSource dataSource, PlatformTransactionManager transactionManager) throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource);
factory.setTransactionManager(transactionManager);
// 1. 격리 수준 변경 (기본값: SERIALIZABLE)
// 성능을 위해 READ_COMMITTED로 낮추는 경우가 많음
factory.setIsolationLevelForCreate("ISOLATION_READ_COMMITTED");
// 2. 테이블 접두사 변경
factory.setTablePrefix("SYSTEM_BATCH_");
factory.afterPropertiesSet();
return factory.getObject();
}
}
왜 격리 수준을 낮추나요?
기본값인 SERIALIZABLE은 데이터 정합성은 완벽하지만, 락(Lock)을 심하게 잡습니다. 여러 배치가 동시에 돌거나, 짧은 주기로 실행될 때 메타 테이블 경합으로 인한 데드락이나 타임아웃이 발생할 수 있습니다. 이를 완화하기 위해 실무에서는 READ_COMMITTED를 많이 사용합니다.
3. 요약 및 활용 전략

- JobLauncher:
- 기본: CLI에서 실행하거나, 순차적으로 실행할 때 사용.
- 비동기: 웹 Admin 페이지에서 “배치 실행” 버튼을 누르고 바로 응답을 줘야 할 때 사용.
- JobRepository:
- 기본: 대부분의 경우 그대로 사용.
- 커스텀: DB 락 문제가 발생하거나, 메타 테이블 이름을 바꿔야 할 때 튜닝.
이 두 가지를 자유자재로 다룰 수 있다면, 여러분은 Spring Batch의 ‘엔진’을 튜닝할 줄 아는 엔지니어입니다.




