갓생사는 김초원의 개발 블로그
chocho_log
갓생사는 김초원의 개발 블로그
전체 방문자
오늘
어제
  • 분류 전체보기 (79)
    • 개발 (24)
      • Spring (5)
      • Java (4)
      • Database (2)
      • Elasticsearch (3)
      • ETC (3)
      • JPA (3)
      • 이슈 (1)
    • 코딩 테스트 (43)
      • 프로그래머스 (23)
      • 백준 (12)
      • TIP (8)
    • 자료구조 (2)
    • 알고리즘 (4)
    • 잡생각 (0)
    • 경험 (5)
      • AWS re:Invent 2024 (5)

블로그 메뉴

    공지사항

    인기 글

    태그

    • jar
    • jpa
    • querydsl
    • 지연로딩
    • Lazy Loading
    • war
    • Spring Boot Embedded Tomcat
    • 디자인패턴 #SOLID 원칙

    최근 댓글

    최근 글

    갓생사는 김초원의 개발 블로그

    chocho_log

    Spring Batch 5 → 6 업그레이드 후 BeforeChunk가 동작하지 않았던 이유
    개발/Spring

    Spring Batch 5 → 6 업그레이드 후 BeforeChunk가 동작하지 않았던 이유

    2026. 1. 23. 21:34

    2025년 11월, Spring Batch 6이 릴리즈되었다.
    프로젝트를 Spring Boot 4.0으로 업그레이드하면서, 의존성으로 포함되어 있던 Spring Batch 역시5 → 6으로 자동 업그레이드되었다. Spring Boot 전반에 걸쳐 많은 변경 사항이 있었지만, 그중에서도 Spring Batch 6으로 업그레이드한 이후 BeforeChunk가 더 이상 호출되지 않는 것처럼 보이는 문제를 겪게 되었다.
    이 글에서는 해당 현상이 발생한 원인과, 이를 어떻게 이해하고 해결했는지를 정리해보려고 한다.
     

    Spring Batch 5에서의 BeforeChunk

    먼저 BeforeChunk에 대해 간단히 정리해보자.
    BeforeChunk는 Spring Batch에서 각 Chunk 처리가 시작되기 전에 호출되는 콜백이다.
    주로 Chunk 단위의 상태 초기화, 로그 출력, 메트릭 수집 등의 용도로 사용된다. ItemReader → ItemProcessor → ItemWriter가 실행되기 전에 호출되며, 하나의 Step 안에서 Chunk 단위로 반복 호출되는 것이 특징이다.
     
    Spring Batch 5 기준으로는 다음과 같은 순서로 동작한다.
    BeforeChunk
     → ItemReader.read()
     → ItemProcessor.process()
     → ItemWriter.write()
     → AfterChunk
     
    즉, ItemReader가 실행되기 전에 beforeChunk가 호출되며, 하나의 Step 안에서 Chunk 단위로 반복 호출된다.
    아래는 Spring Batch 5를 기반으로 동작하던 프로젝트의 예시 코드이다.

    @Component
    @StepScope
    class TestReader() : ItemReader<Long>, ChunkListener<Long, Long> {
        private val logger = LoggerFactory.getLogger(this::class.simpleName)
    
        override fun beforeChunk(chunk: Chunk<Long>) {
               logger.info("print before chunk") // read() 보다 먼저 실행
        }
    
        override fun read(): Long? {
            return 10000L // beforeChunk 이후에 실행
        }
    }

     
    이처럼 Spring Batch 5에서는 beforeChunk가 read() 호출보다 먼저 실행되는 것이 자연스러운 동작이었다.

     
    Spring Batch 6 업그레이드 이후의 변화

    하지만 Spring Batch 6으로 업그레이드한 이후, beforeChunk 메서드가 호출되지 않고 곧바로 read()부터 실행되는 것처럼 보이는 현상을 발견했다. 혹시나 해서 @BeforeChunk 어노테이션 기반으로 변경해 보았지만, 결과는 동일했다.
    Migration Guide를 확인해보니 다음과 같은 변경 사항이 있었다.

      • ChunkListener#beforeChunk(ChunkContext) 메서드 deprecated
      • beforeChunk(Chunk<I> chunk) 사용 권장

    단순히 파라미터 타입만 변경된 것으로 보였기 때문에, 이 변경만으로 beforeChunk가 아예 동작하지 않는 것은 쉽게 이해되지 않았다.

     
    GitHub Issue 등록과 답변

    공식 문서만으로는 명확한 답을 찾기 어려워, Spring Batch GitHub에 직접 Issue를 등록했다.
    https://github.com/spring-projects/spring-batch/issues/5226

    Clarify ChunkListener changes in v6 · Issue #5226 · spring-projects/spring-batch

    Bug description After upgrading from Spring Batch 5.x to 6.x, ChunkListener callbacks are no longer invoked when defined on an ItemReader. This affects both of the following approaches: • Implement...

    github.com

    돌아온 답변은 다음과 같았다.

    Step을 설정할 때 이미 deprecated된 chunk 메서드를 사용하고 있는 것 같다고 했다.
    하지만 이미 마이그레이션 과정에서 해당 부분은 수정한 상태였기 때문에, 이 문제는 원인이 아니라고 판단했다. (Migration Guide 링크)

    // legacy implementation (v5)
    Step step = new StepBuilder("myStep", jobRepository)
                    .chunk(5, transactionManager)
                    // ...
                    .build();
    
    // new implementation (v6)
    Step step = new StepBuilder("myStep", jobRepository)
                    .chunk(5)
                    .transactionManager(transactionManager)
                    // ...
                    .build();

     
    이후 두 번째 답변에서 핵심적인 설명을 얻을 수 있었다.

     

    원인: beforeChunk의 호출 시점 변경

    답변의 핵심 내용을 정리하면 다음과 같다.

    새로운 구현에서는 ChunkListener 메서드들이
    ChunkContext 대신 아이템들의 묶음인 Chunk 자체를 파라미터로 받도록 변경되었습니다.
    그런데 가만히 생각해보면,
    청크를 읽기 전에 아직 청크 자체가 존재하지 않기 때문에
    beforeChunk(Chunk chunk) 메서드에 전달할 수 있는 값이 없습니다.

    그래서 beforeChunk는
    청크가 실제로 처리 가능해진 시점,
    즉 데이터 소스로부터 청크를 읽어온 이후에만 호출되도록 변경되었습니다.

     
    데이터를 읽은 이후에만 beforeChunk가 호출되도록 변경되었다 =  read() 이후에 호출된다 ?
    바로 확인해보니 실제 chunk 단위만큼 read() 메서드가 호출되고 write() 메서드가 호출되기 직전에 beforeChunk 메서드가 호출되었다.
    Spring Batch 5와 6의 beforeChunk, afterChunk 의 호출 흐름을 비교해보면 다음과 같다.

    왼쪽: Spring Batch 5 / 오른쪽: Spring Batch 6

     
    처음에는 Spring Batch 6으로 업그레이드하면서 beforeChunk가 아예 동작하지 않는 줄로만 생각했다.
    하지만 실제로는 read() 이전이 아니라 이후에 호출되도록 동작 방식이 변경된 것이었고, 내가 기대하던 실행 시점과 달라서 동작하지 않는 것처럼 착각했던 것이었다
    사실 BeforeChunk가 반드시 필요한 동작이 아니라면 해당 로직은 read 메서드만으로도 돌아가도록 수정한다던가 하고 그냥 넘어갔을 수도 있다. 하지만 그냥 넘어가지 않고 궁금한 점이 있다면 GitHub Issue를 통해 직접 질문하는 것도 좋은 방법이라는 점을 다시 한번 느꼈다.
    물론 Migration Guide만으로는 알기 어려운 동작 변화가 있을 수 있음을 인지하고 ChunkListener의 Javadoc을 더 꼼꼼히 읽는 것도 중요하다.
     
    정리하면, Spring Batch 6부터 BeforeChunk는 read() 이전이 아닌 이후에 호출된다.
    버전 업그레이드 후 기존 코드가 의도와 다르게 동작할 수 있으니 주의하자.
     
     

    관련 문서
    - https://docs.spring.io/spring-batch/docs/6.0.0-M2/api/org/springframework/batch/core/listener/ChunkListener.html
    -  https://docs.spring.io/spring-batch/docs/6.0.0-M2/api/org/springframework/batch/core/listener/ChunkListener.html

     
     
     

    '개발 > Spring' 카테고리의 다른 글

    Spring Boot 배포 WAR 에서 JAR 로 변경하기 (Spring Boot Embedded Tomcat 사용하기)  (2) 2022.04.13
    QueryDSL + multi data source 연동하기  (0) 2021.09.13
    webflux + reactive redis cache 적용하기  (2) 2021.08.23
    Spring-Cloud-Data-Flow(SCDF)구축해보기  (4) 2020.11.10
      '개발/Spring' 카테고리의 다른 글
      • Spring Boot 배포 WAR 에서 JAR 로 변경하기 (Spring Boot Embedded Tomcat 사용하기)
      • QueryDSL + multi data source 연동하기
      • webflux + reactive redis cache 적용하기
      • Spring-Cloud-Data-Flow(SCDF)구축해보기
      갓생사는 김초원의 개발 블로그
      갓생사는 김초원의 개발 블로그
      갓생사는 김초원의 개발 블로그 github: https://github.com/kimchowon

      티스토리툴바