당니의 개발자 스토리
@Autowired와 @Qualifier 본문
getBean으로 Bean을 꺼낼 때,
만약 같은 타입 Bean이 여러 개 있다면 어떻게 해결할까?
Spring에서 DI를 쓰다 보면 자연스럽게 @Autowired를 사용하게 된다.
@Autowired는 필요한 Bean을 자동으로 넣어주는 애노테이션이다.
예를 들어 이런 코드가 있다고 해보자.
@Service
public class WasherUser {
private final Washer washer;
public WasherUser(Washer washer) {
this.washer = washer;
}
}
여기서 Washer 타입 Bean을 Spring이 찾아서 자동으로 넣어준다.
이걸 조금 더 풀어서 보면 이렇게 동작한다.
1. Washer 타입을 찾는다
2. Container에서 Bean 검색
3. 하나 있으면 바로 주입
이게 정상적인 흐름이다.
그런데 문제가 생기는 경우가 있다.
같은 타입 Bean이 여러 개 있을 때다.
예를 들어 이렇게 만들어보자.
@Component
public class SWasher implements Washer {
}
@Component
public class TurboWasher implements Washer {
}
이제 Washer 타입 Bean이 2개다.
이 상태에서 기존 코드를 그대로 쓰면 어떻게 될까?
public WasherUser(Washer washer)
Spring 입장에서는 이렇게 된다.
Washer 타입 달라고 했는데 두 개 있는데?
그래서 어떤 걸 넣어야 할지 결정하지 못한다.
그래서 에러가 터진다.
NoUniqueBeanDefinitionException
즉 같은 타입이 여러 개면 자동 주입이 실패한다.
이걸 해결하는 방법이 @Qualifier다.
@Qualifier는 Bean을 이름으로 지정해서 선택하는 방식이다.
예를 들어 이렇게 작성한다.
@Component("sWasher")
public class SWasher implements Washer {
}
@Component("turboWasher")
public class TurboWasher implements Washer {
}
그리고 주입할 때 이렇게 쓴다.
public WasherUser(@Qualifier("turboWasher") Washer washer) {
this.washer = washer;
}
이렇게 하면 Spring은 turboWasher Bean을 정확하게 찾아서 넣어준다.
즉 흐름은 이렇게 바뀐다.
1. 타입으로 후보 찾기 (Washer)
2. 이름으로 필터링 (turboWasher)
3. 최종 Bean 선택
여기서 중요한 점은 자동 주입은 기본적으로 타입 기준이라는 점이다.
@Autowired는 기본적으로 타입으로 Bean을 찾는다.
그래서 타입이 하나면 문제가 없지만,
여러 개면 충돌이 발생한다.
그래서 선택 기준을 추가로 주는 것이 @Qualifier다.
여기서 Bean 이름은 어떻게 정해질까?
@Component를 이렇게 쓰면
@Component
public class SWasher {
}
Bean 이름은 기본적으로 클래스 이름에서 앞글자만 소문자로 바뀐다.
sWasher
이게 기본 이름이다.
그래서 @Qualifier에도 이 이름을 넣어야 한다.
@Qualifier("sWasher")
또 하나 방법이 있다.
@Component("myWasher")
이렇게 직접 이름을 지정할 수도 있다.
그러면 Bean 이름은 myWasher가 된다.
@Bean도 마찬가지다.
@Bean
public SWasher sWasher() {
return new SWasher();
}
이 경우 Bean 이름은 메서드 이름을 따라간다.
sWasher
그래서 @Qualifier("sWasher")로 맞춰야 한다.
정리하면 이렇게 된다.
@Autowired
타입 기준으로 Bean을 찾는다
@Qualifier
이름 기준으로 Bean을 선택한다
그래서 같은 타입이 여러 개일 때는 반드시 선택 기준이 필요하다.
여기서 한 가지 더 알아두면 좋은 것이 있다!!
@Primary는 여러 Bean 중에서 기본으로 사용할 Bean을 지정하는 방식이다.
@Component
@Primary
public class SWasher implements Washer {
}
이렇게 하면 Washer 타입이 여러 개 있어도,
기본적으로 SWasher가 먼저 선택된다.
이 상태에서는 @Qualifier 없이도 동작한다.
하지만 특정 상황에서 다른 Bean을 쓰고 싶다면
그때는 @Qualifier를 같이 사용하면 된다.
1. 타입으로 후보 찾기
2. @Primary 있으면 우선 선택
3. @Qualifier 있으면 정확하게 선택
그래서 실무에서는 이렇게 사용한다.
기본 Bean은 @Primary
특정 상황은 @Qualifier
마지막으로 한 줄로 정리하면 이렇다.
@Autowired는 타입으로 찾고
@Qualifier는 이름으로 고른다
'Java, Spring' 카테고리의 다른 글
| Spring Bean 생명주기 (0) | 2026.05.06 |
|---|---|
| @Component vs @Bean (0) | 2026.05.06 |
| DI는 왜 필요할까? 객체 생성 책임과 Spring Container (0) | 2026.05.06 |
| Maven, 빌드 자동화 도구에 대해서 (0) | 2026.05.06 |
| JUnit과 Assertion으로 테스트 코드 작성하기 (0) | 2026.05.06 |