[JAVA] ApplicationContext 로딩 실패 문제 해결 경험

Spring Boot를 사용하다 보면 ApplicationContext 로딩 실패로 애플리케이션이 아예 기동되지 않는 경우를 한 번쯤 겪게 됩니다. 단순한 설정 실수처럼 보이지만, 실제로는 다양한 원인이 얽혀 있는 경우가 많아 원인 파악에 시간이 꽤 걸립니다.

ApplicationContext 로딩 실패 문제란 무엇인가

ApplicationContext 로딩 실패는 Spring Boot 애플리케이션이 시작 단계에서 Bean 초기화에 실패하면서 컨텍스트 자체가 생성되지 못하는 상황을 의미합니다. 로그에는 보통 Failed to start ApplicationContext 또는 BeanCreationException 같은 메시지가 함께 출력됩니다.

이 문제는 단순히 특정 Bean 하나의 오류로 끝나지 않고, 전체 애플리케이션 기동 자체를 막는다는 점에서 영향 범위가 큽니다. 그래서 에러 메시지를 빠르게 읽고 원인을 좁히는 것이 중요합니다.

 

실제 발생했던 증상과 로그

실무에서 자주 보는 형태는 다음과 같습니다. 특정 Bean 생성 실패가 연쇄적으로 이어지면서 ApplicationContext가 올라오지 않는 구조입니다.


org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'userService'

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException

처음 보면 가장 아래 에러만 보게 되는데, 실제로는 위에서부터 어떤 Bean이 어떤 Bean을 의존하다가 실패했는지 흐름을 따라가야 합니다.

 

원인 분석 과정

1. 의존성 주입 실패

가장 흔한 케이스입니다. 필요한 Bean이 등록되지 않았거나, 스캔 범위 밖에 있을 때 발생합니다.


@Service
public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

UserRepository가 Bean으로 등록되지 않았다면 바로 실패합니다. 인터페이스만 있고 구현체가 없거나, @Repository가 빠진 경우도 많습니다.

2. 순환 참조 (Circular Dependency)

두 Bean이 서로를 참조하는 경우입니다. 최근 Spring Boot에서는 기본적으로 순환 참조를 허용하지 않기 때문에 바로 에러가 발생합니다.


@Service
public class AService {
    private final BService bService;
}

@Service
public class BService {
    private final AService aService;
}

이 구조는 설계적으로도 문제가 되는 경우가 많아서, 중간 계층을 분리하거나 이벤트 기반으로 풀어내는 것이 더 자연스럽습니다.

3. 설정 파일 오류

application.yml이나 properties 설정 값이 잘못된 경우에도 ApplicationContext 로딩이 실패할 수 있습니다.

예를 들어 DB 연결 정보가 틀리면 DataSource Bean 생성 단계에서 바로 실패합니다. 이 경우는 Bean 코드 문제가 아니라 환경 설정 문제입니다.

4. 프로파일 설정 문제

특정 profile에서만 Bean이 등록되도록 설정한 경우도 주의해야 합니다.


@Profile("dev")
@Service
public class DevOnlyService {
}

실행 시 profile이 dev가 아니라면 해당 Bean은 아예 생성되지 않습니다. 의존하고 있는 쪽에서는 존재하지 않는 Bean을 찾게 됩니다.

 

해결 방법 정리

ApplicationContext 로딩 실패는 패턴이 어느 정도 정해져 있기 때문에, 순서를 잡고 접근하는 것이 중요합니다.

먼저 로그의 가장 아래가 아니라, Bean 생성 흐름 전체를 위에서 아래로 읽습니다. 어떤 Bean에서 시작해서 어디서 깨졌는지 보는 것이 핵심입니다.

그 다음으로는 아래 순서로 확인하는 편이 효율적입니다.

  • Bean 등록 여부 확인 (@Component, @Service, @Repository)
  • 패키지 스캔 범위 확인
  • 순환 참조 여부 확인
  • 프로파일 설정 확인
  • 환경 설정 값 (DB, 외부 API 등) 확인

이 순서로 보면 대부분의 케이스는 빠르게 정리됩니다.

 

실무에서의 기준

이 문제는 디버깅 자체보다, 예방이 더 중요합니다.

의존 관계를 단순하게 유지하고, Bean 간 역할을 명확히 나누는 것이 기본입니다. 특히 서비스 간 직접 참조를 줄이고 인터페이스 기반으로 설계하면 순환 참조를 피하기 쉬워집니다.

또한 profile 기반 Bean 분리는 필요한 경우에만 사용하는 것이 좋습니다. 설정이 많아질수록 어떤 환경에서 어떤 Bean이 올라오는지 파악이 어려워집니다.

 

정리

ApplicationContext 로딩 실패는 다양한 원인으로 발생하지만, 결국 Bean 생성 과정에서 문제가 생긴 것입니다.

로그 흐름을 따라가며 원인을 좁히고, 의존성 구조와 설정을 차근히 점검하는 방식으로 접근하면 대부분 해결할 수 있습니다.

처음에는 복잡해 보이지만, 몇 번 경험해 보면 어디를 먼저 봐야 하는지 감이 잡히는 영역입니다.