스프링 배치의 Tasklet 방식과 Chunk 방식

Red Culture·2021년 7월 18일
0

스프링 배치 동작 구조

step에서 tasklet 방식으로 구성하는 방법과 ItemReader/ItemProcessor/ItemWriter 단위로 청크 지향 프로세싱을 구성하는 방법이 있다.

  • Job
    -배치 처리 과정을 하나의 단위로 만들어 표현한 객체이다.
    -하나의 Job객체는 여러 Step 인스턴스를 포함하는 컨테이너이다.
  • JobRepository
    -배치 처리 정보를 담고 있다. Job이 실행되었으면 배치 처리에 대한 모든 메타 데이터가 담겨있다.
  • JobLauncher
    -배치를 실행시키는 인터페이스로 클라이언트의 요청을 받아 Job을 실행하는 객체이다.
    -Job, 파라미터를 받아서 실행하며 JobExecution을 반환한다.
  • Step
    -Job 내부에 구성되어 실제 배치 작업 수행을 정의하고 제어한다. Job을 처리하는 단위이다.
    -독립적이고 순차적인 단계를 캡슐화하는 도메인 객체이다.
    -청크 지향 프로세싱 방식이 아닌 tasklet 방식으로 구현하고자 한다면 Step 내부에서 chunk() 대신 tasklet()을 사용한다.
  • Item
    -처리할 데이터의 가장 작은 요소
  • ItemReader
    -Step의 대상이 되는 배치 데이터를 읽어오는 인터페이스이다. 읽어올 item이 없을 때는 read() 메서드에서 null을 반환하며 그 전까지 순차적인 값을 리턴한다. 지정된 청크 사이즈 만큼 읽을 수 있다.
    public interface ItemReader<T> {
        T read() throws Exception;
    }
  • ItemWriter
    -ItemReader에서 읽어온 값을 Insert, Update 처리한다. 리스트의 데이터 수는 설정한 청크 단위로 불러와 사이즈 만큼 처리할 수 있다.
    public interface ItemWriter<T> {
        void write(List<? extends T> items) throws Exception;
    }
  • ItemProcessor
    -ItemReader에서 읽어 들인 Item에 대해 ItemWriter 하기 전에 필요한 로직을 처리한다.
    public interface ItemProcessor<I, O> {
        O process(I item) throws Exception;
    }

Tasklet 방식

단계 내에서 단일 태스크를 수행하기 위한 것으로 임의의 Step을 실행할 때 읽기/처리/쓰기를 하나의 작업으로 처리하는 방식

  • Job 구성 클래스 외부에 tasklet 클래스를 만들어서 참조하는 방식
    1) Step에서 chunk() 대신 tasklet()을 사용하는 것이다.
    2) tasklet은 외부 클래스를 만들고 tasklet 작업을 정의한다.
    3) tasklet 작업을 정의한 외부 클래스에서는 기본적으로 Tasklet을 implements 받아서 구현을 해야한다. 그에 따라 execute 메서드를 구현해야 한다.
    -> execute 메서드 인자 contribution/chunkContext
    -> contribution - 현재 단계 실행을 업데이트하기 위해 다시 전달되는 변경 가능한 상태
    -> chunkContext - 호출 간에는 공유되지만 재시작 간에는 공유되지 않는 속성

*tasklet 클래스가 재사용이 될 수 있는 상황에 적합하다.

  • Job 구성 클래스 내부에 tasklet 구현부를 넣어서 하나의 클래스로 하나의 업무를 정의하는 방식

Chunk 지향 프로세싱

한 번에 모든 행을 읽고 처리하고 쓰는 대신 한 번에 고정 된 양의 레코드(청크)를 읽고 처리하는 방식이다. 트랜잭션 경계 내에서 청크 단위(아이템이 트랜잭션에서 커밋되는 수)로 데이터를 읽고 생성하는 기법이다. 청크를 지정하게 되면 한 건에 실패에 대한 청크부터 뒤에까지만 영향을 받게 되어 실패한 청크 앞의 영역은 영향을 받지 않는다. 또한 청크만큼만 트랜잭션 시간을 가져가기 때문에 트랜잭션 시간을 짧게 가져갈 수 있다. 일괄 데이터 변경이나 어떤 데이터 변화를 주는 작업에 사용하면 좋다.

Chunk 단위로 병렬실행 시키는 방법

1) Tasklet을 implements한 tasklet 클래스에서 execute()를 재 정의한다. execute() 메서드에서는 청크 단위로 처리하는 작업을 한다.
-> Provider 클래스의 provide()를 호출해서 ItemReader에서 청크 사이즈 만큼 데이터를 가지고 온다.
-> Process 클래스의 process()를 호출해서 ItemReader에서 가져온 데이터를 가공하고, ItemWriter의 write()를 통해 데이터를 저장한다.
2) ChunkProvider를 implements한 Provider 클래스에서 Chunk 만큼에 데이터를 읽어서 tasklet로 업데이트할 데이터를 리턴해주는 역할을 하는 provide() 메서드를 재 정의한다.
3) ChunkProcessor, InitailizingBean을 implements한 Processor 클래스에서 process() 메서드를 재 정의한다. process() 메서드에서는 ItemWriter 하기 전에 빈으로 등록된 데이터를 읽고 데이터를 가공하는 처리를 해준다.
4) process()에서 가공이 끝나면 ItemWriter의 write() 메서드를 통해 데이터를 저장한다.

*참고 자료
https://oingdaddy.tistory.com/181
https://hororolol.tistory.com/513
https://k9e4h.tistory.com/392
https://wan-blog.tistory.com/55
https://techblog.woowahan.com/2662/

profile
자기 개발, 학습 정리를 위한 블로그

0개의 댓글