Post

[Spring Batch 2] 스프링 배치 아키텍처와 기본 프로세스

1. Spring Batch Architecture

스프링배치를 구현하기에 앞서 스프링배치가 어떤 아키텍처로 구성되어 있고, 각 구성 요소들은 어떤 역할을 수행하는지 알아보자.

Spring Batch 아키텍처

1-1. 주요 구성 요소

Job

  • Spring Batch에서 일괄 적용을 위한 일련의 프로세스를 요약하는 단일 실행 단위가 된다.
  • 여러 개의 Step을 정의하고, 각 Step 간의 실행 순서를 결정한다.

JobLauncher

  • Job을 수행하기 위한 인터페이스이다.
  • Spring Batch에서 배치 작업을 시작하는 역할을 담당한다.
  • 자바 커맨드를 통해서 CommandLineJobRunner를 실행하여 단순하게 배치 프로세스가 수행될 수 있다.
  • JobJobParameters를 인자로 받아 실행한다.

Step

  • Job을 구성하는 처리 단위이다.
  • 하나의 Step은 하나의 처리 흐름을 의미하며, 일반적으로 읽기, 처리, 쓰기 단계를 포함한다.
  • 하나의 Job에서 여러 Step이 재사용, 병렬화, 조건분기 등을 수행할 수 있다.
  • ItemReader, ItemProcessor, ItemWriter와 같은 배치 처리를 담당하는 컴포넌트로 구성된다.

JobRepository

  • Job과 Step의 상태를 관리하는 시스템이다.
  • 배치 메타데이터를 저장하고 관리하는 역할을 담당한다.
  • 배치 작업의 실행 이력, 상태, 성공/실패 여부를 저장한다.
  • 배치의 재시작 기능을 지원하기 위해 필요한 정보를 제공한다.

ItemReader

  • 청크단위 모델에서 사용하며, 소스 데이터를 읽어 들이는 역할을 수행한다.
  • 파일, 데이터베이스, API 등 다양한 데이터 소스에서 데이터를 읽어 배치 처리의 입력으로 제공한다.

ItemProcessor

  • 읽어들인 청크 데이터를 처리한다.
  • 읽어온 데이터를 가공하는 역할을 수행한다.
  • 데이터 변환, 유효성 검증, 필터링 등을 수행할 수 있다.

ItemWriter

  • 청크 데이터를 읽어들였거나, 처리된 데이터를 실제 쓰기작업을 담당한다.
  • 처리된 데이터를 최종적으로 저장하는 역할을 수행한다.
  • 데이터베이스, 파일, 메시지 큐 등 다양한 데이터 저장소로 데이터를 쓸 수 있다.



2. Spring Batch Process

이번에는 앞서 스프링 배치의 기본 아키텍처를 바탕으로 배치 프로세스가 진행되는 흐름을 살펴보자.

Spring Batch 프로세스

2-1. 처리 흐름

  1. JobScheduler가 배치를 트리거링 하면 JobLauncher를 실행한다.
  2. JobLauncherJob을 실행한다.
  3. Job이 실행되면 JobExecution이 실행되어 배치 작업의 실행 상태, 시작 시간, 종료 시간 등을 기록한다.
  4. Job은 자신에게 정의된 Step을 실행한다. Step의 상태StepExecution이 실행되어 기록한다.
  5. StepChunk 모델(Chunk-Oriented Processing)로 구성되며, ItemReader/ItemProcessor/ItemWriter로 Chunk 단위의 데이터를 처리한다.
  6. ItemReader가 데이터를 읽고, ItemProcessor처리 및 가공하며, ItemWriter가 데이터를 기록한다.
  7. Step이 완료되면 상태가 StepExecution에 실행이력과 상태가 기록된다.
  8. Job의 모든 Step이 완료되면 최종적으로 JobExecution의 상태가 JobRepository를 통해 DB에 저장된다.

2-2. Job 정보의 흐름

  • JobLauncher는 JobRepository를 통해서 JobInstance정보를 데이터베이스에 등록한다.
  • JobExecution을 통해서 Job실행 정보를 데이터베이스에 저장한다.
  • Step은 JobRepository를 통해서 I/O 레코드와 상태정보를 저장한다.
  • Job이 완료되면 JobRepository를 통해서 데이터베이스에 완료 정보를 저장한다.

