Spring

Spring Boot No qualifying bean of type 오류 해결: 컴포넌트 스캔·@Qualifier·프로필 점검 (Spring

바른정보블로그 2026. 9. 10. 18:19
Spring Boot No qualifying bean 오류를 컴포넌트 스캔과 의존성 연결 점검으로 해결하는 개발자용 3D 일러스트

확인 기준: 2026년 9월 10일, Spring Boot 4.1.1·Spring Framework 7.0.x 공식 문서

No qualifying bean of type은 주입 지점에서 요구한 타입에 맞는 Spring Bean을 찾지 못했거나, 반대로 후보가 여러 개라 하나를 고르지 못했을 때 나타납니다. 무작정 @Autowired를 추가하기보다 예외 마지막 부분의 타입·후보 수·활성 프로필을 순서대로 확인해야 합니다.

빠른 결론
① 구현 클래스에 @Service 등 빈 등록 표시가 있는지 봅니다.
② 메인 클래스의 하위 패키지가 스캔되는지 확인합니다.
③ 후보가 여러 개면 @Primary 또는 @Qualifier, 후보가 0개면 프로필·조건을 점검합니다.

오류 문구로 원인 구분

예외 핵심 우선 점검
expected at least 1 bean 후보 0개 애너테이션·스캔 범위·프로필
expected single matching bean but found 2 후보 여러 개 @Primary·@Qualifier
테스트에서만 발생 제한된 테스트 컨텍스트 슬라이스 범위·테스트용 빈
특정 환경에서만 발생 프로필 또는 조건 불일치 spring.profiles.active·조건 속성

No qualifying bean of type 해결 순서

  1. 예외 맨 아래의 타입과 주입 위치를 읽습니다.
    예를 들어 com.example.order.PaymentService가 없다고 나오면 해당 인터페이스의 구현체와 주입받는 생성자를 함께 엽니다. 위쪽의 긴 스택보다 required a bean of type, available, 후보 이름 부분이 직접적인 단서입니다.
  2. 구현 클래스를 Bean으로 등록합니다.
    자동 탐색 대상이라면 클래스에 @Component, @Service, @Repository, @Controller 중 역할에 맞는 애너테이션이 있어야 합니다. 외부 라이브러리 클래스처럼 직접 표시할 수 없다면 @Configuration 클래스의 @Bean 메서드로 등록합니다.
    @Service
    public class DefaultPaymentService implements PaymentService { }
    
    @Configuration
    class PaymentConfig {
      @Bean
      PaymentClient paymentClient() { return new PaymentClient(); }
    }
  3. 컴포넌트 스캔 범위를 맞춥니다.
    Spring Boot는 보통 @SpringBootApplication이 있는 패키지를 기준으로 하위 패키지를 찾습니다. 공식 문서도 메인 클래스를 다른 클래스보다 위쪽의 루트 패키지에 둘 것을 권장합니다. 구현체가 바깥 패키지에 있다면 구조를 옮기거나 필요한 범위만 명시합니다.
    @SpringBootApplication(scanBasePackages = {
      "com.example.app", "com.example.shared"
    })
    public class Application { }
  4. 생성자에서 요구한 타입을 비교합니다.
    구현체가 등록돼도 주입 타입과 상속 관계가 맞지 않으면 후보가 아닙니다. 인터페이스 PaymentService를 주입한다면 구현 클래스가 실제로 그 인터페이스를 구현하는지 확인합니다. 생성자 주입은 필요한 의존성을 한곳에서 드러내므로 누락된 타입을 찾기 쉽습니다.
    @Service
    class OrderService {
      private final PaymentService paymentService;
      OrderService(PaymentService paymentService) {
        this.paymentService = paymentService;
      }
    }
  5. 같은 타입 후보가 여러 개면 선택 기준을 줍니다.
    기본 구현 하나를 정할 때는 그 Bean에 @Primary를 붙입니다. 주입 지점마다 다른 구현을 써야 한다면 생성자 매개변수에 @Qualifier("card")처럼 의미 있는 값을 지정하고 대상 Bean에도 같은 qualifier를 표시합니다.
    @Service("card")
    class CardPaymentService implements PaymentService { }
    
    OrderService(@Qualifier("card") PaymentService service) {
      this.paymentService = service;
    }
  6. 활성 프로필을 확인합니다.
    @Profile("prod")가 붙은 @Component@Configuration은 해당 프로필이 활성일 때만 로드됩니다. 실행 설정, 환경 변수, application.ymlspring.profiles.active가 기대한 값인지 확인합니다. 로컬에서는 되지만 서버에서만 실패한다면 가장 먼저 비교할 항목입니다.
  7. 조건부 설정과 테스트 범위를 점검합니다.
    @ConditionalOnBean, @ConditionalOnMissingBean, @ConditionalOnProperty는 조건이 맞지 않으면 Bean을 만들지 않습니다. @WebMvcTest 같은 슬라이스 테스트는 전체 애플리케이션을 올리지 않으므로 테스트가 요구하는 의존성을 테스트 설정 또는 Mock으로 제공해야 합니다.

주의사항

  • @ComponentScan("com")처럼 지나치게 넓은 범위는 시작 시간을 늘리고 원치 않는 설정까지 읽을 수 있습니다.
  • 후보가 여러 개인데 이름만 우연히 맞춰 해결하지 말고 @Primary나 의미가 분명한 @Qualifier를 사용하세요.
  • 에러를 숨기려고 의존성을 무조건 Optional로 바꾸면 실제 구성 누락을 놓칠 수 있습니다.

해결되지 않을 때 추가 점검

IDE 검색으로 해당 타입의 구현체와 @Bean 메서드를 모두 찾고, 빌드 산출물에 모듈이 포함됐는지 확인합니다. 멀티 모듈 프로젝트라면 실행 모듈의 Gradle 또는 Maven 의존성 방향도 봅니다. 이후 조건 평가 보고서에서 제외된 자동 구성과 매칭되지 않은 조건을 확인합니다.

FAQ

Q1. 를 붙이면 해결되나요?

주입 표시가 없어서가 아니라 대상 Bean이 등록되지 않은 경우가 많습니다. 먼저 구현체 애너테이션, 스캔 범위, 프로필을 확인해야 합니다.

Q2. 와 중 무엇을 쓰나요?

대부분의 주입 지점에서 같은 구현을 기본으로 쓸 때는 @Primary, 지점별로 명확히 구현을 고를 때는 @Qualifier가 적합합니다.

Q3. IntelliJ에서는 클래스가 보이는데 왜 Bean은 없나요?

클래스패스에 존재하는 것과 Spring 컨테이너에 Bean으로 등록되는 것은 다릅니다. 컴포넌트 스캔, @Bean, 프로필, 조건부 설정을 별도로 확인하세요.

함께 보면 좋은 글

공식 출처

Spring Boot 4.1.1과 Spring Framework 7.0.x 문서를 기준으로 작성했으며, 사용 중인 버전의 API와 지원 정책을 함께 확인하세요.