스프링배치는 코커와 인프라스트럭처를 애플리케이션이 감싸는 구조로 되어 있다.
개발자가 개발한 코드
배치 처리 구축에 사용되는 모든 사용자 코드 및 구성을 포함한다.
업무 로직과 서비스 및 잡 구조화와 관련된 구성까지도 애플리케이션 레이어에 포함된다.
애플리케이션 레이어가 최상위에 있는 것이 아니라, 다른 두 레이어인 코어와 인프라스트럭처를 애플리케이션이 감싸고 있는 것으로 이해해야 한다.
애플리케이션 레이어는 그 다음 레이어인 코어 레이어와 상호작용하는 데 대부분의 시간을 소비한다.
배치 영역을 구성하는 실제적인 컴포넌트로 구성
배치 도메인을 정의하는 모든 부분이 포함된다.
코어 컴포넌트의 요소에는 Job 및 Step 인터페이스와, 잡 실행에 사용되는 인터페이스, 즉 JobLauncher 및 JobParameters 등이 있다.
ItemReadr, IremWriter 및 재시작과 관련된 문제 해결 가능한 클래스와 인터페이스 제공
배치 처리를 위해 파일, DB 등으로부터 읽고 쓸 수 있고,
잡 수행에 실패한 이후 재시도될 때 어떤 일을 수행할지 다룰 수 있다.
스프링 배치는 일반적으로 스케줄러이거나, 스케줄링 기능을 갖고 있다고 오해할 수 있으나 그렇지 않다.
프레임워크 내에는 주어진 시간 또는 주어진 이벤트에 따라 잡이 실행되도록 스케줄링 하는 기능이 없다. 크론이나 쿼츠, 컨트롤-M 같은 엔터프라이즈 스케줄러를 이용하는 등 잡을 구동 시키는 여러 방법이 있으나, 프레임워크 내에 존재하지는 않는다.
중단이나 상호작용 없이, 처음부터 끝까지 실행되는 처리
여러 개의 스텝이 모여 잡을 이룬다.
각 스텝에는 관련된 입력과 출력이 있을 수 있다.
// 스프링 배치 잡 정의 예제
@Bean
public AccountTasklet accountTasklet() {
return new AccountTasklet();
}
@Bean
public job accountJob() {
Step accountStep =
this.stepBuilderFactory
.get("accountStep")
.tasklet(accountTasklet())
.build();
return this.jobBuilderFactory
.get("accountJob")
.start("accountStep")
.build();
}
위 소스 내에 두 개의 Bean이 작성되었다.
1) AccountTasklet : 커스텀 컴포넌트. 스텝이 동작하는 동안 비즈니스 로직 수행
스프링 배치는 AccountTasklet이 완료될 때까지 단일 메서드(excute 메서드)를 반복해서 호출하는데, 이때 각각은 새 트랜잭션으로 호출된다.
2) 실제 스프링 배치 잡 : 팩토리가 제공하는 빌더를 사용해, AccountTasklet을 감싸는 스텝 하나를 생성한다. 그 다음 Job Builder를 사용해 스텝을 감싸는 잡을 생성한다.
스프링 부트는 애플리케이션 기동 시 해당 잡을 찾아내 자동으로 실행시킨다.
스프링 배치는 스프링 기반으로 구축되었기 때문에, 의존성 주입 / AOP(Aspect-Oriented Programming) / 트랜잭션 관리 / 일반적인 작업(JDBC, JMS, 전자 메일 등) 을 위한 기능을 제공한다.
책 예제코드 > https://github.com/Apress/def-quide-spring-batch

자바나 XML을 사용해 구성된 배치 잡은, 상태를 수집하고 이전 상태 -> 다음 상태로 전환된다.
개념적으로 스프링 배치 잡은 상태 기계(State Machine)에 지나지 않는다.
스프링배치에서 가장 일반적으로 상태를 보여주는 단위는 스텝이다.
ex) 업무 시간 이후에 고객의 은행계좌 처리
- 스텝1 : 다른 시스템에서 수신한 거래 정보 파일 읽어와 DB에 저장
- 스텝2 : 모든 입금 정보를 계좌에 반영
- 스텝3 : 모든 출금 정보를 계좌에 반영
잡을 구성하는 독립된 작업의 단위
Tasklet 기반 스텝과 Chunk 기반 스텝이 있으며, 태스크릿 기반 스텝의 구조가 더 간단하다.
Tasklet을 구현하여 사용할 수 있으며, 스텝이 중지될 때까지 excute 메소드가 계속 반복해서 수행된다. 이 때 excute 메소드를 호출할 때마다 독립적인 트랜잭션이 얻어진다.
초기화, 저장 프로시저 실행, 알림 전송 등과 같은 잡에서 일반적으로 사용된다.
태스크릿 기반 스텝에 비해 구조가 약간 더 복잡하며, 아이템 기반의 처리에 사용한다.
ItemReader / ItemProcesspr / ItemWriter 라는 3개의 주요 부분으로 구성되며, 이 때 ItemProcessor는 필수는 아니다.
ItemReader와 ItemWriter 만으로도 스텝 실행이 가능한데, 이와 같은 스텝은 일반적으로 데이터 마이그레이션 잡에 많이 사용된다.
스프링의 잡 구조화 방법이 갖는 장점 : 각 스텝이 서로 독립적으로 처리될 수 있도록 분리되어 있다.
유연성 / 유지보수성 / 확장성 / 신뢰성 확보 가능
스프링 배치 아키텍처 내에서 공유되는 주요 컴포넌트 가운데 하나.
배치 수행과 관련된 다양한 수치 데이터(시작 시간, 종료 시간, 상태, 읽기/쓰기 횟수 등) 및 잡의 상태를 유지 관리한다.
JobRepository는 일반적으로 관계형 데이터베이스를 사용하며, 스프링 배치 내의 대부분의 주요 컴포넌트가 이를 공유한다.

