월요일

Spring Boot NoSuchBeanDefinitionException 해결 — Bean을 못 찾는 이유 5가지

Spring Boot NoSuchBeanDefinitionException 해결 — Bean을 못 찾는 이유 5가지

핵심 답변: NoSuchBeanDefinitionException은 Spring 컨테이너가 의존성 주입 시 해당 타입의 Bean이 찾지 못할 때 발생한다. 원인은 ① 컴포넌트 스캔 범위 밖, ② 어노테이션 누락, ③ 구현체 복수 등록, ④ @Bean 미등록, ⑤ 조건부 Bean 조건 불충족 — 이 5가지로 압축된다.

Spring Boot 프로젝트를 시작하면 이런 에러가 뜬다.

org.springframework.beans.factory.NoSuchBeanDefinitionException:

No qualifying bean of type 'com.example.service.UserService' available:

expected at least 1 bean which qualifies as autowire candidate.

또는

org.springframework.beans.factory.BeanCreationException:

Error creating bean with name 'userController':

Unsatisfied dependency expressed through field 'userService'

NoSuchBeanDefinitionException의 의미는 단 하나다: Spring IoC 컨테이너에 해당 타입의 Bean이 등록되어 있지 않다. 코드가 막아 보여도 등록이 안 되어 있으면 반드시 이 에러가 난다.

원인 1: 컴포넌트 스캔 범위 밖

@SpringBootApplication은 해당 클래스가 위치한 패키지와 그 하위 패키지만 스캔한다. 이 범위 밖의 클래스는 @Service를 붙여도 Bean으로 등록되지 않는다. 문제 구조:
com.example.app

└── Application.java ← @SpringBootApplication

com.example.service

└── UserService.java ← @Service 붙여도 스캔 안 됨

해결:
// 방법 1: Application을 최상위 패키지로 이동

// com.example → Application.java

// 방법 2: 스캔 범위 명시

@SpringBootApplication(scanBasePackages = {"com.example.app", "com.example.service"})

public class Application {}

// 방법 3: @ComponentScan 추가

@ComponentScan(basePackages = "com.example")


원인 2: @Component / @Service / @Repository 누락

어노테이션이 없으면 Spring은 그 클래스를 Bean으로 인식하지 않는다.

// ❌ 잘못된 예

public class UserService { // @Service 없음

public User findById(Long id) { ... }

}

// ✅ 올바른 예

@Service

public class UserService {

public User findById(Long id) { ... }

}

Lombok @RequiredArgsConstructor를 써도 마찬가지다. 어노테이션 없으면 Bean이 아니다.


원인 3: 인터페이스 구현체가 여러 개

PaymentService 인터페이스의 구현체가 KakaoPayService, NaverPayService 두 개라면 Spring은 어느 것을 주입할지 결정하지 못한다.
NoUniqueBeanDefinitionException:

expected single matching bean but found 2: kakaoPayService, naverPayService

해결:
// @Primary — 기본 구현체 지정

@Service

@Primary

public class KakaoPayService implements PaymentService {}

// @Qualifier — 주입 시 명시

@Autowired

@Qualifier("naverPayService")

private PaymentService paymentService;

// 변수명으로 지정 (변수명 = Bean 이름)

@Autowired

private PaymentService kakaoPayService;


원인 4: @Configuration에서 @Bean 등록 누락

외부 라이브러리 클래스는 @Configuration@Bean을 명시해야 한다. 이 과정 없이 @Autowired하면 에러가 난다.

// ❌ @Bean 미등록

@Configuration

public class AppConfig {

// RestTemplate 등록 없음

}

@Service

public class ApiService {

@Autowired

private RestTemplate restTemplate; // NoSuchBeanDefinitionException!

}

// ✅ @Bean 명시

@Configuration

public class AppConfig {

@Bean

public RestTemplate restTemplate() {

return new RestTemplate();

}

}


원인 5: 조건부 Bean 조건 불충족

@ConditionalOnProperty 등이 붙은 Bean은 조건이 맞지 않으면 컨테이너에 등록 자체가 되지 않는다.
@Bean

@ConditionalOnProperty(name = "feature.payment.enabled", havingValue = "true")

public PaymentService paymentService() {

return new PaymentService();

}

# application.yml — 이 설정이 없으면 Bean 등록 안 됨

feature:

payment:

enabled: true


빠른 디버깅: 등록된 Bean 목록 확인

management:

endpoints:

web:

exposure:

include: beans

/actuator/beans에서 현재 등록된 모든 Bean을 확인할 수 있다. 문제의 Bean 이름이 목록에 없으면 등록이 안 된 것이다.

체크리스트

증상원인해결
어노테이션 있는데 에러패키지 스캔 범위 밖scanBasePackages 추가
인터페이스 주입 에러구현체 복수 등록@Primary 또는 @Qualifier
외부 라이브러리 주입 에러@Bean 미등록@Configuration에 @Bean 추가
환경별로 다르게 동작조건부 Bean 조건 불충족프로퍼티 값 확인

자주 묻는 질문 (FAQ)

Q. @Autowired 없이 생성자 주입해도 같은 에러가 나나요?

A. 네. 에러 원인은 Bean 등록 여부이지 주입 방식이 아니다. @RequiredArgsConstructor, 생성자 직접 선언, @Autowired 모두 동일하게 발생한다.

Q. 로컬에선 되는데 운영에서만 에러가 납니다.

A. @ConditionalOnProperty@Profile로 환경별 Bean 등록을 제어하는 코드가 있을 가능성이 높다. application-prod.yml에 해당 프로퍼티가 누락됐는지 확인한다.

Q. BeanCreationExceptionNoSuchBeanDefinitionException은 다른 에러인가요?

A. BeanCreationException은 Bean 생성 도중 발생하는 상위 예외다. caused by 라인을 찾으면 내부 원인으로 NoSuchBeanDefinitionException이 포함된 경우가 많다.


정리

NoSuchBeanDefinitionException 진단 순서:

1. 클래스에 @Service / @Component / @Repository가 있는가?

2. 컴포넌트 스캔 패키지 범위 안에 있는가?

3. 구현체가 여러 개라면 @Primary 또는 @Qualifier로 지정했는가?

4. 외부 클래스라면 @Configuration@Bean으로 등록했는가?

5. 조건부 Bean이라면 조건이 충족되는가?

이 5단계를 순서대로 확인하면 원인이 반드시 나온다.


댓글 없음:

댓글 쓰기