[Spring] Spring Batch 와 Scheduler

Jihyoung·2023년 4월 15일
1

Spring

목록 보기
3/5
post-thumbnail

Spring Batch에 대해 공부하면서 플로우에 대해 이해는 했지만, Batch와 Scheduler와의 개념이 모호하게 다가와 둘의 차이에 대해 간략하게 알아보고 Spring batch의 동작 방식에 대해 정리해보려고 한다.

Batch란?

일괄처리 의 의미를 가지며, 사용자와 상호작용 없이 여러 개의 작업을 미리 정해진 순서에 따라 중단 없이 처리하는 것

Batch의 특징

  • 대용량 데이터 : 대량의 데이터를 가져오거나, 전달하거나, 계산하는 등의 처리를 할 수 있어야한다.
  • 자동화 : 심각한 문제 해결을 제외하고 사용자 개입없이 실행되어야 한다.
  • 견고성 : 잘못된 데이터를 충돌 / 중단 없이 처리할 수 있어야 한다.
  • 신뢰성 : 무엇이 잘못되었는지를 추적할 수 있어야한다. (로깅, 알림)
  • 성능 : 지정한 시간안에 처리를 완료하거나 동시에 실행되는 다른 어플을 방해하지 않도록 수행되어야 한다.

사용 사례

  • 대용량의 비즈니스 데이터를 복잡한 작업으로 처리해야하는 경우
  • 특정한 시점에 스케쥴러를 통해 자동화된 작업이 필요한 경우 (ex. 푸시알림, 월 별 리포트)
  • 대용량 데이터의 포맷을 변경, 유효성 검사 등의 작업을 트랜잭션 안에서 처리 후 기록해야하는 경우

Scheduler란?

시간할당 의 의미를 가지며, 특정한 시간에 등록한 작업을 자동으로 실행시키는 것

정리하자면, 특정 시간에 데이터를 전송하는 것을 예약하는 기능은 Scheduler를 통해 이뤄지고, 해당 전송 요청을 일괄적으로 처리해주는 것은 Batch를 통해 이루어진다.


Spring Batch

Spring Batch는 엔터프라이즈 시스템의 운영에 있어 대용량 일괄처리의 편의를 위해 설계된 가볍고 포괄적인 배치 프레임워크다.

아키텍처

Spring Batch의 계층 구조는 아래와 같이 설계되어 있기 때문에 Application 계층의 비즈니스 로직에 집중할 수 있고, 배치의 동작과 관련된 것은 Batch Core에 있는 클래스들을 이용하여 제어할 수 있다.

  • Application : Spring Batch를 사용하여 개발자가 작성한 모든 배치 작업과 사용자 정의 코드
  • Batch Core : 배치 작업을 시작하고 제어하는데 필요한 핵심 런타임 클래스를 포함
  • Batch Infrastructure : 개발자와 애플리케이션에서 사용하는 일반적인 Reader와 Writer 그리고 RetryTemplate과 같은 서비스를 포함

JobRepository

  • 다양한 배치 수행과 관련된 수치 데이터와 잡의 상태를 유지 및 관리
  • 일반적으로 관계형 데이터베이스를 사용하며 스프링 배치 내의 대부분의 주요 컴포넌트가 공유한다.
  • 실행된 Step, 현재 상태, 읽은 아이템 및 처리된 아이템 수 등을 저장

JobLauncher

  • Job을 실행하는 역할을 담당한다
    • Job.execute을 호출하는 역할이다.
  • Job의 재실행 가능 여부 검증, 잡의 실행 방법, 파라미터 유효성 검증 등을 수행

Job

  • 배치 처리 과정을 하나의 단위로 만들어 표현한 객체
  • 여러 Step 인스턴스를 포함하는 컨테이너
  • Job이 실행될 때 스프링 배치의 많은 컴포넌트는 탄력성(resiliency)을 제공하기 위해 서로 상호작용을 한다.

Step

  • 스프링 배치에서 가장 일반적으로 상태를 보여주는 단위
  • 각 Step은 잡을 구성하는 독립된 작업의 단위
  • Step에는 Tasklet, Chunk 기반으로 운영

일반적으로 스프링 배치는 대용량 데이터를 다루는 경우가 많기 때문에 Tasklet보다 상대적으로 트랜잭션의 단위를 짧게 하여 처리할 수 있는 ItemReader, ItemProcessor, ItemWriter를 이용한 Chunk 지향 프로세싱을 이용한다.