잡을 실행하는 역할 담당. (Job.excute 메서드 호출)
또한 잡의 재실행 가능여부 확인 / 잡의 실행 방법(현재 스레드에서 수행할지, 스레드 풀을 통해 실행할지 등) / 파라미터 유효성 검증 등의 처리를 수행한다.
잡 실행 -> 해당 잡은 각 스텝 실행 -> 각 스텝이 실행되면 JobRepository는 현재 상태로 갱신된다.
즉 실행된 스텝, 현재 상태, 읽은 아이템 및 처리된 아이템 수 등이 모두 JobRepository에 저장된다.
잡과 스텝의 처리 방식은 매우 유사한데, 잡은 구성된 스텝 목록에 따라 각 스텝을 실행한다.
여러 아이템으로 이뤄진 청크의 처리가 스텝 내에서 완료될 때 -> 스프링 배치는 JobRepository 내에 있는 JobExecution 또는 StepException을 현재 상태로 갱신한다.
스텝은 ItemReader가 읽은 아이템의 목록을 따라간다. 스텝이 각 청크를 처리할 때 마다 JobRepository 내 StepExecution의 스탭 상태가 업데이트 된다.
현재까지의 커밋 수, 시작 및 종료시간, 기다 다른 정보 등이 JobRepository에 저장되며, 잡 또는 스텝이 완료되면 JobExecution 또는 StepExecution이 최종 상태로 업데이트 된다.
스프링 배치 잡의 논리적인 실행(Logical Execution)을 의미.
ex) 거래명세서를 생성하는 statementGenerator 라는 잡이 다른 파라미터로 실행될 때마다 새로운 JobInstance가 생성된다.
스프링 배치 잡의 실제 실행(execution)을 의미.
잡을 구동할 때마다 새로운 JobExecution을 얻게 된다. 그러나 잡 실행에 실패한 이후 다시 실행하면, 해당 실행은 앞선 것과 동일한 논리적 실행(파라미터가 동일함)이므로 새로운 JobInstance를 얻을 수 없으나, 두 번째 실제 실행을 추적하기 위한 새로운 JobExecution을 얻을 것이다.
즉 JobInstance는 여러 개의 JobExecution을 가질 수 있다.
스텝의 실제 실행(execution)을 의미.
그러나 StepInstance 라는 개념은 존재하지 않는다.
JobExecution은 여러 개의 StepExecution과 연관된다.
스프링 배치에서 잡은 청크라는 블록 단위로 처리되도록 구성되며, 각 청크는 독립적인 트랜잭션으로 처리된다. 일반적으로 각 청크는 연속해서 처리된다.
입력 파일의 데이터를 읽어오는 한 개의 스텝과, DB에 저장하는 일을 하는 한 개의 스텝이 있으나 서로 관련이 없을 경우, 각각 독립 실행되게끔 처리
마스터 노드에서 표준 ItemReader를 사용해 이뤄진다.
입력은 RabbitMQ와 같은 메시지 브로커를 통해 ItemProcessor로 전송된다.
처리가 완료되면 워커는 업데이트된 아이템을 다시 마스터로 보내거나 직접 기록한다.
이 방식은 네트워크 사용량이 많아질 수 있음에 유의해야 하며, 실제 처리에 비해 I/O 비용이 적은 시나리오에 적합하다.
@EnableBatchProcessing
@SpringBootApplication
public class HelloWorldApplication {
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Bean
public Step step() {
return this.stepBuilderFactory.get("step1")
.tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution,
ChunkContext chunkContext) {
System.out.println("Hello, World!");
return RepeatStatus.FINISHED;
}
}).build();
}
@Bean
public Job job() {
return this.jobBuilderFactory.get("job")
.start(step())
,build();
}
public static void main(String[] args) {
SpringApplication.run(HelloWorldApplication.class, args);
}
}
@EnableBatchProcessing 애너테이션을 사용함으로써 다음과 같은 컴포넌트를 직접 포함시킬 필요가 없어진다.
@SpringBootApplication 애너테이션은 @ComponentScan + @EnableAutoConfiguration 을 결합한 메타 애너테이션이다. 데이터 소스 뿐만 아니라 스프링 부트 기반의 적절한 자동 구성을 만들어 준다.
클래스 정의가 끝난 이후에, 스프링 배치가 제공하는 두 개의 빌더(잡 빌더, 스텝 빌더)를 자동 와이어링 한다. 각 빌더는 @EnableBatchProcessing