스프링 프로젝트를 진행하다 보면, 우연히 두 개 이상의 빈(bean) 타입이 중복되는 경우가 발생할 수 있습니다. 이런 경우에는 NoUniqueBeanDefinitionException 에러가 발생하여 어떠한 빈이 중복되었는지 알려줍니다.
! 문제 상황 발생 !
그렇다면, 해당 에러가 발생했을 때는 어떠한 해결책이 있을까요? 우선 문제가 발생하는 상황의 예시를 봅시다.
같은 타입의 이름이 다른 두 개의 빈을 등록하였습니다. 등록할 때는 문제가 되지 않습니다. 에러가 발생하는 것은 실제로 해당 타입의 빈이 사용이 될 때입니다. 다음 예제를 볼까요?
스프링 부트 입장에서는 참 난감합니다. 같은 타입의 빈이 두 개가 있는데, 어떤 의존성을 주입하라는 건지 알 수가 없습니다. 불쌍한 스프링 부트를 위해 이 에러를 해결해 줍시다.
1. 빈 이름 변경하기
당연하게도, 가장 간단한 해결 방법은 빈 이름을 변경하는 것입니다. 다음과 같이 이름을 변경해 봅시다.
첫 번째 메서드의 이름을 myDuck에서 duck으로 변경하였습니다. 이제 스프링 부트는 같은 이름의 빈을 찾았으니 더 이상 고민할 필요가 없게 되었습니다.
혹은, 빈 어노테이션에 이름을 명시할 수도 있습니다. 그림 2-2를 봅시다.
메서드 이름은 그대로 두고 빈 어노테이션에 이름을 명시하였습니다. 어떤 방식을 사용하던지 간에 빈 중복으로 인한 에러를 해결할 수 있습니다.
2. @Qualifier 어노테이션 사용하기
@Qualifier 어노테이션을 사용하면 동일한 타입의 빈이 여러 개일 때 구분할 수 있습니다. 생성자, setter 메서드, 혹은 필드 등 빈이 주입되는 어느 곳에서나 @Qualifier 어노테이션을 사용할 수 있습니다.
그리고 의존성을 주입하는 부분에 @Qualifier 어노테이션을 이용하여 어떤 빈을 사용할 건지 명시합시다.
3. @Primary 어노테이션 사용하기
@Primary 어노테이션을 사용하면 여러 개의 빈 중에서 우선적으로 주입할 빈을 선택할 수 있습니다.
단, Qualifier와 Primary가 동시에 사용될 때는 Qualifier가 우선권을 가져간다는 것에 주의합시다.
어떤 방법이 가장 좋은가?
같은 타입의 빈이 여러 개 존재하고 각각의 상황마다 특정한 빈을 선택해야 하는 경우, @Qualifier 어노테이션을 사용하는 것이 좋습니다. 이를 통해 사용할 빈을 지정하여 빈 선택을 효과적으로 제어할 수 있습니다.
또는, 가장 높은 우선순위를 주고 싶은 빈이 있다면 @Primary 어노테이션을 사용하는 것이 좋습니다. 이를 통해 구성이 단순해지고 디폴트 값으로 빈을 제어할 수 있습니다.
기본 빈에 @Primary를 사용하고 서브 빈에 @Qualifier를 사용하는 방법도 있습니다. 애플리케이션 설계와 요구사항에 따라 최적의 방법이 달라지므로 상황에 따라 유연하게 사용하는 것이 좋습니다.
참고
'Java & Spring Boot' 카테고리의 다른 글
Java 예외에는 어떤 유형이 있을까? (0) | 2023.04.02 |
---|---|
자주 쓰이는 디자인 패턴을 알아보자(with Java) (0) | 2023.03.19 |
자원을 반납하자 (부제: try-catch-finally 멈춰!) (0) | 2023.02.26 |
당신이 Raw type을 지양해야 하는 이유 (0) | 2023.02.12 |
실전, MVC 패턴! (1) | 2022.10.01 |