개발놀이터

스프링 배치 도메인의 이해 : JobInstance, JobParamter, JobExecution 본문

Spring/Spring Batch

스프링 배치 도메인의 이해 : JobInstance, JobParamter, JobExecution

마늘냄새폴폴 2022. 9. 20. 18:30

본 포스팅은 인프런의 정수원님의 스프링 배치 강의를 듣고 정리한 포스팅입니다. 더 자세한 내용은 강의를 참고해주세요. 

 

**본 포스팅은 앞선 포스팅과 이어지는 내용입니다.**

https://coding-review.tistory.com/190

 

스프링 배치 도메인의 이해 : Job

본 포스팅은 인프런의 정수원님의 스프링 배치 강의를 듣고 정리한 포스팅입니다. 더 자세한 내용은 강의를 참고해주세요. Job 기본 개념 배치 계층 구조에서 가장 상위에 있는 개념으로 하나의

coding-review.tistory.com

 

JobInstance 에 대해서 들어가기 앞서 우리는 Job 과 JobInstance 의 차이에 대해 알아봐야 합니다. 

 

Job 자체를 실행하기 위한 단계, 처리, 결과, 구성 등을 포함하고 있는 객체들이 바로 Job, Step, Flow, Tasklet 등등 입니다. 즉, Job 그 자체를 실행하기 위한 객체라는 의미이죠. 그럼 JobInstance 는 뭘까요?

 

JobInstance, JobExecution, JobParamter, StepExecution 등등은 Job 에 대한 상태정보, 실행정보 등을 데이터베이스에 저장하기 위한 객체들 입니다. 

 

정리하자면 Job 은 Job 그 자체를 실행하기 위한 객체, Jobinstance는 Job 의 상태정보나 실행정보 등을 데이터베이스에 저장하기 위한 객체 라고 정리할 수 있습니다. 

 

이제 정리가 되셨나요?

 

본격적으로 JobInstance에 대해서 들어가보도록 하겠습니다. 

 

JobInstance

기본 개념

  • Job이 실행될 때 생성되는 Job 의 논리적 실행 단위 객체로서 고유하게 식별 가능한 작업 실행을 나타냄
  • Job의 설정과 구성은 동일하지만 Job 이 실행되는 시점에 처리하는 내용은 다르기 때문에 Job 의 실행을 구분해야 함
    • 예를 들어서 하루에 한 번 씩 배치 Job 이 실행된다면 매일 실행되는 각각의 Job 을 JobInstance 로 표현한다.
  • JobInstance 생성 및 실행
    • 처음 시작하는 Job + JobParamter 일 경우 새로운 JobInstance 생성
    • 이전과 동일한 Job + JobParamter 로 실행할 경우 이미 존재하는 JobInstance 리턴
      • 내부적으로 JobName + JobKey (JobParameter 의 해시값) 를 가지고 JobInstance 객체를 얻음
  • Job 과는 1 : N 관계

 

BATCH_JOB_INSTANCE 테이블과 매핑

  • JOB_NAME (Job) 과 JOB_KEY (JobParamter의 해시값) 가 동일한 데이터는 중복해서 저장할 수 없음

 

다음으로 JobInstance의 생성 흐름에 대해서 살펴보도록 하겠습니다.

 

 

JobLauncher는 우리가 구성한 배치 잡을 실행하는 역할을 합니다. Job을 실행시킬 때는 두개의 객체를 인자로 받아서 실행합니다. 바로 Job 과 JobParameter 입니다. 

 

위의 그림은 Job 으로 "일별 정산" JobParameter 로 2021.01.01 을 인자로 받았습니다. 

 

JobRepository 는 데이터베이스를 조회해서 해당 Job이 존재한다면 기존 JobInstance를 리턴하고 존재하지 않다면 새로운 JobInstance 를 생성합니다. 

 

만약 같은 JobParamter로 실행한다면 어떻게 될까요? 

 

기존 JobInstance를 반환하면서 에러를 내뱉습니다. 

 

Caused by : org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException : A Job instance already exists and is complete for parameters={name=user1}, If you want to run this job again, change the parameters.

 

에러가 참 친절하네요 JobInstance가 해당 JobParameter로 이미 존재하기  때문에 다시 시작하고 싶으면 파라미터를 바꿔라 라는 에러입니다. 

 

 

 

JobParamter

기본 개념

  • Job 을 실행할 때 함께 포함되어 사용되는 파라미터를 가진 도메인 객체
  • 하나의 Job 에 존재할 수 있는 여러개의 JobInstance 를 구분하기 위한 용도
  • JobParameters 와 JobInstance 는 1 : 1 관계

 

생성 및 바인딩

  • 애플리케이션 실행 시 주입
    • Java -jar LogBatch.jar requestDate=20210101
  • 코드로 생성
    • JobParameterbuilder, DefaultJobParametersConverter
  • SpEL 이용
    • @Value("#{jobParamter[requestDate]}"), @JobScope, @StepScope 선언 필수

 

BATCH_JOB_EXECUTION_PARAM 테이블과 매핑

  • JOB_EXECUTION 과 1 : N 관계

 

JobParameter Wrapper 에는 JobParamter 가 LinkedHashMap 으로 저장되어 있습니다. 

 

JobParameter 에는 parameter, parameterType 을 가지고 있습니다. parameter는 말 그대로 파라미터이구요 parameterType 은 parameter 로 담을 수 있는 클래스를 지정해놓고 있습니다. 

 

