JpaCursorItemReader Chunk 설정

러블리소피·2025년 1월 7일

✅ JpaCursorItemReader와 Chunk 설정은 그대로 사용해도 됩니다.

JpaCursorItemReader를 사용할 때도 Spring Batch의 Chunk 기반 처리는 그대로 유지됩니다.
하지만 JpaPagingItemReader와는 내부 동작이 조금 다르기 때문에 주의할 몇 가지 점을 설명드리겠습니다.

🧩 Chunk 기반 처리와 Cursor 방식의 차이점

✅ JpaPagingItemReader

  • 페이지 단위로 데이터를 읽어옵니다.
  • 매 페이지마다 쿼리가 실행되며, 페이지가 바뀔 때마다 새로운 트랜잭션이 시작될 수 있습니다.
  • Chunk 단위로 커밋이 가능합니다.

✅ JpaCursorItemReader

  • 한 번 커서가 열리면 종료될 때까지 유지됩니다.
  • 데이터베이스와 지속적인 연결이 유지되며, 커서가 닫힐 때까지 전체 트랜잭션이 유지됩니다.
  • Chunk 단위로 커밋은 가능하지만, 트랜잭션 자체는 커서가 닫힐 때까지 유지됩니다.

📝 그럼 Chunk 설정은 어떻게 될까?

Chunk 설정은 그대로 사용할 수 있습니다.

@Bean
public Step myStep(StepBuilderFactory stepBuilderFactory,
                   JpaCursorItemReader<OrderDelivery> reader,
                   ItemWriter<OrderDelivery> writer) {
    return stepBuilderFactory.get("myStep")
        .<OrderDelivery, OrderDelivery>chunk(100)  // Chunk 단위로 처리
        .reader(reader)
        .writer(writer)
        .build();
}

✅ Chunk 설정을 그대로 사용할 수 있는 이유

  • JpaCursorItemReader는 데이터를 하나씩 읽으면서 Chunk 단위로 데이터 처리를 합니다.
  • 예를 들어 chunk(100)으로 설정하면, 커서에서 100개씩 읽고 ItemWriter로 넘긴 뒤 커밋합니다.
  • 커밋은 Chunk 단위로 이루어지지만, 트랜잭션은 전체 데이터 처리 동안 유지됩니다.

⚠️ 주의할 점: 트랜잭션 관리

JpaCursorItemReader는 트랜잭션이 전체 배치 실행 동안 유지되기 때문에 다음 사항을 고려해야 합니다.

📌 주의 사항 1: 데이터베이스 커넥션

  • 커서가 열려 있는 동안 데이터베이스 커넥션이 계속 유지되므로, 커넥션이 오래 열려 있으면 데이터베이스 리소스를 많이 사용하게 됩니다.
  • 대량 데이터 처리 시 커넥션이 끊기거나, 커넥션 풀이 부족해질 수 있으니 주의하세요.

💡 해결 방법:

  • Chunk 크기를 적절히 조절하세요.
    예: chunk(1000) 대신 chunk(100)으로 설정하면, 한 번에 처리하는 데이터가 줄어들어 커넥션 리소스를 줄일 수 있습니다.

📌 주의 사항 2: 트랜잭션 타임아웃

  • 전체 트랜잭션이 유지되기 때문에 트랜잭션 타임아웃 설정을 확인해야 합니다.
  • 데이터 처리 시간이 길어지면 트랜잭션이 타임아웃될 위험이 있습니다.

💡 해결 방법:

  • Spring Batch에서 트랜잭션 타임아웃을 설정할 수 있습니다.
@Bean
public Step myStep(StepBuilderFactory stepBuilderFactory,
                   JpaCursorItemReader<OrderDelivery> reader,
                   ItemWriter<OrderDelivery> writer) {
    return stepBuilderFactory.get("myStep")
        .<OrderDelivery, OrderDelivery>chunk(100)
        .reader(reader)
        .writer(writer)
        .transactionManager(transactionManager())
        .build();
}

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory);
    transactionManager.setDefaultTimeout(600);  // 타임아웃 설정 (초 단위)
    return transactionManager;
}

📌 주의 사항 3: Fail-safe 처리

  • JpaCursorItemReader는 데이터를 커서로 순차적으로 읽기 때문에 배치 도중에 실패가 발생하면 다시 시작할 때 처음부터 다시 읽게 됩니다.
  • 따라서 재시작 가능성을 고려하여 데이터를 처리할 필요가 있습니다.

💡 해결 방법:

  • ExecutionContext를 사용하여 읽은 데이터를 기록하고, 실패 시 재시작 지점을 설정할 수 있습니다.

✅ 결론: Chunk 그대로 사용 가능, 하지만 트랜잭션 관리 주의!

✅ 추천 설정

  • Chunk 크기: chunk(100) 또는 상황에 따라 적절히 조절
  • 트랜잭션 타임아웃: 600초(10분) 이상 설정
  • 데이터베이스 커넥션 풀: 충분한 커넥션을 확보

Chunk를 그대로 사용해도 되지만, 대량 데이터 처리 시 트랜잭션 관리와 커넥션 리소스를 신경 써야 합니다.
특히, 데이터베이스 커넥션 타임아웃과 트랜잭션 타임아웃에 주의하세요! 😊

profile
발전하는 개발자가 되고싶어요

0개의 댓글