개요
Spring Batch는 대량 데이터를 안정적으로 처리하는 Batch Application을 만들기 위한 Spring 기반 프레임워크이다.
연말 정산, 은행 이자 시스템, 주기별 회원 권한 조정, 데이터 일괄 삭제 등등…
INFO
Batch란 “일정 시간 동안 대량의 데이터를 한 번에 처리하는 방식”을 의마한다. (실시간 처리와 반대 개념)
대용량 데이터를 처리하는 중간에 프로그램이 멈출 수 있는 장치를 마련해야 하기 때문에 프레임워크를 사용하는 것이다.
Spring Batch에서는 아래와 같은 기능들을 제공한다.
- Transaction 관리
- Logging / Tracing
- 실행 상태 관리
- 실패 후 재시작
- Skip
- 통계
- Resource 관리
- 병렬/분산 처리
Spring Batch와 Scheduler의 차이점
Batch는 일정 Scheduler와 같이 사용할 수 있도록 설계되었다.
그렇다고 해서 시간 특정 작업을 수행하는 Scheduler와 같은 개념이 아니다.
Batch는 단순히 데이터를 그룹화하여 일괄 처리하는 방법을 말한다.
그 중에서도 배치에서 가장 중요하게 생각되는 핵심은 다음과 같다.
- 어떤 작업까지 수행했는지 파악할 수 있어야 한다.
- 이미 수행한 작업에 대해서는 중복 수행하지 않도록 주의한다.
동작 방식
Caution
해당 방식은 Spring Batch 6.0을 기반으로 작성됐습니다.

- JobLauncher: 하나의 배치 작업을 실행시키는 시작점
- Job:
읽기 → 처리 → 쓰기과정을 정의한 배치 작업 - Step: 실제 하나의
읽기 → 처리 → 쓰기작업을 정의한 부분 - ItemReader: 읽어오는 부분
- ItemProcessor: 처리하는 부분
- ItemWriter: 쓰는 부분
- JobRepository: 얼만큼 했는지, 특정 일자 배치를 이미 했는지 메타 데이터에 기록하는 부분
JobLauncher
JobLauncher는 Spring Batch 6.0부터 Deprecated되었기에 대신 JobOperator를 사용하면 된다.
// 전
jobLauncher.run(jobRegistry.getJob("firstJob"), jobParameters);
// 후
jobOperator.start(jobRegistry.getJob("firstJob"), jobParameters);왜
JobLauncher가 없어졌을까?기존에
JobLauncher는 단순히Job을 실행하는 역할에 그쳤다. 반면JobOperator는Job실행/중지/재시작 등을 운영할 수 있었다. 인프라 간소화를 위해JobLauncher의 기능을 포함한JobOperator만을 남긴 것이다.
JobRegistry
Spring Batch 6.0부터는 JobRegistry가 선택적으로 사용하도록 변경되었다.
ApplicationContext에 있는 Job Bean들을 스스로 찾아 등록한다.
Quote
The
JobRegistryis now optional, and smart enough to register jobs automatically, so there is no need to define a separateJobRegistrySmartInitializingSingletonbean.
그렇기에 자동으로 Bean등록을 하지 않으므로 기존 코드를 유지하고 싶다면 별도의 Bean을 생성하자.
@Configuration
public class BatchConfig {
@Bean
public JobRegistry jobRegistry() {
return new MapJobRegistry();
}
}Step
- Chunk 방식 (Read → Process → Write)
- Tasklet 방식: Tasklet 방식은 아주 간단한 동작만 수행, 데이터 조건을 걸어야 하는 경우 거의 사용하지 않음
- 사용 예시: 단순한 파일 삭제, 값 초기화 등등
Chunk 단위 처리 과정
청크값을 10으로 설정했다면 아래와 같이 작업을 수행한다.
(Read) x 10 → (Write) x 10 → Write
Skip
noSkip()메서드 미지원Spring Batch 6 부터는 책임 단순화를 위해
noSkip()을 지원하지 않는다.
그렇기에SkipPolicy를 중심으로 Skip 동작의 세부 동작을 제어하도록 한다.
FaultTolerantStepBuilder→ChunkOrientedStepBuilder
SKip은 과정 중 예외가 발생하게 되면 예외를 특정 수 까지 건너 뛸 수 있도록 설정하는 방식이다.
@Bean
public Step sixthStep() {
return new StepBuilder("sixthStep", jobRepository)
.<BeforeEntity, AfterEntity> chunk(10, platformTransactionManager)
.reader(beforeSixthReader())
.processor(middleSixthProcessor())
.writer(afterSixthWriter())
.faultTolerant()
.skip(Exception.class) // EXception을 Skip
.noSkip(FileNotFoundException.class) // 그러나 해당 Exception은 Skip하지 않음
.noSkip(IOException.class) // 그러나 해당 Exception은 Skip하지 않음
.skipLimit(10) // 스킵할 구간
.build();
}SkipPolicy를 구현하여 스킵 정책을 커스텀할 수 있다.
@Configuration
public class CustomSkipPolicy implements SkipPolicy {
@Override
public boolean shouldSkip(@NonNull Throwable t, long skipCount) throws SkipLimitExceededException {
if (t instanceof FileNotFoundException) return false;
if (t instanceof IOException) return false;
return true;
}
}@Bean
public SkipPolicy fourthSkipPolicy() {
return (t, skipCount) -> {
if (t instanceof FileNotFoundException) return false;
if (t instanceof IOException) return skipCount < 10;
return true;
};
}Retry
noRetry()메서드 미지원Spring Batch 6부터는
noRetry()메서드 또한 기본 구현체에서 지원하지 않기에RetryPolicyBean을 등록하여retryPolicy()에 추가하자. 의존성은org.springframework.core.retry.RetryPolicy이다.
FaultTolerantStepBuilder→ChunkOrientedStepBuilder
Retry는 Step의 과정 중 예외가 발생했을 때 특정 수까지 반복 시도할 수 있도록 설정하는 방법이다.
@Bean
public Step fourthStep() {
System.out.println("fourth step");
return new StepBuilder("fourthStep", jobRepository)
.<Row, AfterEntity>chunk(10)
.transactionManager(transactionManager)
.reader(excelReader())
.processor(fourthProcessor())
.writer(fourthAfterWriter())
.skipPolicy(fourthSkipPolicy())
.retryLimit(3) // 몇번 재시도
.retry(BatchCustomException.class) // 재시도할 예외
.noRetry(FileNotFoundException.class)
.build();
}RetryPolicy를 통해서도 재시도 정책을 구현할 수 있다.
@Bean
public RetryPolicy fourthRetryPolicy() {
return RetryPolicy.builder()
.maxRetries(3)
.includes(IOException.class, SQLException.class) // 포함
.excludes(FileNotFoundException.class) // 제외
.build();
}Step Listener
stepListener는 Step의 실행 전후에 특정 작업을 수행 시킬 수 있는 방법이다.
로그를 남기거나 다음 Step이 준비가 되었는지, 이번 Step과 다음 Step이 의존되는 경우 변수 정리를 진행힐 수 있다.
@Bean
public StepExecutionListener stepExecutionListener() {
return new StepExecutionListener() {
@Override
public void beforeStep(StepExecution stepExecution) {
System.out.println("before step");
StepExecutionListener.super.beforeStep(stepExecution);
}
@Override
public @Nullable ExitStatus afterStep(StepExecution stepExecution) {
System.out.println("after step");
return StepExecutionListener.super.afterStep(stepExecution);
}
};
}