공부/Spring batch

spring batch 의 스코프 - @JobScope, @StepScope

ompeom 2024. 12. 19. 15:45

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 간의 데이터 공유가 가능하다.