[학습기록] Spring 애플리케이션 설정 관리: (2) @ConditionalOnProperty 사용법과 활용 예제
지난 포스팅에서 설정을 객체로 정의하면 구조와 의도가 코드에 자연스럽게 드러난다는 점은 확인했습니다. 하지만, 한 가지 질문이 남습니다.
@ConfigurationProperties로 선언한 설정 클래스는 언제, 어떻게 Spring Bean(이하, “Bean”)으로 등록되는 걸까요?
이 지점에서 등장하는 것이 @EnableConfigurationProperties 어노테이션입니다.
1. 설정을 활성화하는 방법, @EnableConfigurationProperties
@ConfigurationProperties는 설정값을 객체에 바인딩하는 역할을 합니다. 반면 @EnableConfigurationProperties는 해당 설정 객체를 Bean으로 등록할 수 있도록 합니다.
@Configuration
@EnableConfigurationProperties(ExternalApiProperties.class)
public class ExternalApiConfig {
}
설정 객체가 Bean으로 등록되면 다른 컴포넌트에서 주입받아 사용할 수 있습니다.
@Component
@RequiredArgsConstructor
public class ExternalApiClient {
private final ExternalApiProperties properties;
public void call() {
String url = properties.getUrl(); // https://example.com
int timeout = properties.getTimeout(); // 3000
// ...
}
}
@Component
@RequiredArgsConstructor
public class ExternalApiRetryPolicy {
private final ExternalApiProperties properties;
public int retryCount() {
return properties.getRetry(); // 3
}
}
2. @Component와 @EnableConfigurationProperties의 차이
그렇다면 이런 질문이 자연스럽게 떠오릅니다.
@EnableConfigurationProperties를 사용하지 않고, 그냥@Component를 사용하면 되는 것 아닐까?
실제로 다음과 같이 코드를 작성하는 것도 가능합니다.
@Component
@ConfigurationProperties(prefix = "external.api")
public class ExternalApiProperties {
private String url;
private int timeout;
private int retry;
// getter / setter
}
이렇게 하면 ExternalApiProperties는 컴포넌트 스캔 대상이 되어 자동으로 Spring 컨텍스트에 Bean으로 등록됩니다.
그렇다면 굳이 @EnableConfigurationProperties 어노테이션을 사용할 필요가 있을까요? 두 방식의 차이점을 정리해보면 다음과 같습니다.
| 구분 | @Component | @EnableConfigurationProperties |
|---|---|---|
| 등록 방식 | 자동 컴포넌트 스캔 | 명시적 등록 |
| 용도 | 일반 컴포넌트 | 설정 객체 등록 |
| 라이브러리/모듈화 | 적합하지 않음 | 적합 |
| 구조적 명확성 | 비교적 낮음 | 높음 |
@Component를 사용하는 방식이 분명 빠르고 간편해 보입니다. 하지만, 설정 클래스가 많아질수록 설정 객체와 일반 컴포넌트를 구분하기 어려워질 수 있습니다.
반면 @EnableConfigurationProperties를 사용하면 설정은 “구성 단계에서 활성화되는 요소”라는 인식이 더 분명해질 수 있습니다.
@Component를 사용해도 설정 객체가 Bean으로 등록이 되지만, 설정을 위한 별도의 구성 의도를 드러내지 못할 수 있습니다. 일반적인 애플리케이션이라면 @Component를 사용해도 큰 문제는 없습니다. 하지만 설정의 역할을 명확히 구분하거나 라이브러리 형태로 제공한다면 @EnableConfigurationProperties를 사용하는 것이 더 적합합니다.
3. 설정에 따라 동작을 제어하는 방법, @ConditionalOnProperty
때로는 특정 설정 값에 따라 애플리케이션의 동작을 수행하는 코드를 분기 처리해야 할 필요가 있습니다.
- 특정 기능의 ON/OFF
- 캐시 기능 활성화 여부
- 외부 API 연동 기능 활성화 여부
이때, @ConditionalOnProperty를 사용할 수 있습니다. @ConditionalOnProperty는 특정 설정값의 존재 여부나 값에 따라 Bean 등록 여부를 결정하는 어노테이션입니다.
지금까지 사용한 application.yml 파일에 enabled라는 설정을 추가해보겠습니다.
external:
api:
url: https://example.com
timeout: 3000
retry: 3
enabled: true
아래처럼 @ConditionalOnProperty으로 선언하면 external.api.enabled의 값이 true인 경우에만 ExternalApiClient가 Bean으로 등록됩니다.
@Component
@RequiredArgsConstructor
@ConditionalOnProperty(
prefix = "external.api", // 설정 키의 공통 접두사
name = "enabled", // 확인할 설정 이름
havingValue = "true", // true일 때만 Bean 등록
matchIfMissing = false) // 설정이 없으면 Bean 등록하지 않음
public class ExternalApiClient {
private final ExternalApiProperties properties;
public void call() {
String url = properties.getUrl(); // https://example.com
int timeout = properties.getTimeout(); // 3000
// ...
}
}
반대로 external.api.enabled의 값이 false이거나, 설정이 존재하지 않으면 ExternalApiClient는 Bean으로 등록되지 않습니다. 즉, @ConditionalOnProperty를 사용하면 단순히 설정값을 전달하는 역할을 넘어 애플리케이션의 구성과 기능 활성화 여부까지 제어할 수 있습니다.
4. 마무리
@ConfigurationProperties는 설정을 객체로 관리하기 위한 기능이고, @EnableConfigurationProperties는 설정 객체를 Bean으로 등록하기 위한 기능입니다.
그리고 @ConditionalOnProperty를 함께 사용하면 설정값에 따라 Bean 등록 여부를 제어할 수 있습니다.
이처럼 Spring에서는 설정을 단순한 값이 아니라, 애플리케이션의 구성과 동작을 제어하는 요소로 활용할 수 있습니다.