[Spring] Spring Config

buckshot·2026년 4월 27일

Spring

목록 보기
9/9
post-thumbnail

Spring Config??

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

기존에는 각 서비스마다 application.yml 또는 application.properties 파일을 직접 관리했다면,
Spring Config를 사용하면 이 설정들을 하나의 Config Server에서 통합 관리하고 각 클라이언트가 이를 가져다 사용하는 구조이다.


Spring Config의 필요성

MSA 환경에서의 설정 관리 문제

MSA 환경은 각 도메인 주제에 따라 마이크로서비스로 쪼개진다. 예를 들어 온라인 주문 플랫폼이 있을 때 다음과 같은 마이크로서비스들이 존재한다.

  • user-service
  • order-service
  • payment-service

이와 같은 구조에서 서비스마다 설정 파일이 존재하게 된다. 이런 구조에서 여러 문제가 발생한다.

❌ 문제점

  • 동일한 설정(DB, Redis 등)을 여러 번 작성
  • 설정 변경 시 모든 서비스에 직접 반영해야 함
  • 설정 값이 코드와 함께 배포됨 (보안/유지보수 문제)

설정 변경의 어려움

설정 파일이 코드와 함께 배포된다면 설정에 대한 변경으로 다음과 같은 동작을 추가적으로 수행해야 한다.

  • 모든 서비스의 설정 파일 수정
  • 다시 빌드
  • 다시 배포

이러한 구조는 운영 환경에서는 매우 비효율적이다.


Spring Config를 사용하는 이유

바로 앞에서 확인한 문제점을 해결하기 위해 다음과 같은 해결 방안을 제시해준다.

1. 중앙 집중식 설정 관리

  • 설정을 Git 저장소에 보관
  • Config Server가 이를 읽어서 제공
  • 각 서비스는 실행 시 Config Server에서 설정을 가져옴

2. 동적 설정 변경 (Hot Reload)

Spring ConfigActuator를 사용하면 서버 재시작 없이 설정 변경이 가능하다. 또한 /refresh 또는 Spring Cloud Bus 사용

+ ⍺

  • 환경별 설정 분리
{application-name}-{profile}.yml

위처럼 애플리케이션과 환경에 따라 설정을 분리하여 사용 가능하다.

  • 민감 정보 관리 용이 — 민감 정보(DB 비밀번호, Secret Key 등)를 암호화하여 관리할 수 있다.

Config의 구조

Spring Cloud Config의 동작은 크게 2가지로 나뉜다.

Config Server

설정 파일의 저장소(주로 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에 설정 파일 등록하는 방법

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 Client

서비스 구동 시 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에 접근하지 못해도 애플리케이션이 기동된다. 로컬 개발 환경에서 유용하다.


동적 설정 변경 (Refresh)

설정이 변경되었을 때 서비스를 재시작하지 않고 반영하는 방법은 두 가지다.

방법 1 — @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

다만 이 방법은 서비스가 여러 인스턴스로 띄워져 있을 때 각각 호출해야 한다는 단점이 있다.

방법 2 — Spring Cloud Bus (권장)

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

Spring Config 장/단점

✅ 장점

항목설명
중앙 집중 관리수십 개의 서비스 설정을 단일 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을 함께 활용하는 방식으로 완화할 수 있다.


Bootstrap.yml

Bootstrap사용

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 예시

# 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.yml의 변화

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 환경에서 운영 효율성과 안정성을 높이기 위한 핵심 인프라 요소이다.

설정 관련 정보를 코드에서 분리하여 중앙에서 관리하고, 변경을 빠르게 반영할 수 있도록 해준다.

profile
let's go insane

0개의 댓글