개발 기록

> [Spring Batch] Scope(@StepScope, @JobScope) & Job Parameter - 1. Job Parameter 본문

Spring

> [Spring Batch] Scope(@StepScope, @JobScope) & Job Parameter - 1. Job Parameter

1z 2022. 10. 17. 11:25

1.  개요  

Spring Batch 의 경우 외부 혹은 내부에서 파라미터를 받아 JobInstance에 작업 매개변수를 제공 할 수 있는데
이 파라미터를 Job Parameter 라고 한다.  Job Parameter를 사용하기 위해선 항상 Spring Batch 전용 Scope를 선언해야만 하는데, 크게 @StepScope와 @JobScope 2가지가 있다.

 

 

2.  JobParameter 

 

(1) JobParameter 활용  방법- @Value

@Value("#{jobParameters[파라미터명]}")

 

1. Reader를 호출하는 Step에서는 null 이라는 임시값을 강제로 등록

@Bean
@JobScope
public Step step() {
    return stepBuilderFactory.get(JOB_NAME)
            .<?, ?>chunk(chunkSize)
            .reader(reader(null))

 

2. 실제 Reader에서는 null 이 넘어와도 @Value("#{jobParameters[createDate]}") 로 인해 JobParameter 값으로 교체되어 사용

@Bean
@StepScope
public JpaPagingItemReader<Product> reader(@Value("#{jobParameters[createDate]}") String createDate)

 

3.  Spring Batch JobParameter는 LocalDate를 지원하지 않으니, 일단 문자열로 받아서 LocalDate로 변환한다.

 

 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); 
    LocalDate createDate = LocalDate.parse(createDateStr, formatter); // (3)
​

 

 

문제점

1. 형변환 (LocalDate) 된 Parameter 값을 재사용 불가 => Reader/Processor/Writer 생성 메소드 혹은 별도 클래스 에서 각자 형변환을 해야한다.

2. Job Parameter 확장성이 떨어짐 => Reader에서 파라미터를 받아 본인이 원하는 형태로 분리하는 로직도 함께 갖고 있어야 하는 상황이 생긴다.




(2) JobParameter 활용  방법- JobParameters Class

 

Spring Batch 프레임워크의 JobParameters 클래스를 사용하면 다음과 같이 사용자, 시작 시간 및 실행 매개변수와 같은 모든 매개변수를 작업 인스턴스에 전달할 수 있다.

JobParameters jobParameters = new JobParametersBuilder() 
        .addString("user", user) 
        .addDate("startDate",new Date()) 
        .toJobParameters(); 

jobLauncher.run(batchJob, jobParameters);

 

 

JobParameter를 담을 클래스에서 실제 JobParameter값을 주입 받는 방법에는 Setter / Constructor / Field 3가지가 있다.

 

 

  2-1. Setter 주입

1. 배치 코드에서 사용하는 JobParameter를 클래스로 뽑아낸다.

@Getter
@NoArgsConstructor
public class CreateDateJobParameter {

   // (1) Enum, Long, String의 타입은 직접 필드로 받아도 형변환이 가능
    @Value("#{jobParameters[name]}") 
    private String name;

    private LocalDate createDate;

    @Value("#{jobParameters[createDate]}") // (2)
    public void setCreateDate(String createDate) {
       this.createDate = LocalDate.parse(createDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
   }
}

 

2. 위에서 만든 parameter 클래스는 Job 클래스에서 아래와 같이 @JobScope를 가진 Bean으로 등록하여 사용한다. 

* JobParameter의 @Value로 값을 받기 위해서는 @JobScope, @StepScope 필수

@RequiredArgsConstructor
@Configuration
public class JobParameterExtendsConfiguration {

    ...
    private final CreateDateJobParameter jobParameter; 
    @Bean
    @JobScope
    public CreateDateJobParameter jobParameter() {
        return new CreateDateJobParameter();
    }

 

3. Reader 메소드에서는 Job 클래스 내부에 있는 jobParameter 변수를  바로 사용하면 된다.

형변환은 이미 JobParameter 생성 시점에 되어있으니 별도로 형변환을 할 필요가 없다.

@Bean
@StepScope
public JpaPagingItemReader<Product> reader() {

    Map<String, Object> params = new HashMap<>();
    params.put("createDate", jobParameter.getCreateDate()); 
    params.put("name", jobParameter.getName());
...
}

 

 

  2-2. Constructor 주입

 

1. 생성자로 값을 주입 받는다. 

@Getter
public class CreateDateJobParameter {

    private LocalDate createDate;
    private String name;

    public CreateDateJobParameter(String createDateStr, String name) {
        this.createDate = LocalDate.parse(createDateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        this.name = name;
    }
}

 

2. JobParameter 클래스를 생성하는 메소드에서 @Value 로 파라미터를 받고 이를 생성자 인자로 넘겨 준다.

이때는 받은 형태 그대로 (문자열) 넘겨주고, 이를 어떻게 변환할지는 JobParameter 클래스가 처리한다.

@RequiredArgsConstructor
@Configuration
public class JobParameterExtendsConfiguration {
    ...
    private final CreateDateJobParameter jobParameter;

    @Bean
    @JobScope
    public CreateDateJobParameter jobParameter(@Value("#{jobParameters[createDate]}") String createDate, 
                                               @Value("#{jobParameters[name]}") String name) {
        return new CreateDateJobParameter(createDate, name); 
    }
    ...

 

3. JobParameter Bean을 받아 해당 변수를 이용해 사용


    @Bean
    @StepScope
    public JpaPagingItemReader<Product> reader() {
        Map<String, Object> params = new HashMap<>();
        params.put("createDate", jobParameter.getCreateDate());
        params.put("name", jobParameter.getName());
...
    }
}

 

 

  2-3. Field 주입 - SpEL T 문법 사용

 

 

 

 

(3) Job Parameter 와 Job Instance

- 작업 인스턴스는 작업 실행 프로그램에서 전달한 작업 이름과 매개변수를 사용하여 생성된다.

- 작업이 성공적으로 실행된 경우 동일한 작업을 다시 실행할 수 없다.

- 대신 새 작업 매개변수를 작업에 전달하여 새 작업 인스턴스를 생성해야 한다.

 

 

(4) JobParameter vs 시스템 변수

https://jojoldu.tistory.com/330

 

5. Spring Batch 가이드 - Spring Batch Scope & Job Parameter

이번 시간에는 Spring Batch의 Scope에 대해서 배워보겠습니다. 여기서 말하는 Scope란 @StepScope, @JobScope를 얘기합니다. 무의식적으로 사용하는 이 어노테이션들이 실제로 어떤 일들을 하는지 알아보겠

jojoldu.tistory.com