그 외 공부/트러블 슈팅

Spring Boot 3 버전 도입 후 NoSuchBeanDefinition 오류 발생 원인과 해결

SeongOnion 2024. 1. 6. 22:24
728x90

서론

사내에서 나를 포함한 소수의 사람들에 의해 Spring Boot 3 버전대의 도입이 서서히 준비가 되면서, 관련 의존성이 있는 모듈 및 프로젝트 역시 새 버전과 호환시켜주는 작업이 필요했다.

 

사실 사내에서 유용하게 사용되고 있는 공통 모듈들은 우리 팀에서 만든 것들이 많았는데,

 

대부분 내가 직/간접적으로 참여했다거나 혹은 본인이 부트 3 버전 도입에 적극적으로 임한 것을 이유로 어쩌다보니 거의 대부분 내가 하고 있게 되었다. 😂 (물론 너무 좋은 경험이기도 하다)

 

정식 마이그레이션 가이드를 기반으로 연관있는 클래스들의 변경사항을 참고하여 작업을 진행했고, 와중에 놓친 것들이 있으면 발생하는 예외 로그를 통해 확인하면서 하나씩 고쳐갈 수 있었다.

 

하지만, 오류 발생 원인을 찾기 힘들었던 상황도 많았고 특히 해당 오류가 버전 마이그레이션 때문인지도 불분명한 상황이 있었다.

 

그리고 그 중 하나였던 마이그레이션 후 NoSuchBeanDefinition 예외가 발생 원인을 기록하고자 한다.

 

문제상황

해당 문제는 사내 라이브러리를 마이그레이션하는 중 발생했다.

 

기존 버전에서 사용했던 javax 패키지명을 모두 jakarta로 변경하기만 하면 됐던 간단한 업데이트였으나, 변경 후 해당 라이브러리를 사용하는 프로젝트에서 테스트해보니 전에는 잘만 스캔됐던 라이브러리 패키지 내의 빈들이 갑자기 등록되지 않았다.

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type '...' available:

@Qualifier 를 사용한 Bean이었기에 뭔가 오타가 있었던가 싶어서 눈 부릅뜨고 원인을 찾아봤지만, 역시 그 이유는 아니었다.

 

그리고 해당 빈은 @Configuration 클래스에 정의된 타입의 Bean이었기에, 해당 Configuration 자체가 읽히지 않았다고 판단했다.

 

원인

원인은 Auto-Configuration Files에 대한 업데이트였다. 

 

기존에는 spring.factories 파일 내에 org.springframework.boot.autoconfigure.EnableAutoConfiguration을 키로 하여 사용자 개별의 auto-configuration들을 등록시킬 수 있었다.

 

하지만 Spring Boot 2.7 버전부터는 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports라는 새로운 auto-configuration 등록 파일이 추가되었다.

 

그리고 기존의 spring.factories 내에 등록시키는 방식은 Spring Boot 2 버전대까지는 유지되었으나, 3 버전으로 업데이트되면서 더 이상 지원되지 않게 되었다.

 

해결

Spring Boot 2.7 릴리즈 노트에 명시된 작성 가이드를 따라 기존의 spring.factories 파일을 삭제하고, 기존 내용을 새로운 파일에 형식에 맞게 옮겨주기만 하면 된다.

 

먼저, META-INF/spring/ 패키지 하위에 org.springframework.boot.autoconfigure.AutoConfiguration.imports 라는 이름의 파일을 생성한다.

 

이후, spring.factories에 적혀있던 내용을 콤마 구분 없이 붙여주면 된다.

기존)

# spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.myapp.MyAutoConfiguration,\
com.example.myapp.MyAutoAnotherConfiguration,

 

수정)

# org.springframework.boot.autoconfigure.AutoConfiguration.imports

com.example.myapp.MyAutoConfiguration
com.example.myapp.MyAutoAnotherConfiguration