Fine-tuning Annotation-based Autowiring with @Primary or @Fallback
2023. 7. 8. 19:06ㆍSpring Framework/Spring IoC
이 섹션에서는 “다중 후보 빈 중에서 특정 빈을 우선적으로 선택”해야 하는 상황에서 Spring이 제공하는 미세 조정(fine-tuning) 기능을 소개하고 있습니다.
과거에는 주로 @Primary
(스프링 3.0+)만 알려졌지만, Spring 6.2 버전부터는 새로운 @Fallback
애노테이션도 도입되어, 주입 우선순위를 더욱 세밀하게 제어할 수 있게 되었습니다.
1) 왜 필요한가?
- 스프링에서 “타입에 따른 자동 주입”(@Autowired, @Inject 등)을 쓸 때, 같은 타입을 구현하는 여러 개의 Bean이 등록되어 있으면 스프링은 “어느 한 Bean”을 선택해야 합니다.
- 만약 명시적인 지정(
@Qualifier
)이나 대표 Bean(@Primary
) 지정이 없으면,NoUniqueBeanDefinitionException
예외가 발생할 수 있습니다.
예:
@Configuration
public class MovieConfiguration {
@Bean
public MovieCatalog firstMovieCatalog() { ... }
@Bean
public MovieCatalog secondMovieCatalog() { ... }
}
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog; // <-- 같은 타입이 2개라 충돌
}
위 경우, MovieCatalog
가 2개 있으므로 하나만 주입할 수가 없어서 충돌이 일어납니다.
이를 해결하기 위해 Spring은 @Primary
, @Qualifier
, @Fallback
같은 메커니즘을 제공합니다.
2) @Primary
애노테이션
- 가장 전통적인 방법: 만약 한 빈을 유일한 대표(“primary”)로 삼고 싶다면, 그 빈 정의에
@Primary
를 붙입니다. - 스프링은 여러 후보 중 @Primary가 붙은 빈을 우선 선택해서 주입합니다.
예:
@Configuration
public class MovieConfiguration {
@Bean
@Primary
public MovieCatalog firstMovieCatalog() {
return new FirstMovieCatalog();
}
@Bean
public MovieCatalog secondMovieCatalog() {
return new SecondMovieCatalog();
}
}
- 이 설정에서는
MovieCatalog
를 구현한 Bean이 2개 있더라도,firstMovieCatalog()
가 @Primary로 지정되어 있으므로,MovieRecommender
나 다른 클래스에서@Autowired MovieCatalog
를 단일 필드로 주입할 때 무조건firstMovieCatalog
가 선택됩니다.
3) 새롭게 등장한 @Fallback
(Spring 6.2+)
- Spring 6.2 버전부터 새롭게 추가된 애노테이션
@Primary
는 “내가 대표 Bean이다”라는 적극적 의미라면,@Fallback
은 “나는 서브(대체) Bean이니, 다른 정규(regular) Bean이 없으면 그때만 나를 사용”이라는 소극적 의미로 작동합니다.- 구체적으로:
- “Regular” Bean:
@Fallback
가 붙어있지 않은 Bean (즉, 일반적인 Bean) - “Fallback” Bean:
@Fallback
가 붙은 Bean
- “Regular” Bean:
- 만약 어떤 타입의 Bean이 “Regular”와 “Fallback”를 섞어서 여러 개 있을 경우,
- 먼저 “Regular” Bean 중에서 여러 개가 있다면, 여전히 충돌(NoUniqueBeanDefinitionException) 혹은
@Primary
빈을 선택 - 만약 “Regular” Bean이 정확히 하나만 존재한다면, 그게 곧 주입 대상이 되고, “Fallback” Bean은 무시
- 만약 “Regular” Bean이 아예 없거나 여러 개 중에서 조건이 맞지 않는다면, 그때 “Fallback” Bean이 주입 후보가 될 수 있음(필요 시 하나만 남아야 함)
- 먼저 “Regular” Bean 중에서 여러 개가 있다면, 여전히 충돌(NoUniqueBeanDefinitionException) 혹은
예:
@Configuration
public class MovieConfiguration {
@Bean
public MovieCatalog firstMovieCatalog() {
return new FirstMovieCatalog();
}
@Bean
@Fallback
public MovieCatalog secondMovieCatalog() {
return new SecondMovieCatalog();
}
}
- 여기서
firstMovieCatalog()
는 “regular Bean”,secondMovieCatalog()
는 “fallback Bean”이 됩니다. @Autowired private MovieCatalog movieCatalog;
주입 시,- “regular” Bean이 1개이므로(
firstMovieCatalog
), 스프링은 그걸 주입 대상으로 선택 - “fallback”인
secondMovieCatalog
는 후보에 들지 않음
- “regular” Bean이 1개이므로(
- 만약
@Bean
에서firstMovieCatalog()
가 사라지거나,@Conditional
등에 의해 등록되지 않았다면, 이제 “regular Bean”이 없으므로 “fallback Bean”인secondMovieCatalog
가 사용됩니다. - 즉, “regular”가 있으면 그걸 쓰고, 없으면 “fallback”을 쓰는 전략입니다.
● 이는 “서브(대체) Bean”을 등록해두되, 정상 상황에서는 쓰지 않고, 정규 Bean이 없을 때만 대신 쓰고자 하는 시나리오에 적합합니다.
● 예: 특정 라이브러리가 없는 환경에서만 대체 구현체를 제공하는 경우 등.
4) 공통점: MovieRecommender
에 단일 필드 주입 → 한 Bean만 선택
문서의 예시:
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
// ...
}
@Autowired
된movieCatalog
필드에 MovieCatalog 타입의 구현체가 2개 이상 존재하면 충돌- @Primary 붙은 게 1개면 자동으로 그걸 선택
- @Fallback도 마찬가지로, “regular”와 “fallback” 조합에 따라 1개만 선택되도록 동작
공식 문서에서 말하듯이,
"With both variants of the preceding configuration, the following MovieRecommender is autowired with the firstMovieCatalog."
즉, firstMovieCatalog
가 주입된다는 것은, 두 가지 경우가 동일하게 작동함을 의미합니다.
5) 실제 선택 로직 비교
@Primary
방식:- 다수 후보 중 @Primary가 붙은 Bean이 “무조건 우선순위 1위”
- “대표 Bean”이라는 개념
- 만약 @Primary 붙은 Bean이 여러 개면 충돌
@Fallback
방식(Spring 6.2+):- 우선 "fallback 아닌 Bean들(Regular)" 중에서 하나만 남으면 그걸 선택
- Regular가 여러 개면 충돌(NoUniqueBeanDefinitionException), @Primary가 있으면 그걸 선택
- Regular가 하나도 없거나 등록이 안 되었다면, 그제서야 Fallback Bean 후보들 중 하나를 선택
- 복수의 @Fallback Bean이 있으면 다시 또 충돌 발생 가능(
NoUniqueBeanDefinitionException
)
즉, @Fallback
은 “정규 빈이 존재하지 않을 때만” 사용되는 구조입니다.
6) 요약
@Primary
: “우선순위가 가장 높은(대표) Bean”을 지정하는 고전적인 방법. 다중 후보 중 하나를 강제 선택할 때 사용@Fallback
(Spring 6.2+): “이 Bean은 일반 후보가 없을 때만” 사용하도록 표시해두는 애노테이션.- 정규(regular) Bean이 하나도 없으면 fallback Bean이 대신 주입
- 정규 Bean이 존재하면 fallback Bean은 무시
- 둘 다 “다중 후보 빈 중 하나를 선택”하는 문제를 해결하는데, 의도와 시나리오가 조금 다릅니다.
- 문서 예제에서 보인 것처럼,
firstMovieCatalog()
가 @Primary이거나,secondMovieCatalog()
가 @Fallback이면 결과적으로firstMovieCatalog
가 우선적으로 주입되어,MovieRecommender
가firstMovieCatalog
Bean을 참조하게 됩니다.
'Spring Framework > Spring IoC' 카테고리의 다른 글
Using @Autowired (0) | 2023.12.10 |
---|---|
Dependencies and Configuration in Detail (0) | 2023.12.10 |
Dependency Injection of Spring Framework (0) | 2023.05.01 |
Bean Definition Inheritance (0) | 2023.04.28 |
Introduction to the Spring IoC Container and Beans, Container Overview (0) | 2023.04.25 |