@Value를 여기저기 흩뿌리다가 설정값 관리가 엉망이 된 이유
문제 발생
외부 API 연동 설정(URL, 타임아웃, 재시도 횟수 등 5~6개 값)을 여러 클래스에 @Value("${external.api.xxx}")로 나눠서 주입하고 있었는데, 설정 키 이름에 오타가 나도 애플리케이션이 시작될 때까지 알아챌 방법이 없었고, 어떤 설정값들이 서로 관련 있는지도 코드만 봐서는 파악하기 어려웠습니다.
@Value("${external.api.url}")
private String apiUrl;
@Value("${external.api.timeoutMs}")
private int timeoutMs;원인 분석
@Value는 설정값 하나를 개별 필드에 주입하는 가장 단순한 방법이지만, 몇 가지 근본적인 한계가 있습니다.
- 타입 안전성이 약합니다 — 키 이름은 문자열이라 오타가 나도 컴파일 시점에 잡히지 않고, 실제로 그 설정을 쓰는 코드가 실행될 때(또는 최악의 경우 값이 필요한 조건 분기에 도달할 때)까지 발견되지 않을 수 있습니다.
- 검증이 없습니다 — 타임아웃 값이 음수면 안 된다든지 하는 제약을 표현할 표준적인 방법이 없습니다.
- 관련 설정이 흩어집니다 —
external.api.*설정 5~6개가 서로 다른 클래스의 서로 다른 필드에 나뉘어 있으면, "이 설정 묶음 전체"를 한눈에 보거나 테스트에서 통째로 교체하기가 번거롭습니다.
해결 방안
**@ConfigurationProperties**로 관련된 설정을 하나의 타입 안전한 클래스로 묶습니다.
@ConfigurationProperties(prefix = "external.api")
public record ExternalApiProperties(
String url,
int timeoutMs,
int maxRetries
) {}@Configuration
@EnableConfigurationProperties(ExternalApiProperties.class)
public class ExternalApiConfig {
// 이제 ExternalApiProperties를 빈으로 주입받아 씀
}record(Java 16+)와 조합하면 불변이면서도 간결한 설정 클래스를 만들 수 있습니다 — Spring Boot 3.x부터 record 기반@ConfigurationProperties를 공식 지원합니다.- Bean Validation 애너테이션(
@NotBlank,@Min등)을 필드에 붙이고@Validated를 함께 쓰면, 애플리케이션 시작 시점에 설정값이 검증되어 잘못된 설정으로 배포되는 것을 훨씬 일찍 잡아낼 수 있습니다 — 런타임에 그 설정을 실제로 쓰는 순간까지 기다릴 필요가 없습니다. - 관련된 설정이 하나뿐이고 앞으로도 늘어날 가능성이 낮다면
@Value로도 충분합니다 — 모든 설정을 무조건@ConfigurationProperties로 바꾸라는 뜻은 아니고, "묶여서 의미를 갖는 설정 그룹"이 기준입니다. - IDE(IntelliJ 등)는
@ConfigurationProperties클래스에 대해application.yml자동완성과 타입 검사를 지원합니다 —@Value의 문자열 키에는 이런 지원이 훨씬 제한적입니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.