JaeWon's Devlog
article thumbnail
반응형

1. 1. JobLauncher

<java />
public interface JobLauncher { public JobExecution run(Job job, JobParameters jobParameters) throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, JobParametersInvalidException; }

 

1.1. 1-1) 기본 개념

- 배치 Job 을 실행시키는 역할

- Job 과 JobParameters 를 인자로 받아 배치를 수행하고 끝나면 JobExecution 을 Return

- Application 이 구동될 때 JobLauncher Bean 이 자동 생성

2. 2. JobBuilderFactory & JobBuilder

- Spring Batch 는 Job 과 Step 을 쉽게 생성할 수 있도록 Builder 클래스를 제공

2.1. 2-1) JobBuilderFactory

- JobBuilder 를 생성하는 팩토리 클래스

- jobBuilderFactory.get("jobName") -> "jobName" 은 스프링 배치가 Job 을 실행시킬 때 참조하는 Job 이름

<java />
@Bean(name = "BatchJob") public Job job() { return jobBuilderFactory.get("BatchJob") .start(step()) .on("COMPLETED") .to(processorStep(null, null)) .end() .build(); }

2.2. 2-2) JobBuilder

  • SimpleJobBuilder
    - Job 실행과 관련된 여러 설정 API 제공
  • FlowJobBuilder
    - 내부적으로 FlowBuilder 를 반환함으로서 Flow 실행과 관련된 여러 설정 API 제공

2.3. 2-3) 아키텍처 & 클래스 상속 구조

3. 3. StepBuilderFactory / StepBuilder

3.1. 3-1) StepBuilderFactory

- StepBuilder 를 생성하는 팩토리 클래스

- stepBuilderFactory.get("stepName") -> "stepName" 은 스프링 배치가 Step 을 실행시킬 때 참조하는 Step 이름

<java />
@Bean(name="BatchJobStep") @JobScope public Step step() { return stepBuilderFactory.get("BatchJobStep") .tasklet((contribution, chunkContext) -> { return RepeatStatus.FINISHED; }) .build(); }

3.2. 3-2) StepBuilder

  • TaskletStepBuilder
    - TaskletStep 을 생성하는 기본 빌더 클래스
  • SimpleStepBuilder
    - TaskletStep 을 생성하며 내부적으로 청크기반의 작업을 처리하는 ChunkOrientedTasklet 클래스를 생성
  • PartionStepBuilder
    - PartionStep 을 생성하며 멀티 스레드 방식으로 Job 을 실행
  • JobStepBuilder
    - JobStep 을 생성하여 Step 안에서 Job 을 실행
  • FlowStepBuilder
    - FlowStep 을 생성하여 Step 안에서 Flow 를 실행

4. 4. SimpleJob

4.1. 4-1) 기본개념

- Job 이 실행되면 해당 Job 은 순차적으로 Step 을 실행

- 모든 Step 이 완료되어야만 Job 이 성공적으로 완료(만약 중간 Step 에서 오류/실패가 된다면 해당 Job 은 실패로 완료)

- 맨 마지막 Step 의 BatchStatus 가 Job 의 최종 BatchStatus(배치 상태)

4.2. 4-2) 흐름

<java />
public Job batchJob() { return jobBuilderFactory.get("batchJob") // JobBuilder 를 생성하는 팩토리, Job 의 이름을 매개변수로 받음 .start(Step) // 처음 실행 할 Step 설정, 최초 한번 설정, 이 메서드를 실행하면 SimpleJobBuilder 반환 .next(Step) // 다음에 실행 할 Step 설정, 횟수는 제한이 없으며 모든 next() 의 Step 이 종료가 되면 Job 이 종료된다 .incrementer(JobParametersIncrementer) // JobParameter 의 값을 자동을 증가해 주는 JobParametersIncrementer 설정 .preventRestart(true) // Job 의 재 시작 가능 여부 설정, 기본값은 true .validator(JobParameterValidator) // JobParameter 를 실행하기 전에 올바른 구성이 되었는지 검증하는 JobParametersValidator 설정 .listener(JobExecutionListener) // Job 라이프 사이클의 특정 시점에 콜백 제공받도록 JobExecutionListener 설정 .build(); // SimpleJob 생성 }

4.3. 4-3) API 설정

  • start() / next()
    - start() : 처음 실행할 step 설정, 최초 한번 설정
    - next() : 다음에 실행할 step 들을 순차적으로 연결, 여러변 설정이 가능하며 모든 next() 의 step 이 종료되면 Job 종료

  • incrementer()
    - 기존의 JobParameter 변경없이 동일한 Job 을 여러 번 수행하고자 할 때 사용
    - RunIdIncrementer 구현체를 지원하며 인터페이스를 직접 구현 가능

4.4. 4-4) 아키텍처

5. 5. TaskletStep

5.1. 5-1) 기본 개념

- Step 의 구현체 중 하나로 Tasklet 을 실행시키는 도메인 객체

- RepeatTemplate 를 사용해 Tasklet 의 구문을 트랜잭션 경계 내에서 반복 수행

