Spring 개발일지

[팀프로젝트] MSA 기반 티켓팅 프로그램 - Config Server 연동 삽질기

김둘리 2026. 5. 7. 09:43

MSA 환경에서 각 서비스가 각자 설정을 관리하면 관리 포인트가 너무 많아진다.
Spring Cloud Config Server로 중앙 집중식 설정 관리를 구현했다.
처음에는 간단해 보였는데 환경변수 주입 방식 때문에 꽤 삽질했다.


1. Config Server 구조

config-repo (GitHub)
    ├── application.yml              # 전체 공통
    ├── application-local.yml        # 로컬 공통
    ├── application-prod.yml         # 운영 공통
    └── payment-service/
        ├── payment-service.yml      # payment-service 공통
        ├── payment-service-local.yml # payment-service 로컬
        └── payment-service-prod.yml  # payment-service 운영

config-server (Spring Cloud Config Server)
    → config-repo를 읽어서 각 서비스에 전달

payment-service
    → config-server에서 설정을 받아서 사용

설정 우선순위는 더 구체적인 파일이 일반적인 파일을 덮어쓴다.

payment-service-local.yml > payment-service.yml > application-local.yml > application.yml

2. config-repo 설정 파일 작성

payment-service.yml (공통)

spring:
  jpa:
    properties:
      hibernate:
        format_sql: true
    show-sql: true

payment-service-local.yml (로컬)

server:
  port: 8085

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password:
  jpa:
    hibernate:
      ddl-auto: create-drop
  flyway:
    enabled: false

toss:
  secret-key: '{cipher}암호화된값'

payment-service-prod.yml (운영)

server:
  port: 8080

spring:
  datasource:
    url: jdbc:postgresql://postgres:5432/payment
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}
  jpa:
    hibernate:
      ddl-auto: validate
  flyway:
    enabled: true

toss:
  secret-key: ${TOSS_SECRET_KEY}

prod는 민감정보를 환경변수로 관리한다. DB 비밀번호처럼 팀 공통 ENCRYPT_KEY로 암호화하기 어려운 값은 서버 환경변수로 주입한다.


3. payment-service application.yml 수정

기존 application.yml에 있던 datasource, jpa 설정을 전부 제거하고 Config Server 연동 설정만 남겼다.

spring:
  application:
    name: payment-service
  config:
    import: "optional:configserver:${CONFIG_SERVER_URL:http://localhost:8888}"
  cloud:
    config:
      username: ${CONFIG_SERVER_USERNAME}
      password: ${CONFIG_SERVER_PASSWORD}

payment-service라는 이름이 config-repo의 폴더명/파일명과 일치해야 한다.


4. 삽질 1 — 401 Unauthorized

처음 실행하니까 이런 에러가 났다.

401 on GET request for "http://localhost:8888/payment-service/default"

Config Server에 Basic Auth가 걸려있는데 인증 정보를 못 넘기고 있었다.

원인 분석

application.yml에 이렇게 되어있었다.

spring:
  cloud:
    config:
      username: ${CONFIG_SERVER_USERNAME:}
      password: ${CONFIG_SERVER_PASSWORD:}

${CONFIG_SERVER_USERNAME:}은 기본값이 빈 문자열이라 인증이 항상 실패했다.

그리고 .env 파일에 값이 있어도 터미널에서 확인하니 환경변수가 주입이 안 되어있었다.

echo $CONFIG_SERVER_USERNAME
# (아무것도 안 나옴)

원인: build.gradle에서 .env를 읽어서 Gradle 변수로는 사용하지만 Spring 실행 시 시스템 환경변수로 주입되지 않는다.

해결: IntelliJ Run Configuration → Environment variables에 직접 추가했다.

CONFIG_SERVER_USERNAME=admin
CONFIG_SERVER_PASSWORD=admin1234

그리고 application.yml에서 기본값 제거했다.

spring:
  cloud:
    config:
      username: ${CONFIG_SERVER_USERNAME}
      password: ${CONFIG_SERVER_PASSWORD}

5. 삽질 2 — payment-service/default로 요청

로그를 보니 이런 로그가 있었다.

GET "http://localhost:8888/payment-service/default"

default 프로파일로 요청하고 있어서 payment-service-local.yml을 못 읽어왔다.

해결: payment-service IntelliJ Run Configuration에 Active profiles에 local 추가했다.

Active profiles: local

이후 로그가 이렇게 바뀌었다.

Located environment: name=payment-service, profiles=[local]

6. toss.secret-key 암호화

config-repo에 토스 시크릿 키가 평문으로 올라가 있으면 보안 문제다. Config Server의 /encrypt 엔드포인트로 암호화했다.

curl -u admin:admin1234 \
  -X POST http://localhost:8888/encrypt \
  -d "test_sk_6bJXmgo28e71a9Obm2JjVLAnGKWx"

응답받은 암호문을 payment-service-local.yml에 저장했다.

toss:
  secret-key: '{cipher}41da203e17de7526e41751252bffc8e117...'

반드시 작은따옴표로 감싸야 한다. 없으면 YAML 파싱 에러가 난다.

Config Server가 ENCRYPT_KEY로 자동 복호화해서 payment-service에 평문으로 전달한다.


7. 최종 동작 확인

config-server 실행 후 payment-service를 재시작하니 이런 로그가 찍혔다.

Fetching config from server at : http://localhost:8888
Located environment: name=payment-service, profiles=[local]

Config Server에서 설정을 잘 받아오고 있다.


마무리

Config Server 연동에서 겪은 삽질을 정리하면 이렇다.

삽질 1 — 401 Unauthorized
build.gradle에서 .env를 읽어도 Spring 실행 시 환경변수로 주입되지 않는다. IntelliJ Run Configuration에 직접 추가해야 한다.

삽질 2 — default 프로파일로 요청
payment-service Run Configuration에 Active profiles에 local을 추가해야 payment-service-local.yml을 읽어온다.

민감정보 암호화
Config Server의 /encrypt 엔드포인트로 암호화 후 {cipher} 접두어와 함께 저장한다. 작은따옴표 필수!

다음 편에서는 아웃박스 패턴 구현을 다룰 예정이다.