728x90
반응형
SMALL

Job이란?

1개의 작업에 대한 명세서를 의미한다. 어디까지가 1개 작업으로 봐야할지 기준이 애매할 수 있다. 그 기준은 상황별로 판단하면 된다.

다음 예시를 보자.

  • Job: 식당을 예약한다.
    • Step 1: 전화를 건다.
    • Step 2: 예약을 한다.
    • Step 3: 예약금을 송금한다.

이게 하나의 Job이라고 볼 수 있다. 이처럼,

  • 1개의 Job은 여러개의 Step을 포함할 수 있다.
  • Job name을 통해 Job을 구분할 수 있다. 
  • Job name으로 Job을 실행시킬 수 있다.
  • Job을 만드는 빌더는 많지만, JobBuilder로 쉽게 Job을 만들 수 있다.

 

아래 그림을 보자.

 

Job을 만들고 실행하는 과정에 대한 그림이다. 그럼 저기서 JobJob Instance는 어떤 차이가 있을까? 그리고 Job Execution, Job Parameter는 무엇일까?

 

JobInstance

Job이 명세서라면, JobInstanceJob이 실행되어 실체화된 것이다. JobInstance는 배치 처리에서 Job이 실행될 때 하나의 Job 실행 단위이다. 같은 Job에 같은 조건(Job Parameters)이면, JobInstance는 동일하다고 판단한다. 혹시, Job이 실패해서 다시 같은 조건으로 Job을 실행한다면 같은 JobInstance라고 할 수 있다. 그럼 당연히 같은 Job에 다른 조건(Job Parameters)이면, JobInstance는 다를 것이다.

 

JobExecution

JobExecutionJobInstance의 한번 실행을 뜻한다. 어떤 Job같은 조건으로 1번 실패하고, 1번 성공한다면 JobInstance는 1개이고, JobExecution은 2개이다. JobExecution은 실패했든지 성공했든지 간에 실제로 실행시킨 사실과 동일한 의미이기 때문에 배치 실행과 관련된 정보를 포함하고 있다. 

 

JobExecution에는 들어있는 게 꽤 많다. 예를 들면 다음과 같은 메서드들을 사용할 수 있다.

  • getJobInstance() → JobExecutionJobInstance
  • getJobParameters()JobExecution에서 사용한 Job Parameters
  • getStartTime()Job의 시작시간
  • getEndTime()Job의 종료시간
  • getExitStatus()Job의 실행 결과(Exit Code)
  • getStatus()Job의 현재 상태(Batch Status)
  • getExecutionContext() → Job Execution Context

어떤 것들을 하는 메서드인지 대충봐도 감이 오는데 마지막 ExecutionContext는 무엇일까?

JobExecutionContext

1개의 Job내에서 공유하는 공간(Context)이다. 1개의 Job의 여러 Step들이 있다면, 그 Step들은 해당 공간을 공유할 수 있다.

 

JobParameters

Job이 시작할 때, 필요한 시작 조건을 JobParameters에 넣는다. 동일한 JobJobParameters까지 동일하면, 같은 JobInstance이다. 예를 들면, 다음과 같은 상황이 있다고 해보자.

  • 대한민국의 편의점 리스트를 가져와서 저장하는 Job
    • 매일 폐업하고, 새로 오픈하는 편의점들 리스트를 갱신하는데 목적이 있다.
    • 밤 10시에는 C편의점 리스트 정보 최신화
    • 밤 11시에는 G편의점 리스트 정보 최신화
    • 조건 1: 밤 10시에는 'JobParameters = C편의점' 으로 구동
    • 조건 2: 밤 11시에는 'JobParameters = G편의점' 으로 구동

 

Job 구현 예시

 