- 스프링 배치에서 Step 의 실행 단위는 2가지로 나누어짐.

  • Task 기반
    - 단일 작업 기반으로 처리되는 것이 더 효율적인 경우
    - Tasklet 구현체 사용
    - 대량 처리를 하는 경우 Chunk 기반보다 복잡한 구현 필요
  • Chunk 기반
    - 하나의 큰 덩어리를 N 개씩 나누어 실행한다는 의미로 대량 처리를 하는 경우 효과적으로 수행
    - ItemReader, ItemProcessor, ItemWriter 를 사용하며 청크 기반 전용 ChunkOrientedTasklet 구현체 사용

5.2. 5-2) 예제

<java />
@Bean(name="BatchJobStep") @JobScope public Step step() { return stepBuilderFactory.get("BatchJobStep") // StepBuilder 를 생성하는 팩토리, Step 이름을 매개변수로 받음 .tasklet((contribution, chunkContext) -> { // Tasklet 클래스 설정 return RepeatStatus.FINISHED; }) .startLimit(10) // Step 의 실행 횟수 설정, 초과 시 오류 발생 .allowStartIfComplete(true) // Step 의 성공, 실패와 상관없이 항상 Step 을 실행하기 위한 설정 .listener(new StepExecutionListener() { // Step 라이프 사이클의 특정 시점에 콜백을 제공받는 Listener @Override public void beforeStep(StepExecution stepExecution) { } @Override public ExitStatus afterStep(StepExecution stepExecution) { return null; } }) .build(); }

5.3. 5-3) 아키텍쳐

6. 6. FlowJob

6.1. 6-1) 기본 개념

- Step 을 순차적으로만 구성하는 것이 아닌 특정한 상태에 따라 순서를 변경하도록 구성 가능

  • Step 이 실패하더라도 Job 은 실패로 끝나지 않도록 해야 하는 경우
  • Step 이 성공/실패에 따라 다르게 다음 Step 이 실행되어야 하는 경우

- Flow 와 Job 의 흐름에만 관여하고 비지니스로직은 Step 에서 동작

6.2. 6-2) SimpleJob VS FlowJob

6.3. 6-3) 예제

<java />
@Bean(name = "BatchJob") public Job job() { return jobBuilderFactory.get("BatchJob") .start(step()) // Flow 시작하는 Step 설정 .on("COMPLETED") // Step 의 실행 결과로 ExitStatus 를 캐치하여 상태에 맞는 다음 Step 처리 .to(processorStep(null, null)) // 다음으로 이동할 Step 지정 -> step() 이 성공인 경우(processorStep 수행) .on("FAILED") // 다음으로 이동할 Step 지정 -> step() 이 실패인 경우(end 배치 종료) .end() .from(processorStep(null, null)) // 이전 단계(processorStep)에서 정의한 Step 의 Flow 를 추가로 정의 .on("COMPLETED") .to(finishStep()) .on("COMPELTED") .end() .end() // build() 앞에 위치하면 FlowBuilder 를 종료 -> Job 종료 .build(); }

6.4. 6-4) 아키텍쳐

7. 7. @JobScope / @StepScope

7.1. 7-1) Proxy 객체 생성

- @JobScope, @StepScope 어노테이션이 선언되면 내부적으로 Bean 의 Proxy 객체가 생성 -> Job 실행 시 Proxy 객체가 실제 Bean 을 호출하여 해당 메소드를 실행

7.2. 7-2) JobScope, StepScope

- Proxy 객체의 실제 대상이 되는 Bean 을 등록, 해제

- 실제 Bean 을 저장하고 있는 JobContext, StepContext 를 가짐

7.3. 7-3) JobContext, StepContext

- 스프링 컨테이너에서 생성된 Bean 을 저장하는 컨텍스트 역할

- Job 실행 시점에서 Proxy 객체가 실제 Bean 을 참조할 때 사용

7.4. 7-4) 스프링 어플리케이션 구동 부터 @Value 바인딩 과정

  1. 어플리케이션이 구동되면 Spring 의 ApplicationContext 가 Bean 을 생성하고 관리
  2. 클래스에서 @JobScope / @StepScope 어노테이션이 존재하는지 확인
    - 존재하지 않는다면 기본적인 싱글톤 Bean 을 생성(만약 @Value 어노테이션 선언 시 오류 발생)
    - 존재한다면 해당 Bean 의 Proxy 객체를 생성
  3. 설정이 끝나면 스프링 초기화가 완료, Job 실행(JobLauncher)
  4. Job 은 Step 의 실제 Bean 이 아닌 Proxy 객체를 저장
  5. Proxy 객체는 실제 Step 메소드(step())를 호출할 때 실제 Bean 객체를 참조 -> 해당 시점에 StepBean 생성
  6. 5번에서 프록시 객체가 실제 메소드를 호출할 때 참조할 Bean 을 JobScope 에서 조회(JobScope 는 JobContext 를 통해 조회)
  7. JobContext 에서는 실제 Bean 이 존재하면 해당 Bean 을 꺼내 참조하여 실제 Step 수행
  8. JobContext 에서 실제 Bean 이 존재하지 않으면 스플이 BeanFactory 를 통해 실제 Step 생성 -> 해당 시점에 실제 step() 메소드를 호출해서 Bean 을 생성 및 @Value 바인딩 처리 및 진행
  9. 생성된 StepBean 을 JobContext 에 저장하고, 이후 JobContext 에서 해당 Bean 을 꺼내어 사용

참고

- https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B0%B0%EC%B9%98/dashboard

반응형
profile

JaeWon's Devlog

@Wonol

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!