본문으로 건너뛰기
안동민 개발노트 아이콘

안동민 개발노트

본문 시작
1장 : Spring Boot 소개와 실행 기반

자동 설정과 조건 보고서 읽기

Boot의 자동 설정은 무조건 많은 Bean을 등록하는 기능이 아닙니다. 특정 클래스가 클래스패스에 있는지, 사용자가 어떤 설정 값을 선택했는지, 같은 역할의 Bean을 직접 제공했는지를 조건으로 확인한 뒤 필요한 구성만 적용합니다.

이 원리를 알면 자동 설정이 편리함을 주면서도 사용자 설정을 덮어쓰지 않는 이유를 이해할 수 있습니다. 예상한 Bean이 없을 때는 추측 대신 Condition Evaluation Report에서 어떤 조건이 맞지 않았는지 확인합니다.


자동 설정은 추측이 아니라 조건의 결과다

클래스패스는 애플리케이션이 사용할 수 있는 기능의 후보를 만듭니다. 설정 값은 그 후보 중 사용자가 원하는 동작을 좁히고, 조건 판정은 기존 Bean과 웹 애플리케이션 종류 같은 현재 컨텍스트까지 종합해 실제 등록 여부를 결정합니다.

특히 @ConditionalOnMissingBean은 사용자가 같은 타입의 Bean을 직접 만들면 기본 구성이 물러나는 back-off 규칙입니다. 자동 설정을 통제하려고 무조건 제외하기 전에, 먼저 원하는 Bean을 명시적으로 제공해서 교체할 수 있는지 살펴봅니다.


조건이 있는 Bean을 직접 구성한다

아래 구성은 애플리케이션 전역의 시간 기준을 Clock Bean으로 제공합니다. 운영에서는 UTC 시스템 시계를 쓰되, 테스트나 별도 환경이 다른 Clock을 등록하면 기본 Bean은 생성되지 않습니다.

src/main/java/com/andongmin/studylog/TimeConfiguration.java
package com.andongmin.studylog;

import java.time.Clock;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class TimeConfiguration {
    @Bean
    @ConditionalOnMissingBean
    Clock systemClock() {
        return Clock.systemUTC();
    }
}
src/main/java/com/andongmin/studylog/ClockReporter.java
package com.andongmin.studylog;

import java.time.Clock;
import java.time.Instant;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class ClockReporter implements ApplicationRunner {
    private final Clock clock;

    public ClockReporter(Clock clock) {
        this.clock = clock;
    }

    @Override
    public void run(ApplicationArguments args) {
        System.out.println("clock=" + Instant.now(clock));
    }
}

ApplicationRunner는 컨텍스트가 준비된 뒤 한 번 호출되므로 시작 시 실제 주입된 시계를 관찰하기 좋습니다. Instant.now()를 코드 곳곳에서 직접 호출하는 대신 Clock을 주입하면 시간도 교체 가능한 의존성이 되고, 테스트에서 고정된 시각을 사용할 수 있습니다.

debug 보고서에서 일치와 불일치를 찾는다

--debug는 조건 보고서를 시작 로그에 출력합니다. Positive matches에는 활성화된 조건이, Negative matches에는 적용되지 않은 조건과 이유가 나타납니다. 클래스 이름만 검색하지 말고 어떤 하위 조건이 맞거나 어긋났는지까지 읽습니다.

./mvnw -q spring-boot:run -Dspring-boot.run.arguments=--debug
Condition 확인 결과
CONDITIONS EVALUATION REPORT에서 TimeConfiguration의 조건 일치와 clock 로그를 확인해야 합니다.

직접 만든 다른 Clock Bean을 잠시 추가하고 다시 실행하면 @ConditionalOnMissingBean의 결과가 달라집니다. 이 작은 실험은 자동 설정을 외워서 사용하는 것과 조건을 근거로 설명하는 것의 차이를 보여 줍니다.


다음 절에서는 코드 구조를 바꾸지 않고 환경별 값을 교체하는 외부 설정 규칙을 다룹니다.