
배치 로그를 확인하던 도중 다음과 같은 경고 로그가 발생하였다.
[WARN ][schedulerFactoryBean_Worker-3] [o.s.b.core.listener.AbstractListenerFactoryBean] - org.springframework.batch.item.ItemReader is an interface. The implementing class will not be queried for annotation based listener configurations. If using
@StepScopeon a@Beanmethod, be sure to return the implementing class so listener annotations can be used.
경고 로그 자체의 내용은 직관적이었는데, 메서드에 @Bean 이나 @StepScope와 같은 어노테이션을 부착할 경우 리턴 타입은 반드시 인터페이스가 아닌 구현체로 등록해야한다는 것이었다.
사실 이전까지만 해도 ItemReader, ItemProcessor, ItemWriter 인터페이스의 구현 클래스를 만들고 그 클래스의 인스턴스를 private 메서드로 생성한 뒤 Step에 넣어주고 있었는데, ItemReader, ItemProcessor, ItemWriter의 생명 주기 관리가 필요해져서 @Bean, @StepScope 을 적용하면서 생긴 이슈이다.
// 이전
private ItemReader<TestAmountDto> itemReader() {
return new ItemReaderImpl();
}
// 현재
@Bean
@StepScope
public ItemReader<TestAmountDto> itemReader() {
return new ItemReaderImpl():
}
코드 자체는 정상적으로 작동하고는 있었지만 경고 로그가 계속 발생하고 있다는 것은, 어쨌든 위의 형식이 맞지 않고 그로 인한 사이드 이펙트가 발생할 여지가 있다는 점이기에 어떤 사이드 이펙트가 있는지 Claude에 질문을 했고, 다음과 같은 답변을 받았다.
문제 원인
- 리스너 애노테이션 감지: Spring Batch는
@BeforeStep,@AfterStep같은 리스너 애노테이션을 실제 구현 클래스에서 찾습니다. 인터페이스를 반환하면 이러한 애노테이션들을 검사할 수 없습니다.- @StepScope 프록시 생성:
@StepScope를 사용할 때 Spring은 빈을 프록시로 감쌉니다. 빈이 인터페이스로 등록되면 프록시는 구현체의 특정 메서드와 애노테이션에 접근할 수 없게 됩니다.
발생할 수 있는 사이드 이펙트
- 리더 구현체에 정의된 리스너 애노테이션이 동작하지 않을 수 있습니다
- Spring Batch의 일부 기능이 예상대로 동작하지 않을 수 있습니다
- 배치 처리 중의 중요한 라이프사이클 이벤트를 놓칠 수 있습니다
인터넷에서 다른 레퍼런스를 확인해보니 향로님도 비슷한 이슈에 대해 글을 작성해두신 것이 있었다.
https://jojoldu.tistory.com/132
대응 방법은 아주 간단하다. ItemReader, ItemProcessor, ItemWriter 등의 인터페이스의 실제 구현체를 등록해주면 된다.
@Bean
@Scope
public ItemReaderImpl itemReader() {
return new ItemReaderImpl():
}
사실 보통 @Bean 어노테이션으로 빈을 등록할 때에 기존에는 실제 구현체보다는 인터페이스로 리턴 타입을 잡아두는 경우가 상당히 많았어서 문제가 없을 줄 알았는데 Spring Batch에서는 다른 부분이 있어서 신기했다.