[Spring Batch] Tasklet과 Chunk

유기훈·2025년 6월 16일

Tasklet

Spring Batch는 대량의 데이터를 처리하기 위한 프레임워크로, 다양한 방식으로 작업을 정의할 수 있습니다. 그 중 하나가 바로 Tasklet 기반의 처리입니다.

Tasklet이란?

Tasklet은 Spring Batch에서 단일 작업 단위를 수행하는 인터페이스입니다. 말 그대로 하나의 작업(Task) 을 수행하는 구성 요소이며, 반복적인 처리를 수행하기보다는 단순하거나 명확한 목적을 가진 작업에 적합합니다.

public interface Tasklet {
    RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception;
}

Tasklet은 주로 언제 사용하나

Tasklet은 주로 다음과 같은 상황에서 사용됩니다:

  • 단순한 작업 처리: 파일 삭제, 디렉터리 생성, API 호출, 상태 업데이트 등 반복이 필요 없는 단일 작업
  • 초기화나 정리 작업: 배치 수행 전 테이블 초기화, 배치 수행 후 로그 정리 등
  • 조건 분기, 흐름 제어: Step 내에서 간단한 조건 체크 및 흐름 분기
  • 데이터 처리 외 작업: 데이터를 읽고 쓰는 작업 외의 보조적인 기능이 필요할 때

Tasklet 사용하는 방법

아래는 간단한 Tasklet 구현 예제입니다. 이 Tasklet은 로그를 출력하고 작업을 완료합니다.

@Component
public class SimpleTasklet implements Tasklet {
    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        System.out.println("Tasklet 실행 중!");
        return RepeatStatus.FINISHED;
    }
}

이후, Step과 Job에 등록해서 사용할 수 있습니다.

@Bean
public Step taskletStep() {
    return stepBuilderFactory.get("taskletStep")
        .tasklet(simpleTasklet)
        .build();
}

RepeatStatus란?

RepeatStatus는 Tasklet이 작업을 반복할지 여부를 결정하는 enum입니다.

  • RepeatStatus.FINISHED : 작업이 완료되어 더 이상 반복하지 않음
  • RepeatStatus.CONTINUABLE : 작업을 반복해야 함 (거의 사용되지 않음)

예를 들어, 무한 루프나 조건 기반 반복이 필요할 경우 CONTINUABLE을 반환하고 내부에서 반복 조건을 제어할 수 있습니다.

트랜잭션과의 관계

Spring Batch에서 Tasklet은 기본적으로 Step 단위로 트랜잭션이 적용됩니다. 즉, Tasklet 내의 execute 메서드 전체가 하나의 트랜잭션으로 처리됩니다.

  • 예외가 발생하면 해당 Step은 롤백되며, 재시도나 실패 처리 로직을 수행할 수 있습니다.
  • DB 작업을 수행하는 Tasklet의 경우 트랜잭션 설정을 조정하거나 별도 Propagation을 고려해야 할 수도 있습니다.

트랜잭션을 세밀하게 제어하려면 Step 설정 시 transactionManager를 커스터마이징하거나, Tasklet 내에서 명시적으로 트랜잭션 처리를 해줘야 할 수 있습니다.

Chunk

Spring Batch는 대량 데이터를 효율적으로 처리하기 위해 Chunk 기반 처리 모델을 제공합니다. 이는 많은 데이터 처리 작업에서 가장 흔히 사용되는 방식이며, 대규모 데이터 배치에 최적화되어 있습니다.

Chunk란?

Chunk는 “일정 단위의 데이터를 모아 한 번에 처리하는 방식” 입니다. 예를 들어, 1000개의 데이터를 10개씩 나눠서 처리한다고 하면, 이 “10개 단위”가 하나의 Chunk가 됩니다.

이 모델은 다음과 같은 구조로 구성됩니다:

[Read] → [Process] → [Write]
         (Chunk 단위로 반복)

Chunk 처리 방식: 읽기 → 처리 → 쓰기

Chunk 기반 처리는 다음과 같은 순서로 진행됩니다:
1. ItemReader를 통해 데이터를 1건씩 읽고,
2. ItemProcessor로 읽은 데이터를 가공하고,
3. ItemWriter가 일정 개수(Chunk size)만큼 모아서 한 번에 저장합니다.

이 처리는 반복적으로 실행되며, 아래와 같은 순서로 진행됩니다:

for each chunk:
    read item → process item → accumulate
    ...
    when chunk is full:
        write all items

구성 요소

  1. ItemReader
  • 데이터를 읽는 역할
  • 파일, DB, API, 큐 등 다양한 소스에서 데이터를 한 건씩 읽음
  • 한 번에 하나의 Item을 반환하며, 더 이상 읽을 것이 없으면 null 반환
public interface ItemReader<T> {
    T read() throws Exception;
}
  1. ItemProcessor
  • 데이터를 가공하거나 변환하는 역할
  • 읽은 데이터를 새로운 형태로 가공하거나 필터링 (null 반환 시 해당 item은 skip)
  • 선택(Optional)이기 때문에 생략 가능
public interface ItemProcessor<I, O> {
    O process(I item) throws Exception;
}
  1. ItemWriter
  • 가공된 데이터를 Chunk 단위로 일괄 저장
  • List 형식으로 처리되어 들어옴 (Chunk size 만큼)
  • DB insert/update, 파일 쓰기 등 다양하게 사용
public interface ItemWriter<O> {
    void write(List<? extends O> items) throws Exception;
}

언제 Chunk를 사용할까?

Chunk 기반 처리는 아래와 같은 상황에서 매우 효과적입니다:

  • 대량의 데이터를 효율적으로 처리할 때
    → 예: 수천, 수만 건의 DB row를 읽어서 처리하고 다시 저장
  • 일정량 단위로 커밋이 필요할 때
    → 예: 100건마다 커밋하여 처리 속도 향상 + 트랜잭션 관리 용이
  • 가공/정제/검증이 필요한 데이터 처리
    → 예: 고객 데이터 정리, 주문 상태 변경, 로그 분석 등 데이터 흐름 예시
    Step 시작
       ↓
    [ItemReader] → item1
    [ItemProcessor] → processedItem1
    [ItemReader] → item2
    [ItemProcessor] → processedItem2
    ...
    Chunk Size 도달 (예: 10건)
       ↓
    [ItemWriter] → List<processedItem1...10> 저장
       ↓
    트랜잭션 커밋
       ↓
    다음 Chunk 반복

## Chunk와 트랜잭션
Spring Batch는 Chunk 단위로 트랜잭션을 처리합니다. 즉, 하나의 Chunk가 읽기 → 처리 → 쓰기까지 모두 성공해야 커밋됩니다.
- 실패 시 해당 Chunk 전체가 롤백
- 트랜잭션 경계는 다음과 같습니다:

[Chunk 시작]

  • read item
  • process item
  • accumulate
  • write
    [Chunk 끝] → 커밋 or 롤백
이 덕분에 부분 커밋 방지 및 데이터 정합성 보장이 가능해집니다.

주의사항:
- Chunk size가 너무 크면 메모리 사용량이 증가
- 너무 작으면 트랜잭션 오버헤드가 커짐 → 성능 저하 가능
profile
개발 블로그

0개의 댓글