Match(소개 상대)를 계산하는 로직의 경우 모든 사용자들에 대해 수행이 되는데, 전체 사용자가 300명이라고 할 때, 290번째 데이터까지는 잘 진행되다가 291번째에 오류가 발생하여 배치 작업이 실패로 돌아간 경우, 다시 1번째 작업부터 시작하여야 하는데 이것의 매우 비효율적이다.
Spring 배치는 이런 상황에서 정확하게 실패가 발생한 290번째부터 다시 배치 작업을 수행하도록 한다.
효과적인 로깅, 통계 처리, 트랜잭션 관리 등 재사용 가능한 필수 기능을 제공한다. 수동으로 처리하지 않도록 자동화되어 있다. 예외사항과 비정상 동작에 대한 방어 기능을 제공한다.
스프링 부트 배치의 반복되는 작업 프로세스를 이해하면 비즈니스 로직에 집중 할 수 있다.


소개 상대를 계산하는 로직은 새벽 2시에 하루에 한 번 실행되도록 하고 싶고, 최종 매칭을 처리하는 로직은 10분에 한번씩 수행하도록 하고 싶다

MatchJobConfig와 FinalMatchJobConfig에서 각각 matchJob()과 finalMatchJob()로 함수 이름을 맞추면 JobScheduler @Autowired설정 시 자동으로 wired된다.


@Slf4j
@Configuration
@EnableBatchProcessing
@RequiredArgsConstructor
public class MatchJobConfig {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
private final EntityManagerFactory entityManagerFactory;
private final MatchService matchService;
@Bean
public Job matchJob() throws Exception {
return jobBuilderFactory.get("matchChunkJob")
.start(matchStep())
.build();
}
@Bean
@JobScope
public Step matchStep() throws Exception {
return stepBuilderFactory.get("step")
.<User, List<Match>>chunk(2)
.reader(matchReader())
.processor(matchProcessor())
.writer(matchListWriter())
.build();
}
@Bean
@StepScope
public JpaPagingItemReader<User> matchReader() throws Exception{
Map<String,Object> parameterValues = new HashMap<>();
log.info("ItemReader 실행됨");
return new JpaPagingItemReaderBuilder<User>()
.pageSize(2)
.parameterValues(parameterValues)
.queryString("SELECT m FROM User m")
.entityManagerFactory(entityManagerFactory)
.name("JpaPagingItemReader")
.build();
}
@Bean
@StepScope
public ItemProcessor<User, List<Match>> matchProcessor()
{
log.info("ItemProcessor 실행됨");
return new ItemProcessor<User, List<Match>>() {
@Override
public List<Match> process(User user) throws Exception
{
// 해당 user의 다른 사용자들에 대한 match 점수들 계산해서 얻어낸 match들 return
return matchService.calculateMatches(user);
}
};
}
@Bean
@StepScope
public JpaItemWriter<List<Match>> matchWriter()
{
log.info("ItemWriter 실행됨");
return new JpaItemWriterBuilder<List<Match>>()
.entityManagerFactory(entityManagerFactory)
.build();
}
@Bean
@StepScope
public JpaItemListWriter<Match> matchListWriter(){
JpaItemWriter<Match> writer = new JpaItemWriter<>();
writer.setEntityManagerFactory(entityManagerFactory);
JpaItemListWriter<Match> jpaItemListWriter = new JpaItemListWriter<>(writer);
jpaItemListWriter.setEntityManagerFactory(entityManagerFactory);
return jpaItemListWriter;
}
}