
Spring Cloud Config server 도입기
Spring
2025.09.18.
Spring Cloud Config Server 도입기다.
1. 문제 상황
현재 시스템의 환경 설정 관리는 여러 부분에 분산되어 있다.
- NextJS App의 환경 설정 파일을 개발 환경에선 .env.development(각자 개인이)로 관리하고, 운영환경에서는 Jenkins의 스크립트에서 관리 - ex) echo “NEXT_PUBLIC_BASE_PATH=/data_platform” >> .env.production
- mng서버, clct서버, api gateway서버, spring cloud gateway서버 등 모두 같은 DB에 접근하는데 전부 application.yml에 복사 붙여넣기 되어있다.
- 만약 DB설정 정보가 변경된다면 모든 서버의 코드를 찾아서 수정하고 배포
- 로컬, 운영환경마다 설정이 다른데 관리해야 할 .yml파일이 너무 많음
- 설정 변경을 위한 불필요한 재배포
- 단순히 로그 레벨을 DEBUG로 바꿀때와 같은 간단한 변경을 위해서도 매번 코드를 수정, 빌드, 재배포 과정을 가진다.
2. Spring Cloud Config란?
- Spring Cloud Config는 분산 시스템에서 외부화된 설정 정보를 서버 및 클라이언트에게 제공하는 시스템
- 설정 서버는(Config Server)는 외부에서 모든 환경에 대한 정보들을 관리해주는 중앙 서버
- git을 사용하도록 되어있어서 손쉽게 외부 도구들로 접근 가능하고, 버전 관리도 가능
- Spring Cloud Config 설정 파일 우선 순위
- 프로젝트의 application.yaml
- 설정 저장소의 application.yaml
- 프로젝트의 application-{profile}.yaml
- 설정 저장소의 {application name}/{application name}-{profile}
3. 해결책 → Spring Cloud Config Server사용
- 설정의 중앙화
- 서비스 코드 저장소가 아닌 별도의 Git저장소에 모아두는 것이 가능
- 모든 서버가 시작할 때 로컬의
application.yml이 아닌 Config Server에 질의 → 동적으로 주입 - NextJS의 App의 경우 빌드 시점에 설정을 가져와 환경 변수를 설정 해 사용
- 적용 방식
- Spring Boot 서비스: spring-cloud-starter-config 의존성을 추가하고, bootstrap.yml에 Config Server 주소만 명시하면 애플리케이션 구동 시 자동으로 설정을 가져온다.
- Next.js App: 빌드 시점(e.g., Jenkins Pipeline)에 curl 이나 스크립트를 통해 Config Server API를 호출하여 설정 값을 받아온 후, .env.production 파일을 동적으로 생성
4. 기대 효과
- DB접속 정보는 설정의 Git 저장소인 application.yml 단 한곳에만 존재
- 관리 포인트 감소: 수십 개의 application.yml 파일을 개별적으로 관리하던 복잡성이 사라지고, 중앙 Git 저장소 하나만 관리
- 강력한 보안
- 민감한 정보는 더이상 서비스 코드와 함께 관리되지 않는다.
- Git 저장소는 접근 권한을 더 엄격하게 관리가 가능
- 더 나아가 Config Server는 설정값을 암호화하는 기능 제공
- 암호화된 텍스트만 저장, 서비스에게 값을 전달할 때만 복호화
- 동적 리프레시
- 서버 재배포 없이 설정 변경이 가능
- 로그레벨 INFO, DEBUG로 바꾸기
- 간단한 API호출 (actuator/refresh)만 해주면 해당 서버가 재시작 없이 즉시 새로운 설정 반영
- 서버 재배포 없이 설정 변경이 가능
- 변경된 설정을 각 서버에 동적으로 반영 가능
- (Pull) 개별 적용: actuator/refresh API를 호출하여 특정 서비스 인스턴스만 설정을 갱신
- (Push) 전체 전파: Spring Cloud Bus와 RabbitMQ/Kafka 같은 메시지 큐를 연동하여, Git 변경 사항을 Webhook으로 감지하고 연결된 모든 서비스에 이벤트를 보내 한 번에 설정을 갱신시킬 수 있다.
5. 예상 질문
- Q: 관리 포인트가 늘어나는 것 아닌가?
- 서버 하나와 Git저장소 하나가 추가되지만, 최소 10개가 넘는 설정파일을 개별적으로 관리하며 발생하는 복잡도에 비하면 낮은 비용. 중앙 관리를 통해 얻는 안정성과 효율성이 극대화
- Q: Config Server가 죽으면 모든 서비스가 시작도 못하는거 아닌가?
- 맞다. Config Server는 이중화해 고가용성을 확보하는 것이 표준적인 구성
- 각 서비스는 시작 시 Config Server가 응답이 없으면 시작에 실패하도록 설정하여, 잘못된 설정으로 서비스가 뜨는 것을 방지
- Q: 기존 애플리케이션에 적용하는 과정이 복잡하지 않은가요?
- Spring Boot 기반 애플리케이션의 경우, 의존성 1개와 bootstrap.yml 파일에 몇 줄의 설정만 추가하면 되므로 매우 간단하게 적용
- Non-Spring 애플리케이션(Next.js 등)도 표준 REST API를 통해 설정을 조회하므로 언어와 프레임워크에 제약 없이 유연하게 연동
6. 구현
6.1 설정파일을 저장할 Git 생성
-
git-lab repository 생성
-
설정 파일 추가
ex) mng.yml, mng-dev.yml, mng-prod.yml
6.2 Config 서버 설정
-
프로젝트 생성
-
build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.4.4'
id 'io.spring.dependency-management' version '1.1.7'
}
group = 'com.egis'
version = '0.0.1-SNAPSHOT'
description = 'dataplatform-config-server'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
repositories {
mavenCentral()
}
ext {
set('springCloudVersion', "2024.0.2")
}
dependencies {
// Spring Cloud Config Server 기능을 활성화하는 핵심 의존성
implementation 'org.springframework.cloud:spring-cloud-config-server'
// Spring Boot 프로젝트의 기본 테스트 라이브러리
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
// Spring Cloud 버전을 BOM(Bill of Materials)으로 관리
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
tasks.named('test') {
useJUnitPlatform()
}
- yml파일 작성
server:
port: 8070
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: http://192.168.50.253:8095/data_platform/dataplatform-config
search-paths: '{application}'
username: hshoon
password: ********
clone-on-start: true
default-label: deploy/prod
- java code 작성
@EnableConfigServer
@SpringBootApplication
public class DataplatformConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(DataplatformConfigServerApplication.class, args);
}
}
spring security는 .authorizeHttpRequests 설정해서 ip 허용규칙 작성
- 결과 확인
6.3 Micro service server config 설정
build.gradle에
implementation 'org.springframework.cloud:spring-cloud-starter-config'
설정 추가
application.yml
spring:
config:
import: "configserver:http://localhost:8070"
application:
name: mng
management:
endpoints:
web:
exposure:
include: refresh, health, info
local환경에선 intellij에 환경 설정 값을 준다.
6.4 Spring Cloud Config 설정 파일 내용 갱신하는 방법
별다른 설정 없이는 설정 파일이 변경되어도 설정 클라이언트에 반영 X
-> 설정 서버에 부하를 줄이도록 어플리케이션 실행 시점에 1번 설정 정보를 읽고 로컬에 캐싱
3가지 방법으로 갱신 가능
- spring cloud client서버들에 actuator API 호출
- POST로 /actuator/refresh 요청
- 서버가 여러대라면 번거롭다.
- spring-cloud-bus사용해 이벤트 전파
- 설정 정보등의 변경을 전파하기 위한 경량화된 메세지 브로커
- Config Server에 /bus/refresh 요청 한 번만 보내면 연결된 모든 클라이언트가 자동으로 갱신. 이벤트 기반 아키텍처에 잘 맞는다.
- RabbitMQ나 Kafka 같은 메시지 브로커를 추가로 설치하고 운영해야 한다.
- Watcher를 통해 spring cloud server에 변경 여부 확인
- 설정 서버에게 변경 여부를 지속적으로 물어보고 확인하는 컴포넌트
- 메시지 브로커 같은 추가적인 인프라가 필요 없다.
- 주기적인 Polling이 서버에 거의 부하를 주지 않는다.
- 중소규모의 MSA환경이기 때문에 해당 방식이 제일 적합하다고 생각해 채택
Reference
[Spring] Spring Cloud Config 도입하기 및 private 레포지토리 SSL로 연결 설정 및 privateKey 암호화
[Spring] Spring Cloud Config 설정 파일 내용을 갱신하는 방법, Spring Cloud Bus 없이 자동 갱신하기(AutoRefresh)
[Spring] Spring Cloud Config 정리
[Spring Cloud] Config Server 구축하기 (busrefresh 하기)