Tasklet

  • 초기화, 저장 프로시저 실행, 알림 전송과 같은 잡에서 일반적으로 사용
  • Step이 중지될 때까지 execute 메서드가 계속 반복해서 수행하고 수행할 때마다 독립적인 트랜잭션이 얻어진다.

Chunk

  • 한 번에 하나씩 데이터(row)를 읽어 Chunk라는 덩어리를 만든 뒤, Chunk 단위로 트랜잭션을 다루는 것
  • Chunk 단위로 트랜잭션을 수행하기 때문에 실패할 경우엔 해당 Chunk 만큼만 롤백이 되고, 이전에 커밋된 트랜잭션 범위까지는 반영이 된다.

Chunk 기반 Step은 위의 그림과 같이 ItemReader, ItemProcessor, ItemWriter라는 3개의 주요 부분으로 구성되며, ItemReader와 ItemProcessor에서 데이터는 1건씩 다뤄지고, Writer에선 Chunk 단위로 처리된다.

ItemReader

  • Step에서 Item을 읽어오는 인터페이스
  • ItemReader에 대한 다양한 인터페이스가 존재하며 다양한 방법으로 Item을 읽어 올 수 있다.

ItemProcessor

  • Item Processor는 Reader에서 읽어온 Item을 데이터를 처리
  • Processor는 배치를 처리하는데 필수 요소는 아님
  • Reader, Writer, Processor 처리를 분리하여 각각의 역할을 명확하게 구분하고 있습니다.

ItemWriter

  • 처리 된 Data를 Writer 할 때 사용
    • Writer는 기본적으로 Item을 Chunk로 묶어 처리
  • Writer 또한 Read와 동일하게 다양한 인터페이스가 존재
  • Writer는 처리 결과물에 따라 Insert가 될 수도 Update가 될 수도 Queue를 사용한다면 Send가 될 수도 있다.

위의 과정을 코드를 통해 나타내면 아래와 같다

for(int i=0; i<totalSize; i+=chunkSize){ 
    List items = new Arraylist();
    for(int j = 0; j < chunkSize; j++){
        Object item = itemReader.read()
        Object processedItem = itemProcessor.process(item);
        items.add(processedItem);
    }
    itemWriter.write(items);
}

Chunk 기반 처리를 할 때 주의할 점

Spring Batch에는 다양한 ItemReader와 ItemWriter가 존재한다.
대용량 배치 처리를 하게 되면 Item을 읽어 올 때 Paging 처리를 하는게 효과적이기 때문에 Spring Batch Reader에서는 지원하는 Paging 처리를 대체로 이용한다. 또한 적절한 Paging처리와 Chunk Size(한번에 처리 될 트랜잭션)를 설정하여 더욱 효과적인 배치 처리를 할 수 있다.

Page size vs Chunk size

Chunk Size한번에 처리될 트랜잭션 단위를 얘기하며,
Page Size한번에 조회할 Item의 양을 의미한다.

Page size와 Chunk size를 일치시켜줘야 한다?

chunk size 가 100이고 page size가 10일 경우 10번의 쿼리가 실행되게 된다. 이때 JpaPagingItemReader를 사용하게 되는데, 해당 클래스는 페이지를 읽을 때 트랜잭션을 초기화 한다.
Spring Batch chunk 기반 방식은 chunk 단위로 reader에서 processor로 전달되기에 100개를 채워야만 processor로 데이터가 전달된다는 특징이 있어 마지막 조회를 제외한 9번의 조회결과들의 세션이 종료가 되어 문제가 발생하게 되는 것이다.

*JpaPagingItemReader의 상위 클래스인 AbstractPagingItemReader 에서는 page size가 기본 10으로 설정되어 있음

또한 한번의 트랜잭션 처리를 위해 10번의 쿼리 조회가 발생하기 때문에 성능상 이슈가 발생할 수 있다. 그래서 Spring Batch의 PagingItemReader의 공식문서에 아래와 같은 내용을 담고 있다.

큰 페이지 크기를 설정하고 페이지 크기와 일치하는 commit 간격을 사용하면 성능이 향상 된다.

따라서 구현 시에는 chunk size와 page size를 일치시켜주는 것이 좋다.

Reference

profile
로그를 생활화

0개의 댓글