이 글에서 얻는 것
- Spring Boot “자동 설정”이 정확히 무엇인지(어디서/어떤 조건으로/왜 등록되는지) 설명할 수 있습니다.
- “내가 만든 빈이 왜 안 먹지?”, “왜 갑자기 Security가 켜졌지?” 같은 문제를 조건 리포트로 디버깅할 수 있습니다.
- 자동 설정을 끄기(exclude)보다 확장/오버라이드로 안전하게 커스터마이징하는 방법을 익힙니다.
0) 자동 설정(Auto-Configuration)은 한 문장으로
Spring Boot는 클래스패스(의존성)와 설정 프로퍼티를 보고,
필요한 @Configuration들을 자동으로 import 해서 “기본 동작”을 만들어줍니다.
중요한 포인트는 “자동 설정은 마법”이 아니라 그냥 조건부로 등록되는 설정 클래스 집합이라는 점입니다.
1) 동작 흐름(큰 그림) - The Magic Revealed
@SpringBootApplication은 단순한 어노테이션이 아닙니다. 거대한 자동화 시스템의 트리거입니다.
sequenceDiagram
autonumber
participant App as @SpringBootApplication
participant Selector as AutoConfigurationImportSelector
participant Factories as spring.factories / imports
participant Context as Spring Context
App->>Selector: 1. Trigger @EnableAutoConfiguration
activate Selector
Selector->>Factories: 2. Load Candidate Configurations
Factories-->>Selector: List[SecurityAutoConfig, JdbcAutoConfig, ...]
loop Filter Candidates
Selector->>Selector: 3. Check @ConditionalOnClass (Is Library Present?)
Selector->>Selector: 4. Check @ConditionalOnProperty
end
Selector-->>Context: 5. Return Valid Configurations
deactivate Selector
Context->>Context: 6. Register Beans (Only if @ConditionalOnMissingBean satisfies)
1-1) AutoConfigurationImportSelector의 역할
이 클래스가 바로 “마법사"입니다.
- Candidates Loading:
spring.factories(Boot 2.x) 또는.imports(Boot 3.x) 파일에서 후보군을 싹 긁어옵니다. - Filtering: 현재 클래스패스에 없는 라이브러리 설정은 칼같이 제외합니다. (예:
H2라이브러리가 없으면H2ConsoleAutoConfiguration탈락)
2) 조건부 등록의 핵심: @Conditional*
자동 설정은 무턱대고 켜지지 않습니다. 엄격한 심사를 거칩니다.
flowchart TD
Start["AutoConfiguration Candidate"] --> ClassCheck{"@ConditionalOnClass?"}
ClassCheck -- "No (Lib Missing)" --> Ignore[Ignored]
ClassCheck -- Yes --> PropertyCheck{"@ConditionalOnProperty?"}
PropertyCheck -- "enabled=false" --> Ignore
PropertyCheck -- "enabled=true / Missing" --> BeanCheck{"@ConditionalOnMissingBean?"}
BeanCheck -- "User Defined Bean Exists" --> Backoff["Backoff (User's Win)"]
BeanCheck -- "No Bean" --> Register["Register AutoConfig Bean"]
style Register fill:#c8e6c9,stroke:#388e3c
style Backoff fill:#ffccbc,stroke:#d84315
style Ignore fill:#f5f5f5,stroke:#9e9e9e
- @ConditionalOnClass: “라이브러리(Jar) 넣었니?” (가장 먼저 체크)
- @ConditionalOnProperty: “
application.yml에서 껐니?” - @ConditionalOnMissingBean: “사용자가 직접 같은 빈을 만들었니?” (가장 나중에 체크 - 오버라이딩의 핵심)
3) “내가 만든 설정이 왜 안 먹지?” 디버깅 루틴
추측(Guess)하지 말고 증거(Report)를 보세요.
flowchart TD
Issue["Problem: My Bean is Not Working / Missing"] --> Check1{"Did you check --debug report?"}
Check1 -- No --> Action1["Run with --debug"]
Check1 -- Yes --> Check2{"Is AutoConfig Matched?"}
Check2 -- "No (Negative Matches)" --> Reason1["Check @ConditionalOnClass\n(Dependency Missing?)"]
Check2 -- "Yes (Positive Matches)" --> Check3{"Is overridden by User Bean?"}
Check3 -- Yes --> Fix1["Check @ConditionalOnMissingBean in AutoConfig"]
Check3 -- No --> Fix2["Check @Primary or Bean Name Conflicts"]
style Action1 fill:#fff9c4,stroke:#fbc02d
3-1) ConditionEvaluationReport 읽는 법 (--debug)
실행 옵션에 --debug를 주면 어떤 자동 설정이 “왜 켜졌고/왜 꺼졌는지”가 출력됩니다. **“Positive Matches”**와 **“Negative Matches”**만 찾으세요.
3-2) Actuator의 conditions/beans 활용
운영/로컬에서 원인 추적이 필요하면:
/actuator/conditions: 조건 평가 결과/actuator/beans: 빈 목록과 의존성
(노출은 반드시 인증/내부망 등으로 제한해야 합니다.)
4) 커스터마이징의 우선순위: exclude는 마지막 카드
4-1) 1순위: 프로퍼티로 동작을 조정
자동 설정은 보통 “기본값”을 제공하고, 프로퍼티로 동작을 바꿀 수 있게 설계되어 있습니다.
예:
- DataSource, Jackson, Logging, Management(Actuator) 등은 프로퍼티로 조정 가능한 범위가 큽니다.
4-2) 2순위: 빈 오버라이드(같은 타입 빈 등록)
자동 설정이 @ConditionalOnMissingBean으로 기본 빈을 제공하는 경우,
같은 타입 빈을 직접 등록하면 “내 빈이 우선”이 됩니다.
@Configuration
public class MyConfig {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper().findAndRegisterModules();
}
}
4-3) 3순위: 확장 포인트를 사용(커스터마이저/빌더)
부트는 아예 확장용 타입을 제공하는 경우가 많습니다.
WebMvcConfigurer,Jackson2ObjectMapperBuilderCustomizer같은 커스터마이저- Converter/Formatter 등록 등
4-4) 마지막: exclude
자동 설정 제외는 빠르지만 부작용이 큽니다. 다른 자동 설정이 연쇄적으로 기대하는 빈이 사라질 수 있습니다.
정말 필요할 때만 사용합니다.
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
또는:
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
public class App {}
5) 실무에서 자주 겪는 함정
- 의존성(starter)을 추가했더니 기능이 “자동으로 켜짐” →
@ConditionalOnClass가 원인인 경우가 많음 - 같은 타입 빈이 여러 개라서 주입이 모호함 →
@Primary/@Qualifier로 의도를 명확히 - exclude로 급하게 껐는데 다른 설정이 깨짐 → 우선 프로퍼티/오버라이드/확장으로 해결 가능한지 확인
연습(추천)
spring-boot-starter-security를 추가했을 때 어떤 자동 설정이 켜지는지--debug로 확인해보기- ObjectMapper를 커스터마이징하고, 자동 설정 기본값과 무엇이 달라졌는지 비교해보기
- “의도치 않은 빈 생성”을 일부러 만들어보고(
/actuator/beans,/actuator/conditions), 원인을 추적해보기
💬 댓글