회사에서 주소 데이터를 카카오 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 |