본문 바로가기
개발/spring-batch

[spring-batch] 잡 파라미터

by RunAndrew 2021. 9. 24.

잡 파라미터

JobInstance가 잡 이름 및 잡에 전달된 식별 파라미터로 식별 파라미터로 식별된다는 내용을 몇번 언급했다. 또한 동일한 식별 파라미터를 사용해 동일한 잡을 두 번 이상 실행할 수 없다는 점도 배웠다. 실제로 동일한 파라미터로 잡을 두 번 실행해보면 예외가 나는것을 알 수 있다.

 

그렇다면 이 시점에서 어떻게 잡에 파라미터를 전달하는지 궁금할 것이다. 스프링배치는 잡에 파라미터를 전달 할 수 있게 해줄 뿐만 아니라 잡 실행 전에 파라미터를 자동으로 증가시키거나 검증할 수도 있다. 잡 러너의 기능 중 하나가 바로 잡 실행에 필요한 JobParameters 객체를 생성해 JobInstance에 전달하는 것이다. 명령행에서 잡을 시작할 때와 쿼츠 스케줄러에서 잡을 시작할 때의 파라미터를 전달하는 방식이 서로 다르기 때문에 이는 당연하다. 지금까지 스프링 부트의 JobLauncherCommandLineRunner를 사용해 왔으므로 이 러너를 기준으로 파라미터 전달 방법을 알아보자.

 

JobLaunchercommandLineRunner에 파라미터를 전달하는 것은 key=value 쌍을 전달했던 것처럼 간단하다.

java -jar demo.jar name=Michael

위의 예제는 name이라는 파라미터를 하나를 전달한다. 사용자가 배치 잡에게 파라미터를 전달하면 잡러너는 JobParameters 인스턴스를 생성하는데, 해당 인스턴스는 잡이 전달받는 모든 파라미터의 컨테이너 역할을 한다.

 

JobParameters는 java.util.Map<String, JobParamter> 객체의 래퍼에 불과하다. 위 예제는 파라미터 값으로 문자열을 전달했지만, 실제로는 해당 Map의 값은 org.springframework.batch.core.JobParameter 인스턴스이다. 이는 타입 때문이다. 스프링 배치는 파라미터의 타입을 변환하는 기능을 제공하며, 변환된 타입에 맞는 JobParameter의 접근자를 제공한다. 파라미터 타입을 long으로 지정하면 java.lang.Long 타입처럼 사용할수 있다. String, Doule, java.util.Date 타입도 기본적으로 지원한다. 타입 변환 기능을 사용하려면 아래 예제처럼 파라미터 이름 뒤에 괄호를 쓰고 그 안에 파라미터 타입을 명시해 스프링 배치에게 알려주면 된다. 스프링 배치에서 해당 타입 이름은 모두 소문자여야 한다.

java- jar demo.jar exectuonDate(date)=2020/12/27

잡에 전달한 파라미터를 확인하고 싶다면 JobRepository를 살펴보면된다. BATCH_JOB_EXECUTIONN_PARAMS 테이블이 있다..


지금까지는 식별 파라미터가 JobInstance를 식별하는데 사용되도록 지정했다. 이번에는 식별에 사용되지 않는 파라미터도 있음을 살펴보자. 스프링 배치 2.2 버전부터 잡 파라미터를 전달 할 때 해당 파라미터가 JobInstance 식별에 사용되도록 할지의 여부를 표시할 수 있는 기능이 추가됐다. 특정 잡 파라미터가 식별에 사용되지 않게 하려면 다음처럼 접두사 "-" 를 사용한다.

java- jar demo.jar exectuonDate(date)=2020/12/27 -name=Michael

잡 파라미터에 접근하기

이제 배치 잡에게 파라미터를 전달하는 방법을 알게 됐다. 그럼 해당 파라미터에 접근은 어떻게 할까? ItemReader, ItemProcessor, ItemWriter 및 Tasklet 인터페이스를 살펴보면 모든 메서드가 JobParameters 인스턴스를 파라미터로 전달받지는 않는다는 점을 알 수 있다. 파라미터에 접근하는 위치에 따라 서로 다른 몇가지 방식을 선택가능하다.

  • ChunkContext: Hellowrold 태스크릿을 보면 execute메서드가 두개의 파라미터를 전달 받는 것을 볼 수 있다. 첫번째 파라미터는 StepContribution으로, 아직 커밋되지 않은 현재 트랜잭션에 대한 정보(쓰기 수, 읽기 수 등)을 가지고 있다. 두번째 파라미터는 ChunkContext 인스턴스이다. 이 인스턴스는 실행 시점의 잡 상태를 제공한다. 또한 태스크릿 내에서 처리 중인 청크와 관련된 정보도 갖고 있다. ChunkContext에는 JobParameters가 포함된 StepContext의 참조가 있다.
  • 늦은 바인딩 Late Binding: 스탭이나 잡을 제외한 프레임워크 내 특정 부분에 파라미터를 전달하는 가장 쉬운 방법은 스프링 구성을 사용해 주입하는 것이다. JobParameters는 변경할 수 없으므로 부트스트랩시에 바인딩하는것이 좋다.

다음 예제는 ChunkContext를 사용해 JobParameters에 접근하는 방법의 예이며, name파라미터를 사용해 출력하도록 구성한 Helloworld 잡이다.

@Bean
public Tasklet helloTasklet() {
  return (stepContribution, chunkContext) -> {
    // job parameter 얻어오기
    StepContext stepContext = chunkContext.getStepContext();
    Map<String, Object> jobParameters = stepContext.getJobParameters();
    String name = (String) jobParameters.get("name");
    System.out.println(String.format("Hello %s", name);
    return RepeatStatus.FINISHED;
  };
}
  • 위에서본 람다식을 helloTasklet() 메서드로 추출했다.
  • chunkContext에서 getStepContext().getJobParamters()로 접근해서, JobParameters Map을 가져온다. Value값이 Object이기 때문에 캐스팅을 해야 한다.

다음은 스프링의 늦은 바인딩으로 JobParameters 코드를 참조하지 않고도 잡 파라미터를 컴포넌트에 주입하는 방법을 보여준다. 스프링 EL을 사용해서 값을 전달한다.

@Bean
private Step step1() {
  return this.stepBuilderFactory.get("step1")
    .tasklet(helloTasklet(null)) // 호출부에서는 null로 처리
    .build();
}

@Bean
@StepScope //stepScope로 지정해줘야함
public Tasklet helloTasklet(@Value("#{jobParameters['name']}") String name) {
  return (stepContribution, chunkContext) -> {
            System.out.println(String.format("Hello %s", name);    
    return RepeatStatus.FINISHED;
  };
}
  • 늦은 바인딩은 스프링 EL를 통해서 jobParamters 를 파라미터로 받아올수 있다.

스프링 배치에 포함된 커스텀 스코프와 잡 스코프를 사용하면 늦은 바인딩을 기능을 쉽게 사용할 수 있다. 이 스코프 각각의 기능은 스텝의 실행범위나 잡의 실행 범위에 들어갈 때까지 빈 생성을 지연시키는 것이다. 이렇게 함으로써 명령행 또는 다른 소스에서 받아들인 잡 파라미터를 빈 생성 시점에 주입할 수 있다.

'개발 > spring-batch' 카테고리의 다른 글

[spring-batch] Job 구성하기  (0) 2021.09.24
[spring-batch] Job 소개하기  (0) 2021.09.24
[spring-batch] 스프링 배치 아키텍쳐  (0) 2021.09.24