IT/Spring

[Spring] Spring Batch 도입기

어린이개발자 2025. 1. 2. 21:01

회사에서 주소 데이터를 카카오 API 를 호출하여 획득한 정보로 대용량 업데이트 해야 할 일이 생겼다.

스케줄러를 활용해 주기적으로 업데이트를 하는데, 이 때 Spring Batch 개념을 활용하기로 결정하였다.

그래서 이를 도입할 때의 내용을 정리하고자 한다.

 

1. 도입 배경

- 대용량 데이터 일괄 처리에 필요한 시간이 커서 단순 API 호출로는 해결할 수 없어 대체 방안 필요 

 

2. 환경 설정

- build.gradle 에 의존성(dependency) 추가

implementation 'org.springframework.boot:spring-boot-starter-batch'

 

3. Configuration 파일 추가 및 설정

 3.1. BatchConfig.java

  - ItemReader, ItemProcessor, ItemWriter

    - 여기서 ItemReader 는 JpaPagingItemReader 를, ItemWriter 는 JpaItemWriter 를 사용 (회사에서 JPA 를 적극 사용하고 있기 때문에 간단한 배치 개발에는 제일 적합하다고 생각하였다. 향후 목적에 맞게 다양한 Reader 와 Writer 를 고려하여 결정할 예정이다.)

 3.2. ItemProcessor 에서 비즈니스 로직 작성

@Configuration
@EnableBatchProcessing // 스프링 배치 사용을 위해선 필수
@RequiredArgsConstructor
public class BatchConfig extends OriginObject {

    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;
    private final EntityManagerFactory entityManagerFactory;

    private final AddressWorker addressWorker;

    private int chunkSize = 10;

    @Bean
    public Job addressJob() {
        return jobBuilderFactory.get("addressJob")
                .start(addressStep())
                .build();
    }

    @Bean
    public Step addressStep() {
        return stepBuilderFactory.get("addressStep")
                .<Addresses, Addresses> chunk(chunkSize)
                .reader(pagingItemReader())
                .processor(pagingItemProcessor())
                .writer(pagingItemWriter())
                .build();
    }

    @Bean
    public JpaPagingItemReader<Addresses> pagingItemReader() {
        String query = "SELECT a FROM Addresses o WHERE o.address is not null ORDER BY o.addressNo";

        return new JpaPagingItemReaderBuilder<Addresses>()
                .name("pagingItemReader")
                .entityManagerFactory(entityManagerFactory)
                .pageSize(chunkSize)
                .queryString(query)
                .build();
    }

    @Bean
    public ItemProcessor<Addresses, Addresses> pagingItemProcessor() {
        return item -> {
            String address = item.getAddress();
            Map addressMap = addressWorker.getAddressDetailInfo(address);
            if(bePresent(addressMap)) {
                item = addressWorker.setModelAddress(addressMap, item.getAddressNo());
            }
            return item;
        };
    }

    @Bean
    public JpaItemWriter<Addresses> pagingItemWriter() {
        JpaItemWriter<Addresses> jpaItemWriter = new JpaItemWriter<>();
        jpaItemWriter.setEntityManagerFactory(entityManagerFactory);
        return jpaItemWriter;
    }

    @Bean
    public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor(JobRegistry jobRegistry) {
        JobRegistryBeanPostProcessor processor = new JobRegistryBeanPostProcessor();
        processor.setJobRegistry(jobRegistry);
        return processor;
    }

 

4. 한계

- 사용자 인터페이스 없이 시스템 내부적으로 작동해야 하는 건에 대해서만 사용 가능

'IT > Spring' 카테고리의 다른 글

[Spring] JDK Proxy vs. CGLIB  (0) 2025.01.05
[Spring] Reflection  (1) 2025.01.03
[Spring] WebFlux 테스트 코드 작성  (0) 2024.11.27
[Spring] Spring Framework vs. Spring Boot  (2) 2024.11.14
[Spring] Spring IoC Container  (0) 2023.05.21