
Spring Cloud Config는 분산 시스템(특히 MSA)에서 애플리케이션 설정 정보를 중앙에서 관리할 수 있도록 해주는 서버 기반 도구입니다.

기존에는 각 서비스마다 application.yml 또는 application.properties 파일을 직접 관리했다면,
Spring Config를 사용하면 이 설정들을 하나의 Config Server에서 통합 관리하고 각 클라이언트가 이를 가져다 사용하는 구조이다.
MSA 환경은 각 도메인 주제에 따라 마이크로서비스로 쪼개진다. 예를 들어 온라인 주문 플랫폼이 있을 때 다음과 같은 마이크로서비스들이 존재한다.
user-serviceorder-servicepayment-service이와 같은 구조에서 서비스마다 설정 파일이 존재하게 된다. 이런 구조에서 여러 문제가 발생한다.
설정 파일이 코드와 함께 배포된다면 설정에 대한 변경으로 다음과 같은 동작을 추가적으로 수행해야 한다.
이러한 구조는 운영 환경에서는 매우 비효율적이다.
바로 앞에서 확인한 문제점을 해결하기 위해 다음과 같은 해결 방안을 제시해준다.
Spring Config와 Actuator를 사용하면 서버 재시작 없이 설정 변경이 가능하다. 또한 /refresh 또는 Spring Cloud Bus 사용
{application-name}-{profile}.yml
위처럼 애플리케이션과 환경에 따라 설정을 분리하여 사용 가능하다.
Spring Cloud Config의 동작은 크게 2가지로 나뉜다.
설정 파일의 저장소(주로 Git)를 바라보며, 클라이언트의 요청에 따라 알맞은 설정 값을 HTTP API로 제공한다.
의존성 추가 (build.gradle)
implementation 'org.springframework.cloud:spring-cloud-config-server'
활성화
@SpringBootApplication
@EnableConfigServer // Config Server 활성화
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
Config Server 설정 (application.yml)
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: https://github.com/your-org/config-repo # 설정 파일이 있는 Git 저장소
default-label: main # 브랜치
search-paths: '{application}' # 서비스별 디렉토리 분리 시
Git 저장소 외에도 로컬 파일시스템(
native), Vault, JDBC 등을 백엔드로 사용할 수 있다.
Config Server가 바라보는 Git 저장소에 설정 파일을 올려두는 것만으로 등록이 완료된다. 파일명 규칙은 다음과 같다.
{application-name}.yml # 특정 서비스의 기본 설정
{application-name}-{profile}.yml # 특정 서비스의 환경별 설정
application.yml # 모든 서비스에 공통 적용되는 설정
예시 — Git 저장소 구조
config-repo/
├── application.yml # 공통 설정 (모든 서비스에 적용)
├── user-service.yml # user-service 기본 설정
├── user-service-dev.yml # user-service 개발 환경 설정
├── user-service-prod.yml # user-service 운영 환경 설정
├── order-service.yml
└── payment-service.yml
예시 — user-service-prod.yml
spring:
datasource:
url: jdbc:mysql://prod-db:3306/users
username: prod_user
password: '{cipher}AQB...' # 암호화된 값
jwt:
secret: '{cipher}AQC...'
Config Server는 {application}, {profile}, {label} 세 가지 정보를 기반으로 적절한 파일을 찾아 응답한다. 이 정보는 클라이언트가 요청 시 자동으로 전달한다.
GET http://config-server:8888/{application}/{profile}/{label}
# 예: GET http://config-server:8888/user-service/prod/main
서비스 구동 시 Config Server에서 설정 파일을 가져온다.
의존성 추가 (build.gradle)
implementation 'org.springframework.cloud:spring-cloud-starter-config'
클라이언트 설정 (bootstrap.yml 또는 application.yml)
Spring Boot 2.4 이전에는 bootstrap.yml을 사용했으나, 이후 버전에서는 spring.config.import를 통해 application.yml 단일 파일로 통합되었다.
# Spring Boot 2.4+ 방식 (application.yml)
spring:
application:
name: user-service # Config Server에서 찾을 파일명 기준
profiles:
active: prod
config:
import: optional:configserver:http://localhost:8888
optional:접두사를 붙이면 Config Server에 접근하지 못해도 애플리케이션이 기동된다. 로컬 개발 환경에서 유용하다.
설정이 변경되었을 때 서비스를 재시작하지 않고 반영하는 방법은 두 가지다.
@RefreshScope + Actuator /refresh설정 값을 사용하는 Bean에 @RefreshScope를 선언하고, Actuator의 /actuator/refresh 엔드포인트를 POST로 호출하면 해당 Bean이 재생성되어 새로운 설정이 반영된다.
@RefreshScope
@RestController
public class SomeController {
@Value("${some.property}")
private String someProperty;
}
# 설정 변경 후 호출
curl -X POST http://user-service:8080/actuator/refresh
다만 이 방법은 서비스가 여러 인스턴스로 띄워져 있을 때 각각 호출해야 한다는 단점이 있다.
Spring Cloud Bus는 RabbitMQ 또는 Kafka를 메시지 브로커로 사용하여, Config Server의 /actuator/busrefresh 한 번 호출만으로 연결된 모든 서비스에 변경 사항을 브로드캐스트한다.
Config Server /actuator/busrefresh 호출
↓
RabbitMQ / Kafka
↓
user-service, order-service, payment-service 동시 갱신
# 각 서비스 의존성 추가
implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp' # RabbitMQ
# 또는
implementation 'org.springframework.cloud:spring-cloud-starter-bus-kafka' # Kafka
| 항목 | 설명 |
|---|---|
| 중앙 집중 관리 | 수십 개의 서비스 설정을 단일 Git 저장소에서 관리 |
| 환경 분리 | dev / prod 설정을 파일명 규칙으로 명확히 분리 |
| 보안 강화 | 민감 정보를 암호화({cipher})하여 저장, 소스코드에 노출 없음 |
| 동적 반영 | Cloud Bus 연동 시 전체 서비스 무중단 설정 갱신 |
| 이력 관리 | Git 기반이므로 설정 변경 이력이 자동으로 추적됨 |
| 롤백 용이 | Git revert 만으로 이전 설정으로 복구 가능 |
| 항목 | 설명 |
|---|---|
| 단일 장애점 (SPOF) | Config Server가 다운되면 모든 서비스 기동 불가. optional: 또는 고가용성 구성 필요 |
| 초기 복잡도 | Git 저장소 관리, 암호화 키 설정, Cloud Bus 연동 |
| 네트워크 의존 | 서비스 기동 시 Config Server와의 통신이 전제되어야 함 |
| 캐시 일관성 | 클라이언트가 설정을 로컬에 캐싱하므로, 갱신 전까지 구버전 설정을 유지할 수 있음 |
SPOF 문제는 Config Server를 복수 인스턴스로 구성하고 Load Balancer 뒤에 두거나, Kubernetes 환경이라면 ConfigMap을 함께 활용하는 방식으로 완화할 수 있다.
Spring Config에서 문제가 발생한다.
Config Server에서 설정을 가져오려면, 애플리케이션이 기동되기 전에 이미 Config Server의 주소를 알고 있어야 한다. 그래서 bootstrap.yml이 사용된다.
bootstrap.yml이 바로 그 "임시 출입증" 이라고 생각하면 된다.
어플리케이션이 본격적으로 뜨기 전에 가장 먼저 읽혀서, Config Server 주소처럼
"설정을 가져오기 위해 필요한 최소한의 정보" 를 미리 확보해두는 방법이다.
bootstrap.yml은 Spring Boot 애플리케이션의 부트스트랩 컨텍스트(Bootstrap Context) 에서 로드되는 설정 파일이다.
Spring Boot는 애플리케이션 기동 시 컨텍스트를 두 단계로 나눠 초기화한다.
1단계 (Bootstrap Context)
bootstrap.yml 로드
→ Config Server 주소, 암호화 키 등 "설정을 가져오기 위한 설정" 처리
↓
2단계 (Application Context)
application.yml 로드
→ 1단계에서 가져온 설정 포함, 실제 애플리케이션 Bean 초기화
즉, "설정을 가져오기 위해 필요한 설정" 을 담는 파일이 bootstrap.yml이다.
application.yml보다 먼저 로드되고, 우선순위도 더 높기 때문에 application.yml에서 덮어쓸 수 없다.
Config Server에서 설정을 가져오려면, 애플리케이션이 기동되기 전에 이미 Config Server의 주소를 알고 있어야 한다.
그런데 application.yml은 Bean 초기화와 함께 로드되기 때문에 타이밍이 맞지 않는다.
❌ 문제 상황
application.yml에 Config Server 주소를 적어두면
→ Bean 초기화 시점에 읽힘
→ 그 시점엔 이미 설정을 가져올 타이밍이 지남
✅ 해결
bootstrap.yml에 Config Server 주소를 적어두면
→ 애플리케이션 컨텍스트 초기화 이전에 읽힘
→ Config Server에서 설정을 먼저 가져올 수 있음
# bootstrap.yml
spring:
application:
name: user-service # Config Server에서 가져올 파일명 기준
cloud:
config:
uri: http://localhost:8888 # Config Server 주소
profile: prod # 활성 프로파일
label: main # Git 브랜치
application.yml에는 Config Server에서 가져온 설정을 포함한 나머지 애플리케이션 설정을 작성한다.
Spring Boot 2.4부터 Bootstrap Context 방식이 기본 비활성화되었다.
대신 spring.config.import를 통해 application.yml 하나로 통합하는 방식이 권장된다.
# application.yml (Spring Boot 2.4+)
spring:
application:
name: user-service
config:
import: optional:configserver:http://localhost:8888
그럼에도 기존 방식(bootstrap.yml)을 유지하고 싶다면 아래 의존성을 추가하면 된다.
implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap'
Spring Config는 단순한 설정 관리 도구가 아니라, MSA 환경에서 운영 효율성과 안정성을 높이기 위한 핵심 인프라 요소이다.
설정 관련 정보를 코드에서 분리하여 중앙에서 관리하고, 변경을 빠르게 반영할 수 있도록 해준다.