Boocam 프로젝트에 Spring Batch로 주기적인 데이터 업데이트를 구현한 이후 Application을 실행시켰더니 위에 첨부한 사진처럼 APPLICATION FAILED TO START
메시지가 뜨며 종료되는 문제를 발견했습니다.
가장 중요한 에러 메시지를 읽어봤습니다.
Parameter 1 of method deleteOldReviewsJob in com.fasttime.global.config.BatchConfig required a single bean, but 7 were found:
BatchConfig
의 deleteOldReviewsJob
이라는 메서드 첫번째 파라미터에 하나의 빈이 요구되는데, 7개가 발견되었다는 내용이었습니다.
문제가 발생한 BatchConfig
의 deleteOldReviewsJob
메서드를 살펴봤습니다.
@Bean
public Job deleteOldReviewsJob(JobRepository jobRepository, Step deleteOldReviewsStep) {
return new JobBuilder("deleteOldReviewsJob", jobRepository)
.start(deleteOldReviewsStep)
.build();
}
해당 메서드는 2번째 파라미터에서 Step
를 deleteOldReviewsStep
이라는 이름으로 받아오고 있습니다.
그리고 그 아래, 다음처럼 Step
스프링 빈 객체를 생성하는 여러개의 메서드가 정의되어 있었습니다.
~ 생략 ~
@Bean
@Primary
public Step deleteOldReviewsStep(JobRepository jobRepository,
PlatformTransactionManager transactionManager, DeleteOldReviewsTasklet tasklet) {
return new StepBuilder("deleteOldReviewsStep", jobRepository)
.tasklet(tasklet, transactionManager)
.build();
}
~ 생략 ~
@Bean
public Step updateActivityStatusStep(JobRepository jobRepository,
PlatformTransactionManager transactionManager, UpdateActivityStatusTasklet tasklet){
return new StepBuilder("updateActivityStatusStep", jobRepository)
.tasklet(tasklet,transactionManager)
.build();
}
~ 생략 ~
deleteOldReviewsStep
, updateActivityStatusStep
그리고 그 외 5개의 메서드가 Step
을 반환하도록 정의되어 있었습니다.
Step
타입의 빈이 여럿 있으니, 그 중에 어떤 빈을 주입해야 하는지 정확하게 한정할 수 없어서 발생한 문제였습니다.
어떤 빈을 주입해야 하는지 한정할 수 없기 때문에 발생한 문제라면, 해결 방법도 자연스레 어떤 빈을 주입해야 하는 지 한정시키는 것으로 좁혀집니다.
의존 객체를 선택할 수 있도록 한정시키는 방법은 3가지가 있었습니다.
@Primary
를 붙여 해당 애노테이션을 붙인 메서드로 생성한 빈을 우선적으로 주입하도록 한다. @Qualifier
로 한정 값을 설정해 주입할 빈을 한정할 수 있도록 한다. 저는 세 번째 방법인 @Qualifier
를 사용하는 방법을 채택했습니다. '
첫 번째 방법은 메서드 이름에 따라 인덱스가 변하기 때문에 메서드 이름 변경만으로도 문제를 초래할 수 있기 때문에 빠르게 넘어갔고, 두 번째 방법은 각 메서드마다 한정해야 할 빈이 다르기 때문에 내 상황에 알맞는 해결책은 아니라고 판단했습니다.
@Bean
public Job deleteOldReviewsJob(JobRepository jobRepository,
@Qualifier("deleteOldReviewsStep") Step deleteOldReviewsStep) {
return new JobBuilder("deleteOldReviewsJob", jobRepository)
.start(deleteOldReviewsStep)
.build();
}
위처럼 @Qualifier
에 deleteOldReviewsStep
이라는 한정 값을 설정하기만 하면 됩니다. 각 빈의 기본 한정자는 빈을 생성한 메서드명이기 때문에, 이렇게 지정해두면 주입할 빈을 한정 값과 일치하는 한정자를 가진 빈 객체로 한정할 수 있게 됩니다.
스프링 설정 클래스에서 같은 타입의 빈 객체가 여러 개인 경우 @Primary
와 @Qualifier
애노테이션을 적절히 사용하여 한정할 수 있게 되었습니다.
이론상으로만 배운 것을 실제로 문제로 마주해 문제 해결에 사용하면서 체득할 수 있었던 것 같습니다.