spring batch 의 스코프 - @JobScope, @StepScope
JobScope 와 StepScope 는 spring batch 에서 chunk 프로세스를 이용해 개발한다면 기본적으로 알아야 하는 스코프이다.
프로젝트 하다가 해당 스코프에 대한 이해도가 부족해 에러가 났던 경험이 있어서 공부하면서 블로그에 정리했다.
Spring 의 기본 빈 스코프
1. Singleton (기본 스코프)
- 애플리케이션 컨텍스트당 하나의 인스턴스를 생성하고 재사용
- 빈이 애플리케이션 시작 시점에 즉시 초기화
2. Prototype
- 요청할 때마다 새로운 인스턴스 생성
- 배치 작업과는 잘 맞지 않는 타입
3. Request/Session/Custom Scope
Spring Batch 의 스코프 이해하기
spring 에서 scope 는 spring 컨테이너에서 관리되는 빈(bean) 의 생명 주기를 정의한다.
일반적으로 bean 은 싱글턴으로 관리되며, 애플리케이션 실행 내내 한 개의 인스턴스만 유지한다.
스프링 배치는 배치 작업이 가지고 있는 특수성을 반영하기 위해 spring 이 제공하는 빈 을 제외하고 추가적인 스코프가 존재한다. 스프링 배치는 job, step 단위로 실행이 되는데, 이 작업 단위 별로 스코프 설정이 가능하다.
즉 빈의 생명주기가 job을 실행할 때, 또는 step 을 실행할 때 맞춰서 생성하도록 가능하다.
spring batch 에서는 job 이나 step 에 따라 빈의 생명 주기를 다르게 관리해야 할 때가 있다. 이를 위해 @JobScope와 @StepScope를 사용한다.
StepScope 를 이용한 동적 파라미터 처리 예시
예를 들어, read 할 때 baseDt 를 파라미터로 받아서 실행하고자 한다면, 아래와 같이 코드를 작성할 수 있다.
@Bean
public ItemReader<MyData> myBatisCursorReader(String baseDt) {
MyBatisCursorItemReader<MyData> reader = new MyBatisCursorItemReader<>();
reader.setQueryId("com.example.mapper.MyDataMapper.fetchDataByBaseDt");
reader.setParameterValues(Map.of("baseDt", baseDt));
return reader;
}
그러나 이러한 방식으로 코드를 작성하게 되면 처음에 빈을 초기화 후 더이상 초기화가 이루어지지 않기 때문에 실행 시점에 주입된 baseDt 외에 동적으로 처리가 불가능하다.
이를 해결하는 방법이 스코프다.
StepScope 의 경우 스텝이 실행되는 동안 생성되고 유지되며 step 이 끝나면 소멸되는 빈 스코프이다. @ StepScope 을 사용하며 빈을 정의하면 Step 내에서 동적으로 값이 변경되는 상황(예: JobParameters)에서 매우 유용하다.
@Bean
@StepScope
public ItemReader<MyData> myBatisCursorReader(
@Value("#{jobParameters[baseDt]}") String baseDt) {
MyBatisCursorItemReader<MyData> reader = new MyBatisCursorItemReader<>();
reader.setQueryId("com.example.mapper.MyDataMapper.fetchDataByBaseDt");
reader.setParameterValues(Map.of("baseDt", baseDt));
return reader;
}
@JobScope, @StepScope 의 Lazy Initialization (지연 초기화)
JobScope 와 StepScope 는 둘 다 빈이 job 과 step 이 실행되는 시점에 초기화가 이루어진다. 이를 위해 spring 에서는 프록시 객체를 생성하여 실제 빈 생성하는 것을 지연시킨다. 이러한 지연 초기화 덕분에 동적으로 파라미터를 받아서 수행할 수 있게 된다.
StepScope 의 경우 step 실행마다 고유의 빈이 생성되기 때문에 멀티스레드 환경에서 안전하다.
JobScope 의 경우 하나의 같은 job 범위 내에서 여러 step 간의 데이터 공유가 가능하다.