Spring Boot 자동 설정은 classpath, Bean 존재 여부, property 값을 보고 필요한 Bean을 조건부로 등록한다.
Starter는 관련 의존성을 한 번에 모아 자동 설정이 동작할 수 있는 환경을 만들어 준다.
자동 설정은 개발자가 설정을 하지 않아도 되게 만드는 기능이 아니라, 합리적인 기본값 위에서 필요한 부분만 명시적으로 바꾸게 하는 구조다.
핵심 정리
Spring Boot는 @SpringBootApplication 안의 @EnableAutoConfiguration을 통해 자동 설정 후보를 불러온다.
자동 설정 클래스는 보통 @AutoConfiguration과 여러 @Conditional 조건을 가진다.
Boot 3 계열의 자동 설정 후보는 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports에 나열된다. 예전 spring.factories 방식만 기억하면 최신 자동 설정 구조를 놓치기 쉽다.
spring-boot-starter-web, spring-boot-starter-data-jpa, spring-boot-starter-security 같은 Starter는 기능 자체가 아니라 기능에 필요한 의존성 묶음이다.
자동 설정은 “classpath에 이 라이브러리가 있고, 사용자가 직접 Bean을 만들지 않았고, 관련 설정이 켜져 있다면 기본 Bean을 등록한다”는 식으로 작동한다.
Boot의 좋은 사용법은 자동 설정을 맹신하는 것이 아니라 어떤 조건 때문에 Bean이 생겼는지 추적할 수 있는 상태로 쓰는 것이다.
헷갈리는 지점
Starter가 Bean을 직접 만드는 것으로 오해하기 쉽다. Starter를 추가하면 기능이 바로 생기기 때문이다.
핵심은 Starter는 의존성 묶음이고 Bean 등록은 자동 설정 클래스가 담당한다는 점이다.
의존성이 classpath에 올라오면 조건부 자동 설정이 활성화될 수 있다.
자동 설정을 쓰면 설정을 몰라도 된다고 생각하기 쉽다. 초기에 코드가 거의 없어도 앱이 실행되기 때문이다.
핵심은 기본값은 출발점이고 운영 설정은 이해가 필요하다는 점이다.
문제가 생기면 어떤 자동 설정이 왜 적용됐는지 읽을 수 있어야 한다.
Boot가 모든 Bean을 임의로 만든다고 느끼기 쉽다. 눈에 보이는 설정 코드가 적기 때문이다.
핵심은 조건과 back-off 규칙이 있다는 점이다.
사용자가 직접 Bean을 제공하면 자동 설정이 물러나는 경우가 많다.
자동 설정도 component scan으로 찾아진다고 생각하기 쉽다. 설정 클래스니까 scan 대상처럼 보이기 때문이다.
핵심은 자동 설정 클래스가 import 후보 목록을 통해 로딩된다는 점이다.
자동 설정 클래스를 일반 component scan 대상으로 두면 조건부 설정의 의도가 흐려진다.
확인 질문
Starter의 역할은 무엇인가?
특정 기능에 필요한 의존성들을 편리하게 묶어 제공하는 것이다.
자동 설정은 무엇을 기준으로 Bean 등록 여부를 결정하는가?
classpath, 기존 Bean 존재 여부, property, 웹 애플리케이션 여부 같은 조건을 기준으로 결정한다.
자동 설정을 제대로 쓰려면 무엇을 추적할 수 있어야 하는가?
어떤 자동 설정이 어떤 조건 때문에 적용되었거나 제외되었는지 추적할 수 있어야 한다.
Conditional과 Back-off
3줄 요약
@ConditionalOnClass, @ConditionalOnMissingBean, @ConditionalOnProperty는 자동 설정의 핵심 판단 조건이다.
Back-off는 사용자가 직접 Bean을 등록하면 Boot의 기본 Bean 등록이 물러나는 규칙이다.
자동 설정을 커스터마이징할 때는 전체 자동 설정을 끄기보다 필요한 Bean이나 property만 바꾸는 것이 우선이다.
핵심 정리
@ConditionalOnClass는 특정 클래스가 classpath에 있을 때만 설정을 적용한다.
@ConditionalOnMissingBean은 같은 타입의 Bean이 없을 때 기본 Bean을 등록하게 해 사용자의 명시적 설정을 존중한다.
@ConditionalOnMissingBean은 Bean 정의가 이미 등록된 뒤 평가되는 자동 설정에서 특히 의미가 있다. 사용자 Bean의 타입, 이름, 검색 범위를 확인해야 back-off가 의도대로 동작한다.
@ConditionalOnProperty는 설정 값에 따라 기능을 켜고 끈다.
Back-off 덕분에 개발자는 기본 자동 설정을 사용하다가 필요한 Bean만 직접 제공해 대체할 수 있다.
자동 설정 제외는 강한 조치다. 특정 기능 전체를 빼야 할 때만 쓰고, 우선은 property와 Bean override 지점을 찾는다.
헷갈리는 지점
자동 설정을 바꾸려면 exclude부터 해야 한다고 생각하기 쉽다. 자동으로 만들어진 Bean을 끄고 싶기 때문이다.
핵심은 Boot 자동 설정이 사용자 Bean을 존중하도록 설계되어 있다는 점이다.
먼저 직접 Bean 제공이나 property 변경으로 해결되는지 확인한다.
@ConditionalOnMissingBean이 항상 안전하다고 생각하기 쉽다. 없는 경우에만 만든다는 말이 부드럽게 들리기 때문이다.
핵심은 Bean 타입과 이름, 검색 범위에 따라 예상과 다르게 조건이 맞을 수 있다는 점이다.
커스터마이징 Bean을 만들 때 타입이 자동 설정 조건과 일치하는지 확인해야 한다.
property만 바꾸면 모든 하위 동작이 바뀐다고 보기 쉽다. 설정 파일이 중앙화되어 있기 때문이다.
핵심은 property가 자동 설정이 제공한 조절 지점에만 영향을 준다는 점이다.
더 깊은 제어가 필요하면 Bean 교체나 configurer를 사용해야 한다.
확인 질문
Back-off란 무엇인가?
사용자가 직접 Bean을 등록했을 때 Boot의 기본 자동 설정 Bean 등록이 물러나는 동작이다.
@ConditionalOnMissingBean은 어떤 의도를 가진 조건인가?
사용자가 같은 역할의 Bean을 직접 제공하지 않았을 때만 기본 Bean을 등록하려는 의도다.
자동 설정이 마음에 들지 않을 때 가장 먼저 볼 것은 무엇인가?
property 조절 지점과 사용자가 직접 제공할 수 있는 Bean back-off 지점이다.
Externalized Configuration과 Profile
3줄 요약
Externalized Configuration은 코드 밖의 property, YAML, 환경 변수, command line 인자로 설정을 주입하는 방식이다.
@ConfigurationProperties는 관련 설정을 타입 안전한 객체로 묶어 Bean에 주입하게 한다.
Profile은 환경별 Bean과 설정을 나눌 수 있지만, 과도하게 쓰면 실제 운영 구성이 보이지 않게 된다.
핵심 정리
Boot는 다양한 설정 소스를 정해진 우선순위로 읽어 Environment에 합친다.
@Value는 단일 값을 빠르게 주입할 때 편하지만, 관련 설정 묶음에는 @ConfigurationProperties가 더 유지보수에 좋다.
@ConfigurationProperties는 prefix 단위로 설정을 객체에 바인딩하고 validation과 metadata 지원을 받을 수 있다.
Profile은 local, test, prod처럼 환경별 차이를 표현하지만, 비즈니스 기능 토글까지 Profile로 처리하면 배포와 운영이 복잡해진다.
설정은 비밀값, 환경별 값, 코드 기본값, 운영 튜닝 값을 구분해 관리해야 한다.
헷갈리는 지점
@Value가 간단하니 모든 설정에 쓰면 된다고 생각하기 쉽다. 한 줄로 값을 가져오기 때문이다.
핵심은 관련 설정은 객체로 묶어야 변경과 검증이 쉽다는 점이다.
여러 필드가 함께 의미를 가지면 @ConfigurationProperties를 먼저 검토한다.
Profile을 많이 나누면 안전하다고 느끼기 쉽다. 환경마다 설정을 분리할 수 있기 때문이다.
핵심은 Profile이 늘수록 조합과 실제 적용 값을 추적하기 어려워진다는 점이다.
환경 차이는 최소화하고, 민감값과 배포 환경 값은 외부 주입으로 관리한다.
설정 파일에 값이 있으면 그 값이 반드시 적용된다고 생각하기 쉽다. 파일에 명시되어 있으므로 확실해 보이기 때문이다.
핵심은 설정 소스 우선순위가 있다는 점이다.
환경 변수나 command line 인자가 파일 값을 덮어쓸 수 있다.
확인 질문
@ConfigurationProperties가 @Value보다 적합한 경우는 언제인가?
여러 설정 값이 하나의 의미 있는 묶음을 이루고 타입 안전성과 검증이 필요할 때다.
Profile의 위험은 무엇인가?
환경별 차이가 과도하게 숨겨져 실제 적용 구성을 추적하기 어려워질 수 있다.
Boot 설정 값이 충돌할 때 무엇을 확인해야 하는가?
설정 소스의 우선순위와 실제 Environment에 들어간 값을 확인해야 한다.
Actuator Conditions 진단
3줄 요약
자동 설정 문제는 “왜 이 Bean이 생겼는가”와 “왜 이 Bean이 생기지 않았는가”를 보는 문제다.
Actuator의 conditions report와 startup 로그는 자동 설정 조건 매칭 결과를 보여 준다.
Boot 문제 해결은 Bean 이름을 감으로 찾는 것이 아니라 조건, classpath, property, back-off를 순서대로 확인하는 방식이어야 한다.
핵심 정리
--debug로 애플리케이션을 실행하면 자동 설정 조건 평가 리포트를 로그로 볼 수 있다.
Actuator의 conditions endpoint는 어떤 자동 설정이 positive match, negative match가 되었는지 보여 준다.
자동 설정 문제를 볼 때는 먼저 관련 Starter와 classpath가 있는지 확인한다.
그 다음 property가 조건을 켜거나 끄는지, 사용자가 제공한 Bean 때문에 back-off가 일어났는지 확인한다.
진단 결과를 읽을 수 있으면 Boot는 덜 마법 같고 더 예측 가능한 프레임워크가 된다.
헷갈리는 지점
Bean이 없으면 Component Scan 문제라고 바로 생각하기 쉽다. Spring에서 Bean이 안 보일 때 가장 익숙한 원인이기 때문이다.
핵심은 자동 설정 Bean은 component scan이 아니라 조건부 설정으로 생긴다는 점이다.
자동 설정 후보와 조건 평가 결과를 먼저 확인해야 한다.
conditions report를 너무 복잡해서 무시하기 쉽다. 출력이 길고 내부 클래스명이 많기 때문이다.
핵심은 관련 자동 설정 이름과 negative match 이유만 좁혀 읽는 것이다.
전체를 읽는 것이 아니라 문제 기능의 자동 설정을 검색한다.
자동 설정이 적용되지 않으면 버그라고 느끼기 쉽다. 기대한 기본 Bean이 없기 때문이다.
핵심은 조건이 맞지 않았거나 사용자가 제공한 Bean 때문에 물러났을 수 있다는 점이다.
classpath, property, Bean 존재 여부를 순서대로 확인한다.
확인 질문
자동 설정 적용 여부를 확인하는 대표 방법은 무엇인가?
debug conditions report나 Actuator conditions endpoint를 확인하는 것이다.
자동 설정 Bean이 생기지 않을 때 확인할 세 가지는 무엇인가?
관련 classpath, property 조건, 기존 Bean 때문에 back-off가 일어났는지 확인한다.