2-3. 스프링 배치 저장 정보

  • JobInstance
    • JobInstance는 Job 이름과 전달 파라미터를 정의한다.
    • Job이 중단되는 경우 다음 실행할때 중단 이후부터 실행하도록 지원한다.
  • JobExecution
    • Job의 물리적인 실행을 나타낸다.
    • JobInstance와 달리 동일한 Job이 여러번 수행될 수 있다.(1:N)
    • Job의 실행 이력 및 상태 정보(성공/실패, 시작 시간, 종료 시간 등)를 기록한다.
    • 특정 Step에서 실패했다면, 실패한 Step 이후부터 다시 실행할 수 있도록 Job의 상태를 기록한다.
  • Job-ExecutionContext
    • 각각의 JobExecution에서 처리 단계와 같은 메타 정보들을 공유하는 영역이다.
    • Job내의 모든 Step에서 공유된다. 즉, Step 간에 데이터를 공유해야 할 경우, Job-ExecutionContext를 사용하여 데이터를 주고받을 수 있다.
    • 스프링 배치가 프레임워크 상태를 기록하는데 사용하며, 또한 애플리케이션에서 ExecutionContext에 액세스 하는 수단도 제공된다.
    • Job이 중단되거나 실패했을 때, 재시작 시 필요한 상태를 저장한다.
    • 데이터는 바이트 스트림 형태로 저장되기 때문에 반드시 java.io.Serializable를 구현해야한다.
  • StepExecution
    • Step의 물리적인 실행을 나타낸다.
    • Job은 여러 Step을 수행하므로 1:N 관계가 된다.
    • 실행 이력 및 상태 정보(Chunk별 처리된 레코드 수, 성공/실패 상태 등)를 기록한다.
    • Step이 중단되었을 때 다음에 실행할 Step 등을 결정한다.
  • Step-ExecutionContext
    • Step내에서만 사용하는 데이터를 공유해야하는 영역이다.
    • Step의 실행 중에 발생하는 상태 정보를 저장하고 재시작 시 필요한 상태를 저장한다.
    • 데이터는 바이트 스트림 형태로 저장되기 때문에 반드시 java.io.Serializable를 구현해야한다.
  • JobRepository
    • 배치 실행정보나 상태, 결과정보들이 데이터베이스에 저장될 필요가 있으며 이를 처리하는 것이 JobRepository이다.
    • 저장된 정보를 활용하여 스프링배치는 Job을 재실행 하거나, 정지된 상태 후부터 수행할 수 있는 수단을 제공한다.
항목ExecutionExecutionContext
역할Job 또는 Step의 실행 상태를 추적하고 기록배치 실행 중의 중간 데이터상태 정보를 저장
저장 정보실행 시간, 처리된 데이터 수, 성공/실패 상태, 트랜잭션 상태 등중간에 처리된 데이터, 재시작 시 필요한 상태 정보, Step 간 공유 데이터
주요 사용 시점Job 또는 Step이 실행될 때마다 자동으로 생성 및 업데이트Step 실행 중 중간 상태를 기록하거나 재시작할 때 사용
재시작 기능 지원Job 또는 Step이 중단되었을 때 재시작 지점에서 상태 복원 지원세부적인 중간 상태 데이터를 저장하여, 보다 정교하게 재시작을 지원
데이터 구조내부적으로 관리되는 상태 정보 객체Key-Value 방식의 저장소, 직렬화 가능한 데이터 저장
직렬화 필요 여부직렬화 필요 없음 (Spring Batch가 관리)직렬화(Serializable)가 필요, DB에 저장하기 위해 바이트로 변환



3. Spring Batch Tasklet 방식 구현 및 실행

3-1. Tasklet? Chunk?

스프링 배치를 Tasklet 방식으로 실행하기에 앞서, Chunk 방식과는 어떤 차이가 있는지 간단히 아래 표에 정리하였다.

