Spring Cloud Config Server는 분산 시스템에서 중앙 집중식 설정 관리를 가능하게 해주는 도구로,
애플리케이션 설정을 Git, Vault 등의 외부 저장소에서 관리하여, 이를 Spring Boot 기반의 클라이언트 애플리케이션이 가져와서 사용할 수 있도록 구성할 수 있습니다.
이번 글에서는 Spring Cloud Config Server와 HashiCorp Vault(HCP Vault)를 연동하여, 보안이 필요한 설정 값을 안전하게 관리하는 방법을 설명합니다.
또한, Spring Cloud Config Client가 설정 값을 어떻게 가져와서 애플리케이션에서 활용할 수 있는지도 함께 다뤄보겠습니다.
1. Vault 구성
Vault는 비밀번호, API 키, 인증 정보 등의 보안 데이터를 저장하고 관리하는 강력한 도구입니다.
Vault는 설치형(On-Premise)으로 사용할 수도 있고, HCP(HashiCorp Cloud Platform) Vault(SaaS)를 사용하여 관리형 서비스로 운영할 수도 있습니다.
필자의 경우 HCP Vault(SaaS)를 사용하여 설정 값을 저장하고 관리하는 방식을 선택했습니다.
1-1) KV(Key-Value) 엔진 구성
- 1) KV V2 시크릿 엔진 활성화를 진행합니다.
vault login <your-root-token> # Vault 로그인 (토큰 사용)
export VAULT_NAMESPACE=admin # 네임스페이스 설정
vault secrets enable -path=spring-config-kv -version=2 kv
- vault secrets enable : 새로운 시크릿 엔진을 활성화하는 명령어
- -version=2 : Key-Value Version 2(KV V2) 엔진을 활성화합니다.
- kv : 사용하려는 시크릿 엔진 유형이 Key-Value(kv)임을 명시합니다.
- -path=spring-config-kv : 시크릿 엔진을 spring-config-kv라는 경로(path)에 마운트합니다.
- 환경별 시크릿 저장합니다. (dev, local, prod)
# dev 환경
vault kv put spring-config-kv/spring/dev \
db_url="jdbc:mysql://dev-db-url" \
username="dev-username" \
password="dev-password"
# local 환경
vault kv put spring-config-kv/spring/local \
db_url="jdbc:mysql://local-db-url" \
username="local-username" \
password="local-password"
# prod 환경
vault kv put spring-config-kv/spring/prod \
db_url="jdbc:mysql://prod-db-url" \
username="prod-username" \
password="prod-password"
- vault kv put <경로> <키>=<값> : Vault KV V2 시크릿 엔진에 데이터를 저장하는 명령어
- spring-config-kv/spring/dev : spring-config-kv 경로 아래 spring/dev 위치에 시크릿 저장합니다.
- db_url="<DB URL 기입>" : db_url 값을 저장합니다.
- password="<DB 패스워드 기입>" : password 값을 저장합니다.
- username="<DB User 이름 기입>" : username 값 저장합니다.
- 저장된 시크릿 조회 예시) (dev)
$ vault kv get spring-config-kv/spring/dev
========== Secret Path ==========
spring-config-kv/data/spring/dev
======= Metadata =======
Key Value
--- -----
created_time 2025-03-08T09:38:55.872151421Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
====== Data ======
Key Value
--- -----
db_url jdbc:mysql://dev-db-url
password dev-password
username dev-username
2. Spring Cloud Config Server 구성
Spring Cloud Config Server는 HashiCorp Vault와 연결되어 클라이언트 애플리케이션에 필요한 설정 값을 제공하는 역할을 합니다.
2-1) Gradle 의존성 (dependencies 설정)
Gradle 기반의 Spring Boot 프로젝트를 생성하고, build.gradle.kts에 아래와 같이 의존성을 추가합니다.
dependencies {
// Spring Cloud Config Server
implementation("org.springframework.cloud:spring-cloud-config-server")
// Spring Cloud Vault
implementation("org.springframework.cloud:spring-cloud-starter-vault-config")
// Kotlin 필수 설정
implementation("org.jetbrains.kotlin:kotlin-reflect")
}
- implementation("org.springframework.cloud:spring-cloud-config-server")
- Spring Cloud Config Server를 활성화하는 라이브러리
- implementation("org.springframework.cloud:spring-cloud-starter-vault-config")
- HashiCorp Vault와 Spring Cloud Config Server 간 연동을 위한 라이브러리
2-2) Config Server 애플리케이션 코드 작성 (KotlinGradleVaultApplication.kt)
package com.example.kotlin_gradle_vault
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.cloud.config.server.EnableConfigServer
@SpringBootApplication
@EnableConfigServer
class KotlinGradleVaultApplication
fun main(args: Array<String>) {
runApplication<KotlinGradleVaultApplication>(*args)
}
- @EnableConfigServer
- Spring Cloud Config Server를 활성화하는 어노테이션
- 이 설정을 통해 Spring Cloud Config Server가 활성화되며, Vault에서 설정 값을 가져올 수 있도록 동작하게 됩니다.
2-3) application.yml 설정
Vault와 연동하여 설정 값을 가져오기 위해 Spring Cloud Config Server의 설정 파일을 구성합니다.
server:
port: 8888
spring:
application:
name: spring-config-server
profiles:
active: vault
cloud:
config:
server:
vault:
fail-fast: true # Vault 연결 실패 시 서버 시작 차단
host: {vault hostname 기입}
port: 8200
namespace: {vault namespace 기입}
authentication: token
token: {vault token 기입} # Vault 접근 토큰
kv-version: 2
backend: spring-config-kv # Vault의 KV 엔진 경로
profile-separator: '/'
scheme: https
- server.port: 8888
- Spring Cloud Config Server가 포트 8888에서 실행됩니다.
- spring.profiles.active: vault
- Vault를 설정 저장소로 사용하도록 프로파일 활성화합니다.
- spring.cloud.config.server.vault.fail-fast: true
- Vault 연결 실패 시 서버 시작을 차단 합니다.
- (설정 값을 필수로 가져와야 할 경우 유용합니다.)
- spring.cloud.config.server.vault.host: {vault hostname}
- spring.cloud.config.server.vault.port: 8200
- spring.cloud.config.server.vault.namespace: {vault namespace 기입}
- spring.cloud.config.server.vault.authentication: token
- spring.cloud.config.server.vault.token: {vault token 기입}
- Vault 서버 정보를 정의합니다.
- 호스트네임 또는 IP, 포트 번호, 네임스페이스(HCP Vault 사용 시 필수) 등을 기입합니다.
- Vault 서버 정보를 정의합니다.
- spring.cloud.config.server.vault.kv-version: 2
- Vault에서 사용되는 Key-Value (KV) 엔진의 버전을 기입합니다. (V2 사용)
- spring.cloud.config.server.vault.backend: spring-config-kv
- Vault에서 설정 값을 저장하는 KV 엔진의 마운트 경로입니다
- spring.cloud.config.server.vault.profile-separator: '/'
- Vault에서 프로파일별 설정을 구분하는 구분자 (spring/prod 형식으로 저장됨) 를 설정합니다.
- spring.cloud.config.server.vault.scheme: https
- Vault와의 통신 방식을 정의합니다. (HTTPS 사용)
2-4) Spring Cloud Config Server 실행
- ./gredlew clean bootRun 명령어를 통해 Config Server를 실행합니다.