parameter 에는 String , Date, Long, Double 이 네가지의 클래스만 들어갈 수 있습니다. 

 

예를 들어서 위의 그림에서 세개의 파라미터가 들어갔는데요 requestDate, run.id, name 입니다. 이것이 BATCH_JOB_EXECUTION_PARAM 테이블에 이렇게 매핑 됩니다.

 

 

type_cd 에는 parameter 의 타입이, key_name 에는 우리가 지정한 key 값이, val (value) 에는 각각의 값이 저장되는 방식입니다. 

 

우선 잡이 기본적으로 시작되지 않도록 application.yml 에서 설정을 바꿔줍니다.

 

 

그리고 JobParameter 를 테스트할 클래스를 만들어 줍니다. 

 

package io.sprintbatch.springbatchlecture;

import lombok.RequiredArgsConstructor;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
@RequiredArgsConstructor
public class JobParameterTest implements ApplicationRunner {

    private final JobLauncher jobLauncher;
    private final Job job;

    @Override
    public void run(ApplicationArguments args) throws Exception {

        JobParameters jobParameters = new JobParametersBuilder()
                .addString("name", "user1")
                .addLong("seq", 2L)
                .addDate("date", new Date())
                .addDouble("age", 16.5)
                .toJobParameters();

        jobLauncher.run(job, jobParameters);
    }
}

 

이렇게 설정하고 실행한 다음 BATCH_JOB_EXECUTION_PARAMS 테이블에 가보면

이렇게 값이 들어가 있는 것을 확인할 수 있습니다. 

 

이런식으로 JobParameter를 넣었는데 이제 이걸 사용해야겠죠? 우선 tasklet에서 사용하는 방법은 다음과 같습니다. 

 

JobParameters jobParameters = stepContribution.getStepExecution().getJobExecution().getJobParameters();
jobParameters.getString("name");
jobParameters.getLong("seq");
jobParameters.getDate("date");
jobParameters.getDouble("age");

 

tasklet 에 있는 StepContribution 에서 StepExecution 을 꺼내고 JobExecution 을 꺼내고 JobParameters 를 꺼냅니다. 

 

이렇게 꺼낸 JobParameter 는 getString, getLong, getDate, getDouble 을 이용해 각각의 값을 꺼낼 수 있습니다. 

 

많은 분들이 tasklet 으로 JobParameter 를 사용하시지는 않고 SpEL 로 꺼내는 방법 (@StepScope, @JobScope) 으로 꺼내는 방법을 많이들 알고 계실겁니다. 이 부분에 대해서는 추후에 포스팅 하도록 하겠습니다. 

 

 

 

JobExecution

기본 개념

  • JobInstance 에 대한 한번의 시도들을 의미하는 객체로서 Job 실행 중에 발생한 정보들을 저장하고 있는 객체
    • 시작시간, 종료시간, 상태 (시작됨, 완료, 실패), 종료 상태의 속성을 가짐
  • JobInstance 와의 관계
    • JobExecution 은 "FAILED" 또는 "COMPLETED" 등의 Job 의 실행 결과 상태를 가지고 있음
    • JobExecution 의 실행 상태 결과가 "COMPLETED" 면 JobInstance 실행이 완료된 것으로 간주해서 재 실행이 불가능함
    • JobExecution 의 실행 상태 결과가 "FAILED" 면 Jobinstance 실행이 완료되지 않은 것으로 간주해서 재 실행이 가능함
      • JobParameter 가 동일한 값으로 Job 을 실행할지라도 JobInstance 를 계속 실행할 수 있음
    • JobExecution 의 실행 상태 결과가 "COMPLETED" 될 때까지 하나의 JobInstance 내에서 여러번의 시도가 생길 수 있음

 

BATCH_JOB_EXECUTION 테이블과 매핑

  • JobInstance 와 JobExecution 은 1 : N 관계로서 JobInstance 에 대한 성공/실패의 내역을 가지고 있음

 

 

JobExecution 은 JobInstance 와 혼동하기 쉽습니다. 둘의 가장 큰 차이는 JobInstance는 같은 job_name, JobParameter를 가졌다면 반드시 하나만 생성되지만 JobExecution은 Job이 실행될때마다 새로 생성된다는 차이가 있습니다. 

 

즉, JobExecution 은 Job 의 실행단위인 것입니다. 

 

그 다음으로 알아봐야 하는 것은 JobInstance 와의 상관관계입니다. 위에서 말했지만 중요하기 때문에 다시 말씀드리겠습니다. 

 

알기 쉽게 순서도로 설명드리겠습니다. 

 

1. Job이 성공 -> BatchStatus = COMPLETED -> JobInstance 는 한개 JobExecution 도 한개 생성 -> 재시작 불가능

2. Job이 실패 -> BatchStatus = FAILED -> JobInstance 는 한개 JobExecution 도 한개 생성 -> 재시작 가능

 

만약 2번 Job을 다시 실행한다면 JobInstance는 변함없지만 JobExecution 이 하나 더 생성 된 모습을 볼 수 있습니다. 

 

 

여기까지 Job 과 관련된 실행 정보, 상태 정보를 위한 JobInstance, JobParameter, JobExecution에 대해서 알아봤습니다. 다음 포스팅에서는 Step에 관련된 포스팅을 진행하도록 하겠습니다.