[JAVA] Spring Boot 기동 시 Failed to start bean 해결 과정

Spring Boot 애플리케이션을 실행하다 보면 가장 흔하게 마주치는 오류 중 하나가 "Failed to start bean" 입니다. 단순히 설정이 틀린 경우도 있지만, 의존성 구조나 초기화 흐름 문제까지 얽혀 있는 경우가 많아 디버깅이 길어지기 쉽습니다.

Spring Boot Failed to start bean 오류가 발생하는 이유

Spring Boot에서 Failed to start bean 오류는 말 그대로 특정 Bean을 생성하지 못했을 때 발생합니다. Spring 컨테이너가 초기화되는 과정에서 의존성 주입, 설정값 바인딩, 라이프사이클 메서드 실행 중 하나라도 실패하면 애플리케이션이 기동되지 않습니다.

이 오류는 단순히 Bean 하나의 문제가 아니라, 전체 컨텍스트 초기화 실패로 이어진다는 점이 중요합니다. 그래서 에러 메시지의 첫 줄보다 "Caused by" 아래를 보는 것이 더 좋습니다.

 

실제로 많이 발생하는 원인 유형

1. 의존성 주입 실패

가장 흔한 케이스입니다. 생성자 또는 필드 주입 시 필요한 Bean을 찾지 못하면 바로 실패합니다.

@Service
public class OrderService {

    private final PaymentClient paymentClient;

    public OrderService(PaymentClient paymentClient) {
        this.paymentClient = paymentClient;
    }
}

이 경우 PaymentClient Bean이 등록되어 있지 않으면 바로 실패합니다. 실무에서는 패키지 스캔 범위 문제로 빠지는 경우가 생각보다 많습니다.

2. 설정값 바인딩 실패

@ConfigurationProperties나 @Value를 사용할 때 값이 없거나 타입이 맞지 않으면 Bean 생성이 실패합니다.

@Value("${external.api.url}")
private String apiUrl;

application.yml에 값이 없으면 바로 예외가 발생합니다. 특히 환경별 설정을 나눌 때 빠뜨리기 쉬운 부분입니다.

3. 순환 참조 (Circular Dependency)

Bean A가 Bean B를 참조하고, Bean B가 다시 Bean A를 참조하는 구조입니다.

최근 Spring Boot에서는 기본적으로 순환 참조를 허용하지 않기 때문에 이 경우 바로 기동 실패로 이어집니다. 설계상 책임을 분리해야 하는 신호로 보는 편이 좋습니다.

4. 초기화 로직 실패 (@PostConstruct)

Bean 생성 이후 실행되는 초기화 코드에서 예외가 발생해도 동일한 오류가 발생합니다.

@PostConstruct
public void init() {
    if (externalService.call() == null) {
        throw new RuntimeException("init failed");
    }
}

이 경우는 로그를 보면 Bean 생성 자체는 되었지만 초기화 단계에서 실패한 것으로 나타납니다.

 

문제 해결 접근 순서

이 오류는 원인이 다양하기 때문에 순서대로 좁혀가는 방식이 중요합니다.

1. Caused by 로그부터 확인

가장 위의 메시지는 요약에 가깝고, 실제 원인은 아래쪽에 있습니다. 스택트레이스를 끝까지 내려서 확인해야 합니다.

2. Bean 생성 위치 추적

어떤 클래스에서 실패했는지 확인한 뒤, 생성자와 필드 주입 부분을 먼저 봅니다. 대부분 여기에서 단서가 나옵니다.

3. 설정 파일 확인

환경 변수, yml, profile 설정을 함께 확인합니다. 특히 로컬에서는 되는데 서버에서 안 되는 경우는 이 부분일 가능성이 높습니다.

4. 의존성 그래프 점검

순환 참조가 있는지, 불필요하게 서로 참조하고 있는 구조는 아닌지 확인합니다. 서비스 레이어에서 서로 호출하는 구조가 생기면 여기서 문제가 드러납니다.

 

자주 놓치는 포인트

실무에서는 아래 케이스를 놓치는 경우가 많습니다.

첫 번째는 패키지 스캔 범위입니다. 메인 클래스 기준으로 하위 패키지만 스캔되기 때문에, 구조를 나누다가 Bean이 등록되지 않는 경우가 있습니다.

두 번째는 테스트 코드와 실제 실행 환경의 차이입니다. 테스트에서는 MockBean으로 해결되던 부분이 실제 실행 시에는 그대로 실패하는 경우가 있습니다.

세 번째는 Optional Bean 처리입니다. 조건부 Bean(@ConditionalOnProperty 등)을 사용하는 경우, 조건이 맞지 않으면 Bean이 생성되지 않는다는 점을 고려해야 합니다.

실무 기준으로 보는 정리

Failed to start bean 오류는 특정 기술 문제라기보다, Spring 컨테이너 초기화 과정 전체를 이해하고 있는지가 드러나는 지점입니다.

단순히 에러 메시지를 보고 대응하기보다는, Bean이 언제 생성되고 어떤 순서로 초기화되는지 흐름을 알고 접근하는 것이 훨씬 빠르게 해결됩니다.

개인적으로는 새로운 기능을 추가할 때 Bean 간 의존 관계를 단순하게 유지하는 것이 가장 효과적이었습니다. 구조가 단순하면 이런 오류도 자연스럽게 줄어듭니다.