- Vault에서 Config Server가 설정을 가져오는 과정을 확인합니다.

- propertySources에 vault:spring/dev에서 가져온 설정이 포함되어 확인 가능합니다.
- db_url, username, password 등의 정보가 정상적으로 Vault에서 가져와졌음을 확인 가능합니다.
개인 정리
최종 테스트에서는 KV mount를 spring-config-kv로 설정하고, spring/dev 밑에 KV를 저장하는 방식을 사용하여 Config Server에서 spring/dev 경로로 값을 가져오도록 진행했으나, KV mount를 spring-test로 하고, ops 밑에 직접 KV를 저장했을 때는 ops/default 경로에서 값을 정상적으로 가져올 수 있었음.. ( localhost:8888/ops/default -- 이런 호출 방식으로 진행 )
정리하자면....
Spring Cloud Config Server의 프로퍼티 매핑 방식은 다음과 같다고 한다... (URL 참고)
- Config Server는 설정 값을 {application}/{profile}/{label} 형태로 매핑하여 제공
- {application} : spring.application.name (애플리케이션 이름)
- {profile} : spring.profiles.active (현재 활성화된 프로필)
- {label} : 기본적으로 master (Git 레이블이나 브랜치)
즉, 내가 application.yml에 backend를 spring-config-kv로 설정해놨기에,
http://localhost:8888/spring/prod 로 호출을 하면 spring-config-kv/spring/prod에서 데이터를 가져옴!
Vault KV Mount 및 Profile Path의 차이점 (테스트 결과)
1. KV Mount를 spring-config-kv로 설정하고, spring/prod 경로로 KV 저장한 경우
- Vault 경로 : spring-config-kv/spring/prod
- Config Server 요청 : http://localhost:8888/spring/prod
- 정상적으로 값을 가져올 수 있음
2. KV Mount를 spring-test로 설정하고, ops에 직접 KV 저장한 경우
- Vault 경로: spring-test/ops
- Config Server 요청: http://localhost:8888/ops/default
- ops/default에서 값을 가져와야 정상적으로 동작
Config Server는 spring/{profile} 형태로 경로를 찾지만, Vault는 KV Mount마다 다른 접근 방식을 요구할 수 있음!!
KV Mount 이름과 Config Server의 Profile 구조가 정확히 일치해야 예상한 대로 설정이 로딩되며, 필요에 따라 profile-separator, default-context 설정을 조정할 필요가 있음