공공 요양병원 API 데이터를 주기적으로 동기화하는 배치 작업 구현
전체 데이터가 아닌 일부 데이터만으로 비교하다 보니 잘못된 데이터 갱신 발생,
실제로 운영 중인 병원이 CLOSE 상태로 잘못 변경되는 문제 발생
저는 공공요양병원 데이터를 동기화하기 위해 다음과 같은 Spring Batch Step을 구현했습니다.
@Bean
public Step hospitalDataStep() {
return new StepBuilder("hospitalDataStep", jobRepository)
.<HospitalEntity, HospitalEntity> chunk(10, platformTransactionManager)
.reader(hospitalDataReader())
.writer(hospitalDataWriter())
.faultTolerant()
.retry(Exception.class)
.retryLimit(3)
.build();
}
문제는 ItemWriter의 write() 메서드에서 발생했습니다. write() 메서드는 chunk 단위(10개)로 데이터를 전달받아 처리하는데, 이 과정에서 데이터베이스에 있는 전체 데이터(예: 100개)와 비교를 수행했습니다.
여기서 문제는 chunk 사이즈가 아니라, write() 메서드가 받는 데이터가 10개씩 분할되어 전달된다는 점입니다. 따라서 현재 chunk에 있는 10개의 데이터만을 가지고 전체 데이터베이스의 데이터와 비교하다 보니, 아직 전달받지 못한 나머지 chunk의 데이터들은 비교 대상에서 제외되는 문제가 발생했습니다.
문제를 해결하기 위해 StepExecutionListener를 활용했습니다. 이는 Spring Batch가 제공하는 인터페이스로, Step의 실행 전후에 추가 작업을 수행할 수 있게 해줍니다.
public class HospotalDataWriter implements ItemWriter<HospitalEntity>, StepExecutionListener {
private final HospitalRepository hospitalRepository;
private List<HospitalEntity> newHospitalDataListEntity = new ArrayList<>();
// step이 실행하면 초기화한다.
@Override
public void beforeStep(StepExecution stepExecution) {
newHospitalDataListEntity.clear();
}
@Override
public void write(Chunk<? extends HospitalEntity> chunk) {
// chunk로 들어오는 데이터를 전역 변수에 계속 쌓아둠
newHospitalDataListEntity.addAll(chunk.getItems());
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
// 모든 chunk 처리가 끝난 후 데이터 비교 실행
List<HospitalEntity> beforeData = hospitalRepository.findByHospStatus(HospStatus.OPEN);
// 요양기호(ykiho) 기준으로 비교를 위해 Set으로 변환
Set<String> beforeYkihoSet = beforeData.stream()
.map(HospitalEntity::getYkiho)
.collect(Collectors.toSet());
Set<String> newYkihoSet = newHospitalDataListEntity.stream()
.map(HospitalEntity::getYkiho)
.collect(Collectors.toSet());
// 데이터 동기화 처리
updateHospitalStatus(beforeData, newYkihoSet);
saveNewHospitals(beforeYkihoSet);
return ExitStatus.COMPLETED;
}
}
이렇게 구현함으로써:
1. write() 메서드에서는 데이터 수집만 담당
2. afterStep()에서 전체 데이터에 대한 비교와 처리를 한 번에 수행
3. 데이터의 정합성을 보장하면서 효율적인 처리가 가능