Spring Boot Auto-configuration 동작 원리 — @SpringBootApplication이 켜는 100개의 스위치
Spring Boot의 가장 큰 매력은 "별것 안 했는데 알아서 동작한다"는 점입니다. 그러나 그 알아서 동작하는 부분에 사고가 생기면, 어디서부터 봐야 할지 막막해집니다. 이 글은
@SpringBootApplication한 줄이 어떻게 수십 개의 자동 설정을 켜고, 그 중 어떤 것이 살아남고 어떤 것이 조용히 사라지는지를 Spring Boot 3.4 기준 내부 코드와 함께 정리합니다. 처음 Spring Boot에 입문한 분, 그리고 Bean이 왜 안 만들어지는지 한참을 헤매 본 분을 대상으로 합니다.
처음 Spring Boot 프로젝트를 만들었을 때, 저는 어리둥절했습니다. pom.xml에 spring-boot-starter-web을 추가했더니 톰캣이 떠 있고, application.yml에 데이터소스 URL을 적었더니 HikariCP 풀이 만들어져 있었습니다. 분명히 어떤 코드도 작성하지 않았는데 말입니다.
@SpringBootApplication 어노테이션 한 줄에 그 모든 것이 들어 있다는 건 알았지만, 정확히 어떤 메커니즘으로 그것들이 켜지는지는 한참 후에야 알게 되었습니다. 그리고 그 시점은 보통 자동 설정이 꺼졌을 때입니다. 분명히 클래스패스에 라이브러리가 있는데도 빈이 안 만들어지거나, 내가 만든 @Configuration을 무시하고 자동 설정이 우선 적용되는 식이죠.
이 글은 그 블랙박스를 풀어 헤치고, 자동 설정이 클래스패스 스캔 → 후보 로딩 → 필터링 → 정렬 → 적용으로 이어지는 5단계를 따라가며 정리합니다.
1. 출발점: @SpringBootApplication이 감추는 세 어노테이션
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
@SpringBootApplication은 사실 세 어노테이션의 합성입니다.
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(...)
public @interface SpringBootApplication { ... }
@SpringBootConfiguration— 그냥@Configuration의 별명. 의미상 "이 클래스가 부트 애플리케이션의 루트 설정"@ComponentScan— 자기 패키지부터 하위 패키지까지@Component계열 빈 등록@EnableAutoConfiguration— 이 글의 주인공. 자동 설정을 켭니다
@EnableAutoConfiguration의 본체
@Target(TYPE)
@Retention(RUNTIME)
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
핵심은 @Import(AutoConfigurationImportSelector.class) 한 줄입니다. **자동 설정이라는 화려한 이름과 달리, 그 본질은 평범한 @Import**입니다. 단지 import할 클래스의 목록을 런타임에 동적으로 결정할 뿐입니다.
@AutoConfigurationPackage는 보너스입니다. @SpringBootApplication이 붙은 클래스가 속한 패키지를 "기본 패키지"로 등록해, 이후 @EntityScan이나 @MapperScan이 생략되어도 동작하게 합니다.
2. AutoConfigurationImportSelector — 마지막에 일하는 선택자
AutoConfigurationImportSelector는 단순한 ImportSelector가 아니라 DeferredImportSelector를 구현합니다.
public class AutoConfigurationImportSelector implements DeferredImportSelector,
BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware,
EnvironmentAware, Ordered {
static final int ORDER = Ordered.LOWEST_PRECEDENCE - 1;
...
}
DeferredImportSelector라는 이름에서 짐작되듯, 이 셀렉터는 다른 모든 @Configuration 처리가 끝난 뒤에야 실행됩니다. 이유는 명확합니다.
@ConditionalOnMissingBean이 동작하려면 사용자가 정의한 빈이 먼저 등록되어 있어야 합니다. 만약 자동 설정이 사용자 설정보다 먼저 적용되면, "사용자가 빈을 정의하지 않았을 때만 우리가 제공한다"는 규칙을 지킬 수 없습니다.
flowchart TD
A["Application start"] --> B["Process @SpringBootApplication"]
B --> C["Process @ComponentScan beans"]
C --> D["Process user @Configuration"]
D --> E["DeferredImportSelector.process()"]
E --> F["AutoConfigurationImportSelector"]
F --> G["Auto-config classes registered LAST"]
G --> H["Conditions evaluated against current bean state"]
이 순서가 "사용자 설정이 자동 설정을 항상 이긴다"는 Spring Boot의 황금률을 만듭니다.
셀렉터의 6단계
AutoConfigurationImportSelector.getAutoConfigurationEntry()가 자동 설정을 결정하는 핵심 메서드입니다. 실제 코드를 보면 6단계로 정리됩니다.
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) return EMPTY_ENTRY;
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
- isEnabled —
spring.boot.enableautoconfiguration=false면 빈 엔트리 반환 - getCandidateConfigurations —
META-INF/spring/...AutoConfiguration.imports에서 후보 로드 - removeDuplicates —
LinkedHashSet으로 중복 제거 (여러 jar에 같은 클래스가 들어 있을 수 있음) - getExclusions / checkExcludedClasses —
exclude속성과spring.autoconfigure.exclude프로퍼티 적용 - filter —
AutoConfigurationImportFilter체인이 클래스패스/빈 조건을 빠르게 걸러 냄 - fireAutoConfigurationImportEvents —
AutoConfigurationImportListener들에게 결과 통지 (대표적으로ConditionEvaluationReport)
각 단계를 차례로 풀어 보겠습니다.
3. 후보 로딩 — AutoConfiguration.imports라는 텍스트 파일
자동 설정의 후보 목록은 어디서 올까요. Spring Boot 3는 ImportCandidates라는 클래스가 책임집니다.
public final class ImportCandidates implements Iterable<String> {
private static final String LOCATION = "META-INF/spring/%s.imports";
private static final String COMMENT_START = "#";
public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
String location = String.format(LOCATION, annotation.getName());
Enumeration<URL> urls = classLoader.getResources(location);
...
}
}
@EnableAutoConfiguration이 사용하는 @AutoConfiguration 어노테이션의 FQN을 파일명에 박아 넣습니다. 결과적으로 모든 jar 안의 다음 경로에 있는 파일이 합쳐집니다.
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
파일 형식은 한 줄에 하나의 클래스 FQN, #로 시작하는 주석 허용. Spring Boot 3.4의 spring-boot-autoconfigure jar 안에는 이런 식으로 백 줄 가까이 들어 있습니다.
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
...
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
spring.factories의 죽음
Spring Boot 2.7 이전에는 META-INF/spring.factories 파일에 다음과 같이 등록했습니다.
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
...
이 방식은 두 가지 문제가 있었습니다.
spring.factories는 다양한SpringFactoriesLoader키가 한 파일에 섞여 있어, 자동 설정만 추리려면 키 매칭이 필요했습니다- 백슬래시 라인 컨티뉴에이션과 콤마 구분으로 파싱이 깨지기 쉬웠습니다 (특히 GraalVM 네이티브 이미지에서 메타데이터 분석 시 부담)
Spring Boot 2.7에서 META-INF/spring/...AutoConfiguration.imports 방식이 도입되고 3.0에서 spring.factories의 자동 설정 키는 완전히 제거되었습니다 (다른 SPI 키는 여전히 spring.factories를 사용).
패키지가 다른 이유
흥미로운 점 하나. AutoConfigurationImportSelector는 org.springframework.boot.autoconfigure 패키지에 있지만, ImportCandidates는 org.springframework.boot.context.annotation에 있습니다.
ImportCandidates는 자동 설정 전용 도구가 아니기 때문입니다. 같은 메커니즘이 @ImportAutoConfiguration (테스트 슬라이스에서 사용), Spring Cloud의 @EnableConfigurationServer 등 다른 어노테이션에서도 재사용됩니다. 어노테이션마다 자신의 FQN이 박힌 .imports 파일을 갖는 구조입니다.
4. 필터 — 클래스패스 단계에서 빠르게 잘라 내기
후보 백 개를 모두 @Configuration으로 파싱한 뒤 @Conditional을 평가하면 시간이 너무 오래 걸립니다. Spring Boot는 그 전에 메타데이터 기반 필터로 명백히 동작 불가능한 후보를 제거합니다.
private static class ConfigurationClassFilter {
private final AutoConfigurationMetadata autoConfigurationMetadata;
private final List<AutoConfigurationImportFilter> filters;
List<String> filter(List<String> configurations) {
String[] candidates = StringUtils.toStringArray(configurations);
for (AutoConfigurationImportFilter filter : this.filters) {
boolean[] match = filter.match(candidates, this.autoConfigurationMetadata);
for (int i = 0; i < match.length; i++) {
if (!match[i]) candidates[i] = null;
}
}
...
}
}
빌드 시점에 만들어지는 메타데이터
AutoConfigurationMetadata는 빌드 시점에 생성된 META-INF/spring-autoconfigure-metadata.properties를 읽습니다. 이 파일에는 각 자동 설정 클래스에 붙은 @ConditionalOnClass 같은 어노테이션의 인자가 키-값 형태로 들어 있습니다.
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration=
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.ConditionalOnClass=\
javax.servlet.Servlet,org.springframework.web.servlet.DispatcherServlet
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.AutoConfigureOrder=...
AutoConfigurationImportFilter의 구현체들은 이 properties 파일만 읽고, 실제 @Configuration 클래스를 로드하지 않고 후보를 솎아 냅니다. 즉 클래스 자체를 메모리에 올리지 않고도 @ConditionalOnClass(Servlet.class) 같은 조건을 사전 평가할 수 있습니다.
세 가지 필터
AutoConfigurationImportSelector는 SpringFactoriesLoader로 AutoConfigurationImportFilter 구현체들을 로드합니다. 표준 구현은 세 개입니다.
- OnClassCondition —
@ConditionalOnClass의 클래스가 클래스패스에 없으면 후보 탈락.Class.forName으로 시도해ClassNotFoundException이면 결정 - OnBeanCondition —
@ConditionalOnBean/@ConditionalOnMissingBean의 일부 케이스를 사전 평가 - OnWebApplicationCondition —
@ConditionalOnWebApplication평가 (Servlet, Reactive, Any)
이 단계에서 떨어진 후보는 이후 @Configuration 파싱 자체가 일어나지 않습니다. 시작 시간을 크게 줄이는 핵심 최적화입니다.
flowchart LR
A["100+ candidates from .imports"] --> B["OnClassCondition filter"]
B --> C["OnBeanCondition filter"]
C --> D["OnWebApplicationCondition filter"]
D --> E["Surviving candidates parsed as @Configuration"]
E --> F["Per-method @Conditional re-evaluated"]
5. 조건 어노테이션 — 살아남은 후보를 다시 검사
필터를 통과한 클래스는 일반 @Configuration처럼 파싱되고, 그 시점에 모든 @Conditional 어노테이션이 다시 평가됩니다. 자주 쓰이는 조건 어노테이션과 그 평가자를 정리하면 다음과 같습니다.
| 어노테이션 | 평가자 | 의미 |
|---|---|---|
@ConditionalOnClass |
OnClassCondition |
지정된 클래스가 클래스패스에 있을 때 |
@ConditionalOnMissingClass |
OnClassCondition |
지정된 클래스가 클래스패스에 없을 때 |
@ConditionalOnBean |
OnBeanCondition |
BeanFactory에 지정된 빈이 이미 등록돼 있을 때 |
@ConditionalOnMissingBean |
OnBeanCondition |
지정된 빈이 등록돼 있지 않을 때 |
@ConditionalOnProperty |
OnPropertyCondition |
프로퍼티가 특정 값과 매칭될 때 |
@ConditionalOnResource |
OnResourceCondition |
클래스패스 리소스가 존재할 때 |
@ConditionalOnWebApplication |
OnWebApplicationCondition |
Web/Reactive/Any 환경일 때 |
@ConditionalOnExpression |
OnExpressionCondition |
SpEL 식이 true일 때 |
전형적인 자동 설정의 형태는 두 조건을 함께 쓰는 것입니다.
@AutoConfiguration
@ConditionalOnClass(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
읽어 보면 의미가 그대로 드러납니다.
- 클래스패스에
javax.sql.DataSource가 있을 때만 (@ConditionalOnClass) - 사용자가
DataSource빈을 직접 등록하지 않았을 때만 (@ConditionalOnMissingBean) - 자동 설정이 기본
DataSource를 만들어 준다
@ConditionalOnMissingBean이 자기 클래스 안의 빈을 못 보는 함정
자주 부딪히는 함정 하나입니다. 같은 @Configuration 클래스 안에서 @Bean 메서드끼리는 @ConditionalOnMissingBean으로 서로를 가리지 못합니다. 메서드 평가 순서가 보장되지 않기 때문입니다 (Spring Boot 이슈 #30508 참조).
해결책은 둘 중 하나입니다. 별도의 @Configuration 클래스로 분리하거나, 빈 정의의 의존 관계를 명시적으로 만들거나.
6. 정렬 — @AutoConfigureBefore/After/Order
후보가 모두 결정된 뒤에는 적용 순서를 정해야 합니다. AutoConfigurationGroup.selectImports()에서 AutoConfigurationSorter.getInPriorityOrder()로 위임됩니다.
세 가지 어노테이션이 정렬을 제어합니다.
@AutoConfigureBefore(X.class)— 이 클래스가 X보다 먼저 적용되도록@AutoConfigureAfter(X.class)— 이 클래스가 X보다 나중에 적용되도록@AutoConfigureOrder(N)— 직접 관계가 없는 자동 설정들 사이의 우선순위 (낮은 값이 먼저)
@AutoConfigureBefore/After는 의존 관계가 명확할 때, @AutoConfigureOrder는 서로 모르는 자동 설정들 사이에서 사용합니다.
주의: 일반 빈에 쓰이는
@Order는 자동 설정 순서에 영향을 주지 않습니다. 자동 설정에는 반드시@AutoConfigureOrder를 써야 합니다.
Spring Boot 2.7 이후의 단축 문법
@AutoConfiguration은 Spring Boot 2.7에 도입되었습니다. 자동 설정 클래스에는 항상 같은 어노테이션 묶음이 붙기 때문에 이를 한곳에 모은 메타 어노테이션입니다.
@Target(TYPE)
@Retention(RUNTIME)
@Documented
@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore
@AutoConfigureAfter
public @interface AutoConfiguration {
@AliasFor(annotation = Configuration.class)
String value() default "";
@AliasFor(annotation = AutoConfigureBefore.class, attribute = "value")
Class<?>[] before() default {};
@AliasFor(annotation = AutoConfigureAfter.class, attribute = "value")
Class<?>[] after() default {};
...
}
세 가지 차이점이 있습니다.
@Configuration(proxyBeanMethods = false)를 강제 — CGLIB 프록시 비용 회피. 자동 설정은 일반적으로@Bean메서드 사이의 직접 호출이 없어야 합니다before/after속성이 어노테이션 본체에 통합 — 별도@AutoConfigureBefore줄을 추가할 필요가 없음- 의도가 명시적 — "이 클래스는 자동 설정이지 일반
@Configuration이 아니다"
권장사항은 @AutoConfiguration을 쓰는 것입니다. @Configuration도 동작은 하지만, 의도를 흐리고 proxyBeanMethods=true로 동작하는 부작용이 있습니다.
7. 진단 — CONDITIONS EVALUATION REPORT
자동 설정이 어떻게 결정되었는지를 보고 싶을 때 가장 쉬운 방법은 --debug 플래그입니다.
java -jar myapp.jar --debug
ConditionEvaluationReportLoggingListener가 ApplicationContextInitializer로 등록되어 있어, 컨텍스트 초기화가 끝나면 다음과 같은 보고서를 DEBUG 레벨로 출력합니다.
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:
-----------------
AopAutoConfiguration matched:
- @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)
- @ConditionalOnClass found required class 'org.aspectj.lang.annotation.Aspect' (OnClassCondition)
DataSourceAutoConfiguration matched:
- @ConditionalOnClass found required class 'javax.sql.DataSource' (OnClassCondition)
Negative matches:
-----------------
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class
'jakarta.jms.ConnectionFactory' (OnClassCondition)
Exclusions:
-----------
None
Unconditional classes:
----------------------
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
세 섹션이 보입니다.
- Positive matches — 적용된 자동 설정과 그 근거
- Negative matches — 후보였지만 조건을 만족하지 못해 탈락한 자동 설정과 사유
- Exclusions —
exclude속성으로 명시적으로 배제된 항목 - Unconditional classes — 조건 없이 항상 적용되는 자동 설정
운영 환경에서 actuator를 사용한다면 /actuator/conditions 엔드포인트로 같은 정보를 JSON으로 받을 수 있습니다.
8. 직접 만드는 starter
자동 설정을 직접 만드는 것은 의외로 단순합니다. 사내 라이브러리에 자동 설정을 넣어 보겠습니다.
자동 설정 클래스
package com.acme.greeting.autoconfigure;
@AutoConfiguration
@ConditionalOnClass(GreetingService.class)
@ConditionalOnProperty(prefix = "acme.greeting", name = "enabled",
havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(GreetingProperties.class)
public class GreetingAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public GreetingService greetingService(GreetingProperties properties) {
return new GreetingService(properties.getMessage());
}
}
프로퍼티 클래스
@ConfigurationProperties(prefix = "acme.greeting")
public class GreetingProperties {
private String message = "Hello";
// getters/setters
}
.imports 파일
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.acme.greeting.autoconfigure.GreetingAutoConfiguration
이 jar를 의존성으로 추가하면 사용자 측에서는 다음만 하면 됩니다.
acme:
greeting:
message: "안녕하세요"
GreetingService 빈이 자동으로 등록되고, 사용자가 @Bean GreetingService를 직접 만들면 자동 설정은 양보합니다 (@ConditionalOnMissingBean 덕분에).
메타데이터 자동 생성
spring-autoconfigure-metadata.properties 파일은 손으로 작성하지 않습니다. org.springframework.boot:spring-boot-autoconfigure-processor를 annotationProcessor 의존성으로 추가하면 컴파일 시점에 자동 생성됩니다.
dependencies {
annotationProcessor("org.springframework.boot:spring-boot-autoconfigure-processor")
}
이 프로세서가 있어야 4단계의 사전 필터가 우리가 만든 자동 설정에도 적용됩니다.
9. 운영 함정 다섯 가지
(1) excludeName vs exclude
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
exclude는 컴파일 의존성을 요구합니다. 자동 설정 클래스가 클래스패스에 있어야 합니다. 사이드카로 들어온 자동 설정처럼 컴파일 시 알 수 없는 경우는 excludeName이나 프로퍼티를 사용해야 합니다.
spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
(2) "있어야 할 자동 설정이 없다"
99%의 경우 두 가지 중 하나입니다.
- 클래스패스에 필요한 라이브러리가 없음 (보통 starter 누락)
- 사용자가 어딘가에서 같은 타입의 빈을 직접 등록함 (
@ConditionalOnMissingBean이 양보)
--debug로 negative matches를 보면 둘 중 어느 쪽인지 즉시 드러납니다.
(3) @TestConfiguration이 자동 설정을 가린다
테스트에서 @TestConfiguration으로 빈을 정의하면 @ConditionalOnMissingBean이 양보합니다. 반대로 자동 설정이 동작해야 하는 경우라면 테스트에서 빈을 직접 등록하면 안 됩니다. 둘이 의도적으로 충돌하는 시나리오를 만들면 디버깅이 어려워집니다.
(4) proxyBeanMethods = false의 함의
@AutoConfiguration은 항상 proxyBeanMethods = false입니다. 같은 @Configuration 안에서 @Bean 메서드를 직접 호출해서 빈 인스턴스를 가져오는 패턴은 동작하지 않습니다.
@AutoConfiguration
public class MyAutoConfiguration {
@Bean
public A a() { return new A(); }
@Bean
public B b() {
return new B(a()); // CGLIB 프록시 없음 → 새 A 인스턴스 생성됨
}
}
해결: b(A a)로 파라미터 주입을 받습니다. 이것이 권장 패턴입니다.
(5) @AutoConfigureBefore/After는 빈 생성 순서가 아니다
@AutoConfiguration
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MyAutoConfiguration { ... }
이 어노테이션은 자동 설정 클래스가 파싱되는 순서만 결정합니다. 실제 빈이 만들어지는 순서는 의존성 그래프와 @DependsOn이 결정합니다. 빈 생성 순서가 중요하다면 @DependsOn을 추가로 사용해야 합니다.
10. 정리
@SpringBootApplication 한 줄에서 시작해 자동 설정이 적용되기까지 거치는 길은 다음과 같습니다.
flowchart TD
A["@SpringBootApplication"] --> B["@EnableAutoConfiguration"]
B --> C["@Import(AutoConfigurationImportSelector.class)"]
C --> D["DeferredImportSelector deferred until last"]
D --> E["ImportCandidates.load()"]
E --> F["META-INF/spring/...AutoConfiguration.imports"]
F --> G["AutoConfigurationImportFilter chain"]
G --> H["OnClassCondition / OnBeanCondition / OnWebApplicationCondition"]
H --> I["Surviving candidates parsed as @Configuration"]
I --> J["@AutoConfigureBefore/After/Order sorting"]
J --> K["Per-method @Conditional re-evaluation"]
K --> L["Beans registered into BeanFactory"]
이 흐름을 머리에 넣어 두면 두 가지 능력이 생깁니다.
- 사라진 자동 설정의 원인 추적 —
--debug의 negative matches를 어디부터 읽을지가 명확해집니다 - 자체 starter 설계 — 어떤 조건으로, 어떤 순서로 적용될지를 의도대로 설계할 수 있습니다
처음에는 마법처럼 보이는 자동 설정도, 결국 텍스트 파일 한 줄 한 줄을 읽고 클래스패스를 한 클래스씩 확인하는 차분한 절차의 합입니다. 마법은 없습니다. 잘 설계된 컨벤션과, 그 컨벤션을 충실히 실행하는 백 줄짜리 셀렉터 한 개가 있을 뿐입니다.
참고자료
- Spring Boot 공식 문서 — Auto-configuration: https://docs.spring.io/spring-boot/reference/using/auto-configuration.html
- Spring Boot 공식 문서 — Creating Your Own Auto-configuration: https://docs.spring.io/spring-boot/reference/features/developing-auto-configuration.html
AutoConfigurationImportSelector소스: https://github.com/spring-projects/spring-boot/blob/v3.4.0/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.javaImportCandidates소스: https://github.com/spring-projects/spring-boot/blob/v3.4.0/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/annotation/ImportCandidates.java@AutoConfiguration소스: https://github.com/spring-projects/spring-boot/blob/v3.4.0/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfiguration.java@EnableAutoConfiguration소스: https://github.com/spring-projects/spring-boot/blob/v3.4.0/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfiguration.javaMETA-INF/spring/...AutoConfiguration.imports(Spring Boot v3.3.5): https://github.com/spring-projects/spring-boot/blob/v3.3.5/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsConditionEvaluationReportLoggingListenerJavadoc: https://docs.spring.io/spring-boot/api/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingListener.htmlConditionEvaluationReportJavadoc: https://docs.spring.io/spring-boot/api/java/org/springframework/boot/autoconfigure/condition/ConditionEvaluationReport.html- spring.factories → AutoConfiguration.imports 마이그레이션 (Spring Boot 2.7 release notes): https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes
- 같은
@Configuration안의@ConditionalOnMissingBean함정: https://github.com/spring-projects/spring-boot/issues/30508

