Contents
see List설정값을 코드 밖으로 꺼내도 안전하지 않은 이유
Spring Boot 서비스는 데이터베이스 주소, 외부 API 시간 제한, 파일 저장 경로, 기능 플래그처럼 실행 환경마다 달라지는 값을 설정으로 관리한다. 문제는 설정 파일에 값이 있다고 해서 그 값이 항상 유효한 것은 아니라는 점이다. 운영 환경에서 URL이 누락되거나 타임아웃이 0으로 들어가면, 애플리케이션은 기동에는 성공한 뒤 실제 요청에서 늦게 실패할 수 있다. 환경 변수 이름이 잘못되거나 배포 도구가 빈 문자열을 주입하는 경우도 같은 유형의 장애를 만든다.
이를 줄이려면 관련 값을 한 곳에 묶고, 애플리케이션 시작 시점에 타입과 범위를 검증해야 한다. Spring Boot에서는 분산된 @Value 주입보다 @ConfigurationProperties와 Bean Validation 조합이 유지보수에 적합하다. 접두사 아래의 값을 하나의 불변 설정 객체로 만들면 코드에서 어떤 설정이 필요한지 확인하기 쉽고, 테스트에서도 원하는 설정만 교체할 수 있다.
설정 클래스를 도메인 단위로 묶기
예를 들어 외부 결제 API를 호출하는 서비스라면 URL, 연결 시간 제한, 읽기 시간 제한, 재시도 횟수를 payment.client 아래에 모은다. Java record를 쓰면 생성 후 값이 바뀌지 않아 요청 처리 중 설정이 달라질 위험도 없다. @Validated를 함께 지정하면 서비스 빈이 만들어지기 전에 잘못된 값으로 실행을 중단할 수 있다.
package com.example.payment;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.net.URI;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
@Validated
@ConfigurationProperties(prefix = "payment.client")
public record PaymentClientProperties(
@NotNull URI baseUrl,
@Min(100) @Max(10_000) int connectTimeoutMs,
@Min(100) @Max(30_000) int readTimeoutMs,
@Min(0) @Max(5) int maxRetries,
@NotBlank String apiVersion
) {}URI처럼 형식이 있는 값은 String보다 해당 타입으로 받는 편이 낫다. 잘못된 주소가 들어오면 서비스 호출 코드까지 가지 않고 바인딩 단계에서 실패한다. 시간 제한은 최소값과 최대값을 둬서 0, 음수, 비현실적으로 큰 숫자를 차단한다. 비밀번호나 API 키처럼 민감한 값은 이 객체에 넣을 수 있지만, 로그나 예외 메시지로 객체 전체를 출력하지 않도록 주의해야 한다.
YAML과 환경 변수를 같은 규칙으로 운영하기
기본값은 application.yml에 두고, 운영별 차이는 환경 변수 또는 별도 프로필 파일로 오버라이드한다. 값의 출처가 많아질수록 우선순위가 혼란스러워지므로, 동일한 키를 여러 파일에 중복해 정의하지 않는 것이 좋다. 특히 컨테이너 환경에서는 환경 변수 PAYMENT_CLIENT_BASE_URL처럼 점 표기 키가 대문자 밑줄 형식으로 매핑된다. 배포 매니페스트에서 이 이름을 정확히 사용해야 한다.
payment:
client:
base-url: https://api.example.com
connect-timeout-ms: 1000
read-timeout-ms: 3000
max-retries: 2
api-version: v1
spring:
config:
activate:
on-profile: prod운영 API 주소나 키를 application-prod.yml에 직접 커밋하지 않는다. 주소처럼 공개돼도 되는 값은 환경별 구성으로 관리하고, 비밀값은 배포 플랫폼의 시크릿 저장소나 환경 변수 주입 기능을 이용한다. 개발 환경에서만 필요한 기본값도 운영 프로필로 넘어가면 위험할 수 있으므로, 운영 환경에서 필수인 값은 빈 값 허용 없이 검증 규칙을 적용한다.
설정 바인딩을 명시적으로 활성화하기
Spring Boot 애플리케이션에서는 @ConfigurationPropertiesScan을 사용하거나, 특정 설정 클래스를 @EnableConfigurationProperties로 등록해야 한다. 여러 모듈에서 설정 클래스를 관리한다면 애플리케이션 시작 클래스에 스캔 방식을 두는 편이 단순하다. 설정 객체는 컨트롤러에서 직접 꺼내 쓰기보다 WebClient, RestClient, 메시지 발행기 같은 인프라 빈을 만드는 구성 클래스에 주입한다.
@SpringBootApplication
@ConfigurationPropertiesScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@Configuration
class PaymentClientConfig {
@Bean
RestClient paymentRestClient(PaymentClientProperties properties) {
return RestClient.builder()
.baseUrl(properties.baseUrl().toString())
.build();
}
}설정 객체를 서비스마다 복사하거나 문자열 키를 반복해서 조회하면 키 이름 변경 시 누락이 생긴다. 한 번 바인딩한 객체를 의존성으로 전달하면 컴파일러와 테스트가 변경 영향을 더 빨리 알려 준다. 또한 설정값이 갱신 가능한지 여부를 명확히 정해야 한다. 일반적인 서버 설정은 기동 시 고정하고, 런타임 갱신이 정말 필요한 기능 플래그만 별도 구성 관리 체계로 분리하는 편이 예측 가능하다.
테스트와 배포 전 점검
설정 검증은 정상 사례만 확인해서는 충분하지 않다. 누락, 경계값, 잘못된 URI가 들어왔을 때 컨텍스트가 시작하지 않는지 테스트한다. 통합 테스트에서는 @SpringBootTest의 properties 속성 또는 테스트 전용 프로필로 필요한 최소 설정을 제공한다. 운영 배포 파이프라인에서는 실제 비밀값을 노출하지 않고도 필수 환경 변수가 존재하는지 검증할 수 있다.
@SpringBootTest(properties = {
"payment.client.base-url=https://sandbox.example.com",
"payment.client.connect-timeout-ms=500",
"payment.client.read-timeout-ms=2000",
"payment.client.max-retries=1",
"payment.client.api-version=v1"
})
class PaymentClientConfigTest {
}적용 체크리스트
- 관련 설정을 하나의 @ConfigurationProperties 클래스 또는 record로 묶는다.
- URL, 숫자, 열거형은 가능한 한 적절한 타입으로 받고 Bean Validation 범위를 지정한다.
- 운영 비밀값은 저장소에 커밋하지 않고 배포 환경의 시크릿 주입으로 제공한다.
- 프로필과 환경 변수의 우선순위를 문서화하고 중복 키를 줄인다.
- 누락과 잘못된 형식에서 애플리케이션이 즉시 실패하는지 배포 전 테스트한다.
spring
| No | 작성일 | Title |
|---|---|---|
| 2124 | 2026. 02. 11. | Virtual Thread와 Spring WebFlux 성능 비교 |
| 2123 | 2026. 02. 11. | Spring AI: 스프링에서 LLM 통합하기 |
| 2122 | 2026. 02. 11. | Spring Boot 3.4 신기능과 마이그레이션 가이드 |
| 2013 | 2025. 11. 30. | Spring Cache 추상화 - Redis 캐시 적용 |
| 2012 | 2025. 11. 30. | Spring Validation - Bean Validation 활용 |
| 2011 | 2025. 11. 30. | Spring Profile로 환경별 설정 관리 |
| 2010 | 2025. 11. 30. | Spring AOP로 로깅과 트랜잭션 처리 |
| 2009 | 2025. 11. 30. | Spring Batch 대용량 데이터 처리 |
| 2008 | 2025. 11. 30. | Spring Cloud Gateway로 API Gateway 구축 |
| 2007 | 2025. 11. 30. | Spring WebFlux - 리액티브 프로그래밍 입문 |