스프링 배치(Spring Batch)란?
Spring Batch는 엔터프라이즈 시스템의 운영에 있어 대용량 일괄처리의 편의를 위해 설계된 가볍고 포괄적인 배치 프레임워크다. Spring의 특성을 그대로 가져왔기 때문에 DI, AOP, 서비스 추상화 등 Spring 프레임워크의 3대 요소를 모두 사용할 수 있다.
보통 아래와 같은 경우 많이 사용한다.
- 대용량의 비즈니스 데이터를 복잡한 작업으로 처리해야하는 경우
- 특정한 시점에 스케쥴러를 통해 자동화된 작업이 필요한 경우 (ex. 푸시알림, 월 별 리포트)
- 대용량 데이터의 포맷을 변경, 유효성 검사 등의 작업을 트랜잭션 안에서 처리 후 기록해야하는 경우
Spring Batch는 로깅/추적, 트랜잭션 관리, 작업 처리 통계, 작업 재시작, 건너뛰기, 리소스 관리 등 대용량 레코드 처리 에필 수적인 재사용 가능한 기능을 제공한다. 또한 최적화 및 파티셔닝 기술을 통해 대용량 및 고성능 일괄 작업을 가능하게 하는 고급 기술 서비스 및 기능을 제공한다.
배치 애플리케이션은 다음의 조건을 만족해야만 한다.
- 대용량 데이터 : 대량의 데이터를 가져오거나, 전달하거나, 계산하는 등의 처리를 할 수 있어야 한다.
- 자동화 : 심각한 문제 해결을 제외하고는 사용자 개입 없이 실행되어야 한다.
- 견고성 : 잘못된 데이터를 충돌/중단 없이 처리할 수 있어야 한다.
- 신뢰성 : 무엇이 잘못되었는지를 추적할 수 있어야 한다. (로깅, 알림)
- 성능 : 지정한 시간 안에 처리를 완료하거나 동시에 실행되는 다른 애플리케이션을 방해하지 않도록 수행되어야 합니다.
간혹 Spring Batch와 Spring Quartz를 비교하곤 한다.
Quartz는 스케줄러의 역할이지, Batch와 같이 대용량 데이터 배치 처리에 대한 기능을 지원하지 않는다.
반대로 Batch 역시 Quartz의 다양한 스케줄 기능을 지원하지 않아서 보통은 Quartz + Batch를 조합해서 사용한다.
스프링 배치 아키텍처
- Application : Spring Batch를 사용하여 개발자가 작성한 모든 배치 작업과 사용자 정의 코드
- Batch Core : 배치 작업을 시작하고 제어하는 데 필요한 핵심 런타임 클래스를 포함
- Batch Infrastructure : 개발자와 애플리케이션에서 사용하는 일반적인 Reader와 Writer 그리고 RetryTemplate과 같은 서비스를 포함
스프링 배치는 계층 구조가 위와 같이 설계되어 있기 때문에 개발자는 Application 계층의 비즈니스 로직에 집중할 수 있고, 배치의 동작과 관련된 것은 Batch Core에 있는 클래스들을 이용하여 제어할 수 있다.
JobRepository
다양한 배치 수행과 관련된 수치 데이터와 잡의 상태를 유지 및 관리한다.
일반적으로 관계형 데이터베이스를 사용하며 스프링 배치 내의 대부분의 주요 컴포넌트가 공유한다.
실행된 Step, 현재 상태, 읽은 아이템 및 처리된 아이템 수 등이 모두 JobRepository에 저장된다.
Job
Job은 배치 처리 과정을 하나의 단위로 만들어 표현한 객체이고 여러 Step 인스턴스를 포함하는 컨테이너이다.
Job이 실행될 때 스프링 배치의 많은 컴포넌트는 탄력성(resiliency)을 제공하기 위해 서로 상호작용을 한다.
JobLauncher
Job을 실행하는 역할을 담당한다. Job.execute을 호출하는 역할이다.
Job의 재실행 가능 여부 검증, 잡의 실행 방법, 파라미터 유효성 검증 등을 수행한다.
스프링 부트의 환경에서는 부트가 Job을 시작하는 기능을 제공하므로, 일반적으로 직접 다룰 필요가 없는 컴포넌트다.
Job을 실행하면 해당 잡은 각 Step을 실행한다. 각 스텝이 실행되면 JobRepository는 현재 상태로 갱신된다.
Step
스프링 배치에서 가장 일반적으로 상태를 보여주는 단위이다. 각 Step은 잡을 구성하는 독립된 작업의 단위이다.
Step에는 Tasklet, Chunk 기반으로 2가지가 있다.
Tasklet
Step이 중지될 때까지 execute 메서드가 계속 반복해서 수행하고 수행할 때마다 독립적인 트랜잭션이 얻어진다. 초기화, 저장 프로시저 실행, 알림 전송과 같은 잡에서 일반적으로 사용된다.
Chunk
한 번에 하나씩 데이터(row)를 읽어 Chunk라는 덩어리를 만든 뒤, Chunk 단위로 트랜잭션을 다루는 것
Chunk 단위로 트랜잭션을 수행하기 때문에 실패할 경우엔 해당 Chunk 만큼만 롤백이 되고, 이전에 커밋된 트랜잭션 범위까지는 반영이 된다.
Chunk 기반 Step은 ItemReader, ItemProcessor, ItemWriter라는 3개의 주요 부분으로 구성될 수 있다.
ItemReader와 ItemProcessor에서 데이터는 1건씩 다뤄지고, Writer에선 Chunk 단위로 처리된다.
일반적으로 스프링 배치는 대용량 데이터를 다루는 경우가 많기 때문에 Tasklet보다 상대적으로 트랜잭션의 단위를 짧게 하여 처리할 수 있는 ItemReader, ItemProcessor, ItemWriter를 이용한 Chunk 지향 프로세싱을 이용한다.
배치를 구현할 때 권장되는 원칙 및 전략은 아래 링크에서 자세히 확인할 수 있다.
스프링 배치 사용 예제
1. Spring Batch Dependenciy 추가
dependencies {
...
implementation 'org.springframework.boot:spring-boot-starter-batch'
...
}
2. 애플리케이션 메인 클래스에 @EnableBatchProcessing(batch 기능 활성화) 어노테이션을 설정
@EnableBatchProcessing
@SpringBootApplication
public class SpringBatchApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBatchApplication.class, args);
}
}
3. Spring Batch 코드 작성
@Slf4j
@RequiredArgsConstructor
@Configuration // Spring Batch의 모든 Job은 @Configuration으로 등록해서 사용해야 한다.
public class SimpleJobConfiguration {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
@Bean
public Job simpleJob() {
return jobBuilderFactory.get("simpleJob")
.start(simpleStep1())
.build();
}
@Bean
public Step simpleStep1() {
return stepBuilderFactory.get("simpleStep1")
.tasklet((contribution, chunkContext) -> {
log.info(">>>>> This is simpleStep1");
return RepeatStatus.FINISHED;
})
.build();
}
}
애플리케이션을 실행해보면!
메타 테이블 데이터인 BATCH_JOB_INSTANCE가 존재하지 않는다는 에러와 함께 배치가 실패했다.
Spring Batch에선 메타 데이터 테이블들이 필요한데 테이블들이 생성되어있지 않아 실패한 것이다.
Spring Batch의 메타 데이터는 다음과 같은 내용들을 담고 있다.
- 이전에 실행한 Job이 어떤 것들이 있는지
- 최근 실패한 Batch Parameter가 어떤 것들이 있고, 성공한 Job은 어떤 것들이 있는지
- 다시 실행한다면 어디서부터 시작하면 될지
- 어떤 Job에 어떤 Step들이 있었고, Step들 중 성공한 Step과 실패한 Step들은 어떤 것들이 있는지
기본적으로 H2 DB를 사용할 경우엔 Boot가 실행될 때 자동으로 생성해주지만, MySQL이나 Oracle과 같은 DB를 사용할 때는 자동으로 생성되지 않는다. 나는 MySQL을 사용하였기 때문에 배치가 실패한 것이다.
MySQL을 사용하려면 메타 테이블을 직접 생성하면 된다.
아까 추가한 Spring Batch 라이브러리에 org.springframework.batch.core 폴더에 가보면 schema-mysql.sql 파일이 있을 것이다.
요 파일에 작성된 SQL을 그대로 실행하면 메타 테이블을 생성할 수 있다.
생성 후에 다시 애플리케이션을 실행해보면!
정상적으로 Job이 실행된 것을 확인할 수 있다.
※ 전체 코드는 GitHub에서 확인하실 수 있습니다.
※ 참고 블로그 https://jojoldu.tistory.com/325, https://deeplify.dev/back-end/spring/batch-tutorial
'Spring' 카테고리의 다른 글
스프링 배치(Spring Batch) 활용하기 (0) | 2022.02.22 |
---|---|
스프링 배치(Spring Batch) 메타 데이터(Meta-Data) 살펴보기 (0) | 2022.02.22 |
H2 Database를 활용해 In-memory Database 사용하기 (0) | 2022.02.07 |
Spring Boot 유효성 검증 어노테이션 만들기 (0) | 2022.01.28 |
Junit 테스트 시 테스트 목록 보이게 하기(IntelliJ IDEA) (0) | 2021.12.19 |