항목Tasklet 방식Chunk 방식
처리 방식단일 작업(단일 태스크) 처리대량 데이터를 일정 크기(Chunk)로 나누어 처리
반복 처리반복적이지 않음, 한 번에 한 작업만 처리Chunk 단위로 데이터를 반복적으로 처리
트랜잭션 관리트랜잭션 수동 관리Chunk 단위로 자동으로 트랜잭션 커밋 및 롤백 관리
주요 사용단일 작업(파일 삭제, 데이터 초기화 등)대용량 데이터 처리 시 사용 (파일 처리, DB 연동 등)
구성 요소Tasklet 인터페이스ItemReader, ItemProcessor, ItemWriter로 구성
유연성단순 작업 처리에 적합, 복잡한 처리에는 부적합대용량 데이터 처리에 적합, 유연한 트랜잭션 관리

3-2. Tasklet 구현

구현체가 어느시점에 실행되는지는 아직 모르나 일단 KIDO님의 구현 순서를 따라서 작성하였다.

Tasklet 구현체 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Slf4j
public class GreetingTask implements Tasklet, InitializingBean {
  @Override
  public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
    log.info("------------------ Task Execute -----------------");
    log.info("GreetingTask: {}, {}", contribution, chunkContext);

    return RepeatStatus.FINISHED;
  }

  @Override
  public void afterPropertiesSet() {
    log.info("----------------- After Properites Sets() --------------");
  }
}

Job, Step 빈 구성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Slf4j
@Configuration
public class BasicTaskJobConfiguration {
  @Autowired
  PlatformTransactionManager transactionManager;

  @Bean
  public Tasklet greetingTasklet() {
    return new GreetingTask();
  }

  @Bean
  public Step step(JobRepository jobRepository) {
    log.info("------------------ Init myStep -----------------");

    return new StepBuilder("myStep", jobRepository)
      .tasklet(greetingTasklet(), transactionManager)
      .build();
  }

  @Bean
  public Job myJob(JobRepository jobRepository) {
    log.info("------------------ Init myJob -----------------");
    return new JobBuilder("myJob", jobRepository)
      .incrementer(new RunIdIncrementer())
      .start(step(jobRepository))
      .build();
  }
}
  • 빈은 Tasklet, Step, Job 순으로 등록되는 것을 확인할 수 있다.
  • Job Bean에서는 진행할 step과 jobRepository를 주입받아 JobBuilder를 통해 Job을 생성한다.
  • Step Bean에서는 실행할 tasklet과 jobRepository를 주입받아 StepBuilder를 통해 Step을 생성한다.



4. 스프링 배치 어플리케이션 실행

4-1. 실행 및 결과

img.png

로그를 자세히 확인해보면 Job -> Step -> Tasklet 순으로 로그가 노출되는 것을 확인할 수 있다.

img_2.png

Job에 대한 파라미터 정보, 실행 Step 정보, Tasklet 실행 정보 등을 확인할 수 있다. 이 정보들 중에서 execute 메서드 실행시 들어오는 파라미터 정보들은 다음과 같았다.

contribution

1
StepContribution: read=0, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING

chunkContext

1
ChunkContext: attributes=[], complete=false, stepContext=SynchronizedAttributeAccessor: [], stepExecutionContext={batch.version=5.1.0, batch.taskletType=com.schooldevops.springbatch.batchstudy.jobs.task01.GreetingTask, batch.stepType=org.springframework.batch.core.step.tasklet.TaskletStep}, jobExecutionContext={batch.version=5.1.0}, jobParameters={run.id=2}

StepContribution에는 read, write count 같은 stepExecution 정보가 포함되어 있는 것을 확인할 수 있고,
ChunkContext에는 기본적인 Job,Step ExcutionContext 정보가 포함되어있는 것을 확인할 수 있다.

4-2. 스프링 배치 DB 메타데이터

스프링 배치가 실행되면서 기록된 MySQL DB 스프링배치 메타데이터도 확인할 수 있다.

BATCH_JOB_INSTANCE

img_3.png

BATCH_JOB_EXECUTION

img_4.png

BATCH_JOB_EXECUTION_CONTEXT

img_5.png

BATCH_JOB_EXECUTION_PARAMS

img_6.png

BATCH_STEP_EXECUTION

img_7.png

BATCH_STEP_EXECUTION_CONTEXT

img_8.png


참고: DEVOCEAN KIDO님 SpringBatch 연재 02


This post is licensed under CC BY 4.0 by the author.