@Bean
public Job reserveRestaurantJob(JobRepository jobRepository,
                                Step searchAvailableKoreanRestaurantStep,
                                Step reserveRestaurantStep,
                                Step sendDepositStep) {
    return new JobBuilder("reserveRestaurantJob", jobRepository)
            .start(searchAvailableKoreanRestaurantStep)
            .next(reserveRestaurantStep)
            .next(sendDepositStep)
            .build();
}

 

  • JobBuilderJob을 만든다. 이때 Job을 가져와야 하는데 Job의 이름(Bean의 이름)을 통해 가져온다.
  • 시작 스텝과 다음 스텝들을 지정한다.
  • 여기서, 한개의 스텝이라도 실패하면 다음 스텝으로 진행하지 않는다.
  • build()를 통해 Job을 생성한다.

 

조금 더 복잡한 Job의 예시를 보면 다음과 같다.

 

@Bean
public Job reserveRestaurantJob(JobRepository jobRepository,
                                Step searchAvailableKoreanRestaurantStep,
                                Step searchAvailableAsianRestaurantStep,
                                Step reserveRestaurantStep,
                                Step sendDepositStep) {
    return new JobBuilder("reserveRestaurantJob", jobRepository)
            .start(searchAvailableKoreanRestaurantStep)
                .on("FAILED") // searchAvailableKoreanRestaurantStep 가 FAILED 인 경우
                .to(searchAvailableAsianRestaurantStep) // searchAvailableAsianRestaurantStep 실행
                .on("FAILED") // searchAvailableAsianRestaurantStep 가 FAILED 인 경우
                .end() // 아무것도 하지 않고 FLOW 종료
            .from(searchAvailableKoreanRestaurantStep)
                .on("*") // searchAvailableKoreanRestaurantStep 가 FAILED 가 아닌 경우
                .to(reserveRestaurantStep) // reserveRestaurantStep 실행
                .next(sendDepositStep) // sendDepositStep 실행
            .from(searchAvailableAsianRestaurantStep)
                .on("*") // searchAvailableAsianRestaurantStep 가 FAILED 가 아닌 경우
                .to(reserveRestaurantStep) // reserveRestaurantStep 실행
                .next(sendDepositStep) // sendDepositStep 실행
            .end() // Job 종료
            .build();
}
  • 이번에는 한식 레스토랑 예약이 실패했을 경우 다른 방법을 찾기 위해 아시안 레스토랑을 예약하는 과정까지 넣었다.
  • 그래서 위 코드처럼, 먼저 한식 레스토랑 예약 스텝을 실행하는데 그 스텝이 FAILED인 경우, 아시안 레스토랑 예약 스텝을 실행한다. 그런데 그마저도 실패할 경우가 있으므로, 그땐 이 Job을 종료한다.
  • 한식 레스토랑 예약 스텝 또는 아시안 레스토랑 예약 스텝 둘 중 하나라도 실패가 아닌 경우가 생겼으면 다음 스텝들을 쭉쭉 진행한다.

 

저기서 JobBuilder는 어떻게 가져올까? 다음과 같이 @EnableBatchProcessing 애노테이션을 Spring Boot 엔트리 포인트 클래스에 붙여주면 된다.

@SpringBootApplication
@EnableBatchProcessing
public class DMakerApplication {
    public static void main(String[] args) {
        SpringApplication.run(DMakerApplication.class, args);
    }
}

이렇게 애노테이션을 달면 다음과 같은 빈들을 자동으로 등록해 준다.

  • JobRepository
  • JobLauncher
  • JobRegistry
  • JobExplorer
  • PlatformTransactionManager
  • JobBuilder
  • StepBuilder

이렇게 사용할 수 있는 빈들 중 보이는 JobBuilder를 주입받아 사용하면 되는 것이다. 원래는 JobBuilderFactory가 있었는데 5.0 이후부터 Deprecated 됐다. 그래서 JobBuilder를 사용하면 된다.

 

정리를 하자면

Job에 대해 알아보았다. 다음 포스팅에는 Step에 대해 알아보자!

728x90
반응형
LIST

'Spring Batch' 카테고리의 다른 글

ItemReader  (1) 2024.10.09
Chunk Processing  (5) 2024.10.09
Tasklet  (0) 2024.10.09
Step  (2) 2024.10.09
Spring Batch 구조와 핵심 키워드  (2) 2024.10.09

+ Recent posts