Spring Batch ‐ Tasklet vs Chunk - dnwls16071/Backend_Summary GitHub Wiki

📚 태스크릿(Tasklet) 지향 처리

  • 태스크릿(Tasklet) 지향 처리 모델은 Spring Batch에서 가장 기본적인 Step 구현 방식으로 비교적 복잡하지 않은 단순한 작업을 실행할 때 사용
  • 단일 비즈니스 로직 실행에 초점

[Tasklet 구현 예시]

@Slf4j
public class ZombieProcessCleanupTasklet implements Tasklet {

    private final int processesToKill = 10;
    private int killedProcesses = 0;

    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        killedProcesses++;
        log.info("☠️  프로세스 강제 종료... ({}/{})", killedProcesses, processesToKill);

        if (killedProcesses >= processesToKill) {
            log.info("💀 시스템 안정화 완료. 모든 좀비 프로세스 제거.");
            return RepeatStatus.FINISHED;  // 모든 프로세스 종료 후 작업 완료
        }

        return RepeatStatus.CONTINUABLE;  // 아직 더 종료할 프로세스가 남아있음
    }
}
  • RepeatStatus를 사용하는 이유는 거대한 하나의 트랜잭션 대신 작은 트랜잭션들로 나누어 안전하게 처리를 하기 위함이다.
  • PlatformTransactionManager 스프링 빈을 직접 정의할 땐 주의가 필요하다.
    • Spring Batch는 내부적으로 Job과 Step의 상태와 같은 메타데이터를 DB를 통해 관리한다.
    • 이 때, 트랜잭션이 사용되는데 별도의 구성 변경 없이 PlatformTransactionManager를 빈으로 정의할 경우 Step의 비즈니스 로직 처리를 위한 트랜잭션과 메타데이터 관리를 위한 트랜잭션이 서로 다른 성격임에도 불구하고 같은 "platformTransactionManager" 빈을 사용하기 때문에 의도치 않은 문제가 발생할 수 있다.

📚 청크 지향 처리

  • 청크(Chunk)는 데이터를일정 단위로 쪼갠 덩어리를 말한다. Spring Batch에서 데이터 기반 처리 방식을 청크 지향 처리라고 부르는 이유는, 읽고, 처리하고, 쓰는 작업을 일정 크기로 나눈 데이터 덩어리(청크)를 대상으로 하기 때문

[ItemReader]

public interface ItemReader<T> {
    T read() throws Exception, 
        UnexpectedInputException, 
        ParseException, 
        NonTransientResourceException;
}
  • read() 메서드는 아이템을 하나씩 반환
  • ItemReader가 null을 반환하는 것이 청크 지향 처리 Step의 종료 시점이라는 점을 반드시 기억
  • 다양한 구현체 제공

[ItemProcessor]

public interface ItemProcessor<I, O> {
    O process(I item) throws Exception;
}
  • 데이터 가공: 입력 데이터(I)를 원하는 형태(O)로 변환
  • 필터링: null을 반환하면 해당 데이터는 처리 흐름에서 제외
  • 데이터 검증: 입력 데이터의 유효성을 검사 / 필터링과 달리 조건에 맞지 않는 데이터를 만나면 예외를 발생
  • 필수 아님: ItemProcessor는 생략 가능

[ItemWriter]

public interface ItemWriter<T> {
    void write(Chunk<? extends T> chunk) throws Exception;
}
  • Chunk 단위로 묶어서 한 번에 데이터를 쓴다
  • 다양한 구현체 제공

Q. 그렇다면 적절한 청크 사이즈는 과연 얼마일까?
A. 청크 사이즈가 크면 그만큼 메모리에 많은 데이터를 한 번에 로드하게 된다. 트랜잭션 경계가 커지기 때문에 문제 발생 시 롤백되는 데이터의 양도 많아진다. 그러나 청크 사이즈가 작다면 트랜잭션 경계가 작아져서 문제 발생 시 롤백되는 데이터가 최소화된다. 하지만 그만큼 I/O 작업이 자주 발생하게 된다는 단점이 있다.

⚠️ **GitHub.com Fallback** ⚠️