티스토리 뷰

'기억보단 기억을' 블로그를 참고하여 작성하였습니다. 해당 프로젝트는 Java로 작성되어있으나 필자는 Kotlin 방식으로 작성하였습니다.


스프링 배치 메타 데이터 테이블 구조

각 테이블이 어떠한 역할을 하고 어떠한 데이터를 갖고 있는지 설명해본다.

1. BATCH_JOB_INSTANCE

해당 테이블에 쿼리를 보내보면 하나의 로우가 조회된다.

  • JOB_INSTANCE_ID
    • `BATCH_JOB_INSTANCE 테이블`의 PK
  • JOB_NAME
    • 수행한 Batch Job 이름

실제로 방금 실행했던 batchJob의 이름이 들어있다.

이때, BATCH_JOB_INSTANCE 테이블은 Job Parameter에 따라 생성되는 테이블이다. 이 Job Parameter는 생소한 부분인데, Sprint Batch가 실행될 때 외부에서 받을 수 있는 파라미터를 말한다.

 

예를들어 특정 날짜를 job parameter로 넘기면 Spring Batch에서는 해당 날짜 데이터로 조회/가공/입력 등의 작업을 할 수 있는 것이다.

 

이 Job Parameter가 다르면 같은 Job이라도 BATCH_JOB_INSTANCE에 기록이 되고, 같으면 기록되지 않는다.

 

기존의 SimpleJob과 SimpleStep의 코드를 수정해보자.

수정을 했으면 실행 시 파라미터로 넘겨보자.

파라미터 추가 & 기입

결과 & 로그 확인

결과가 잘 나온 것을 볼 수 있다. 이제 BATCH_JOB_INSTANCE 테이블을 봐보자.

일단 requestDate가 `20220626` 일 때 하나가 생성된것을 볼 수 있다.

한번 더 실행해도 requestDate가 같다면 생성되지 않는지 확인해보자.

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

같은 JobParameters로 실행된 Job 인스터스가 존재하기에 실행시킬 수 없으며 해당 값을 변경해서 시도하라는 오류이다.

말 그대로 Job 이라는 클래스를 통해 인스턴스가 생성되며 같은 Hash값을 가지는 인스턴스의 경우 추가로 생성되지 못하는 그러한 구조와 같다.

2. BATCH_JOB_EXECUTION

해당 테이블을 보면 이전에 본 JOB_ISNTANCE_ID 값과 JOB_EXECUTION_ID가 쌍으로 있는걸 볼 수 있다. 

JOB_EXECUTION과 JOB_ISNTANCE 는 부모-자식 관계와 같아서 JOB_EXECUTION은 자신의 부모인 JOB_ISNTANCE가 성공/실패했던 모든 내역을 갖고 있는다.

 

실제로 step이 실패하도록 코드를 변경해보자.

@Configuration
class SimpleJobConfiguration(
    val jobBuilderFactory: JobBuilderFactory,
    val stepBuilderFactory: StepBuilderFactory
) {
    val log = LoggerFactory.getLogger(this.javaClass.simpleName)

    @Bean
    fun simpleJob(): Job {
        return jobBuilderFactory.get("simpleJob")
            .start(simpleStep1(null))
            .next(simpleStep2(null))
            .build()
    }

    @Bean
    @JobScope
    fun simpleStep1(@Value("#{jobParameters[requestDate]}") requestDate: String?): Step {
        return stepBuilderFactory.get("simpleStep1")
            .tasklet { _, _ ->
//                log.info(">> This is simpleStep1 <<")
//                log.info(">> request Date is ${requestDate}")
//                RepeatStatus.FINISHED
                throw IllegalArgumentException("step 1에서 실패합니다.")
            }
            .build()
    }

    @Bean
    @JobScope
    fun simpleStep2(@Value("#{jobParametes[requestDate]}") requestDate: String?): Step {
        return stepBuilderFactory.get("simpleStep2")
            .tasklet { _, _ ->
                log.info(">> This is simpleStep2 <<")
                log.info(">> request Date is ${requestDate}")
                RepeatStatus.FINISHED
            }
            .build()
    }
}

 

실행 & 결과

실제로 실패한 인스턴스의 결과가 추가된 것을 볼 수 있다.

 

다시 코드가 성공하도록 코드를 수정하고, jobParameters를 변경하지 않고 다시 실행해보자.

같은 인스턴스임에도 실패한 경우 다시 실행이 가능하며, 또 실패한 경우 성공할 때 까지 재실행이 가능한 것을 확인할 수 있다.

즉, 실패한 Job에 한하여 같은 JOB_INSTANCE_ID를 갖고 있더라도 재실행이 가능한 것.

 

이러한 내용을 가지고 다시한번 정리해보자.

3. JOB, JOB_INSTANCE, JOB_EXECUTION

 

Job

- 현재 프로젝트의 `SimpleJob`에 해당한다.

 

 

Job Instance

- Job Parameter를 20220625, ... 등으로 실행한 SimpleJob들 각각에 해당한다.

- Job Parameter 단위로 생성된다. (성공 여부를 확인해서)

 

 

Job Execution

- Job Parameter를 20220625로 실행한 SimpleJob의 Instance에 대한 1번째 시도, 2번째 시도, 그 이후 시도 + 결과 (실패 / 성공)

 

이외에도 추가적인 메타 데이터 테이블이 존재하지만 일단 여기까지 설명하고 뒤 과정을 진행하면서 추가적으로 설명을 하도록 하겠다.

예를들어 `BATCH_JOB_EXECUTION_PARAMS` 테이블의 경우 `BATCH_JOB_EXECUTION`테이블이 생성될 때 전달받은 Job Parameter를 갖고 있는 테이블이다.

이렇게 Spring Batch의 전반적인 내용에 대한 정리를 진행했으며 이제부터 본격적으로 예제를 통해 코드구현을 해보는 실전 부분을 작성하도록 하겠다.

반응형
Comments
반응형
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday