이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.

  • 자동 설정 클래스는 어떤 @Conditional 조건으로 적용 여부를 판단하는가?
  • 사용자가 Bean을 직접 등록하면 Boot 기본 설정이 왜 물러나는가?
  • 자동 설정을 제외하지 않고 원하는 동작으로 조정하는 순서는 무엇인가?

개요

자동 설정을 이해하는 핵심 키워드는 조건과 back-off다. Boot는 모든 기본 Bean을 무조건 등록하지 않는다. 조건이 맞을 때만 등록하고, 사용자가 이미 같은 역할의 Bean을 제공했다면 물러나는 경우가 많다.

이 철학 덕분에 Boot는 빠른 시작과 커스터마이징을 동시에 제공한다. 기본값은 제공하지만 사용자의 명시적 선택을 이기지 않으려는 것이다.

주요 조건

@ConditionalOnClass는 특정 클래스가 classpath에 있을 때만 설정을 적용한다. 예를 들어 Jackson 관련 클래스가 있으면 JSON message converter 설정이 후보가 될 수 있다.

@ConditionalOnMissingBean은 같은 역할의 Bean이 없을 때만 기본 Bean을 만든다. 개발자가 직접 ObjectMapper, SecurityFilterChain, DataSource 같은 Bean을 제공하면 기본 설정 일부가 물러날 수 있다. 이 조건은 타입, 이름, annotation, search strategy에 따라 결과가 달라질 수 있으므로 “같은 역할”이 정확히 무엇인지 자동 설정 코드를 봐야 한다.

@ConditionalOnProperty는 property 값에 따라 기능을 켜고 끈다. 관리 포트, actuator endpoint, cache provider, scheduling 같은 기능에서 자주 보인다.

@ConditionalOnWebApplication은 웹 애플리케이션 종류를 기준으로 적용 여부를 결정한다. Servlet과 reactive 환경은 서로 다른 자동 설정이 필요하다.

Back-off 설계

Back-off는 Boot 자동 설정의 예의다. 사용자가 명시적으로 등록한 Bean이 있으면 Boot는 “개발자가 의도를 표현했다”고 보고 기본 Bean 등록을 멈춘다.

@Configuration
public class JacksonConfig {
 
    @Bean
    public ObjectMapper objectMapper() {
        return JsonMapper.builder()
                .findAndAddModules()
                .propertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
                .build();
    }
}

이런 Bean을 등록하면 Jackson 자동 설정의 기본 ObjectMapper가 대체될 수 있다. 문제는 이 Bean 하나가 Boot가 제공하던 세부 커스터마이저 적용 흐름까지 바꿀 수 있다는 점이다. 그래서 직접 Bean을 만들기 전에 Customizer, builder customizer, property로 충분한지 먼저 확인한다.

조정 순서

자동 설정이 마음에 들지 않을 때는 다음 순서로 본다. 먼저 property로 바꿀 수 있는지 확인한다. 그 다음 Boot가 제공하는 customizer나 configurer를 찾는다. 그래도 부족하면 사용자가 직접 Bean을 제공해 back-off시킨다. 마지막으로 정말 필요할 때만 자동 설정 exclude를 사용한다.

exclude는 기능 전체를 끄는 강한 도구다. 문제 하나를 고치려고 자동 설정을 통째로 꺼 버리면 나중에 관련 기본 Bean과 설정을 모두 직접 관리해야 할 수 있다.

실전 팁

  • 자동 설정 문제는 조건 이름을 읽으면 절반은 풀린다.
  • 사용자 Bean을 추가하기 전에 그 Bean 타입이 어떤 자동 설정을 back-off시키는지 확인한다.
  • @ConditionalOnMissingBean이 타입 기준인지 이름 기준인지, parent context까지 검색하는지 확인한다.
  • property, customizer, Bean 제공, auto-configuration exclude 순서로 접근한다.
  • 여러 자동 설정이 같은 Bean에 영향을 줄 수 있으므로 conditions report에서 positive/negative match를 함께 본다.
  • 테스트에서 ApplicationContextRunner를 쓰면 자동 설정 조건을 작은 단위로 검증할 수 있다.

위험 신호!

  • exclude로 문제를 해결한 뒤 어떤 기본 Bean을 잃었는지 모른다.
  • @ConditionalOnMissingBean의 대상 타입을 확인하지 않고 사용자 Bean을 추가한다.
  • default Bean을 통째로 대체하면서 Boot가 제공하던 customizer 체인까지 사라지는 것을 모른다.
  • property로 해결 가능한 설정을 코드 Bean으로 덮어쓴다.
  • 자동 설정 조건을 읽지 않고 Stack Overflow 답변만 복사한다.
  • Boot 업그레이드 후 조건 변경을 확인하지 않는다.

확인 질문

확인 질문

  • @ConditionalOnClass는 어떤 조건인가?
    • 특정 클래스가 classpath에 있을 때만 설정을 적용하는 조건이다.
  • Back-off는 왜 중요한가?
    • 사용자가 명시적으로 제공한 Bean을 Boot 기본 설정보다 우선하게 해 커스터마이징을 가능하게 하기 때문이다.
  • 자동 설정 exclude는 언제 쓰는 것이 좋은가?
    • property, customizer, 사용자 Bean 제공으로 해결되지 않고 해당 자동 설정 전체를 끄는 것이 의도일 때 사용한다.

참고 문서