Config Server — 흩어진 설정을 한 곳에서 뿌리기
코드와 설정은 다르다. 코드는 "무엇을 하는가"이고, 설정은 "어디에 연결하고 어떤 값으로 동작하는가"다. DB 주소, 외부 API 키, 기능 on/off 플래그 같은 것들 — 이건 환경(개발·스테이징·운영)마다 다르고, 코드를 안 고치고도 바뀌어야 한다. 그래서 설정은 코드 밖으로 빼는 게 정석이다.
서비스가 하나면 설정 파일도 하나라 별 문제가 없다. 그런데 마이크로서비스로 쪼개 서비스가 10개, 20개가 되면 이야기가 달라진다. 같은 DB 비밀번호가 여러 서비스에 중복으로 박혀 있고, 그 값 하나를 바꾸려면 모든 서비스의 설정을 각각 고쳐 전부 다시 배포해야 한다. Config Server는 이 설정들을 한 곳(주로 Git 저장소)에 모아두고, 각 서비스가 부팅할 때 거기서 받아오게 만든다.
설정을 Git 저장소에 두고, Config Server가 그걸 읽어 각 서비스에
내려보내는 표준 구성을 기준으로 한다. order-service,
payment-service 가 부팅하며 자기 설정을 Config Server에서 받아오는
시나리오를 따라간다.
1. 흩어진 설정이 만드는 문제
왜 굳이 서버를 하나 더 두면서까지 설정을 중앙화할까? 흩어진 설정이 실제로 어떤 고통을 주는지 보면 답이 분명해진다.
- 1값 하나 바꾸려면 전부 재배포
공통 DB 비밀번호가 10개 서비스에 복사돼 있다.
비밀번호를 교체하면 그 값을 쓰는 모든 서비스의 설정 파일을 고치고 각각 빌드·배포해야 한다. 하나라도 빠뜨리면 그 서비스만 옛 값으로 동작해 장애가 난다.
- 2환경별 설정이 코드에 섞인다
개발·운영 DB 주소가 코드/이미지에 박힌다.
환경마다 다른 빌드를 만들게 되고, "운영 이미지에 개발 DB 주소가 들어간" 사고가 난다. 설정은 환경에 따라 갈아끼우는 외부 값이어야 하는데 그게 안 된다.
- 3변경 이력을 추적할 수 없다
누가 언제 어떤 값을 왜 바꿨는지 모른다.
설정 사고는 코드 사고만큼 잦은데, 흩어진 파일에는 이력이 안 남는다. 설정을 Git에 두면 변경 이력·리뷰·되돌리기가 코드와 똑같이 가능해진다. Config Server가 Git을 백엔드로 쓰는 핵심 이유다.
이 문제들의 공통 원인은 하나다. 설정이 서비스마다 흩어져 있다는 것. 그러니 해법도 하나의 방향으로 모인다 — 설정을 한 곳에 모으고, 서비스는 그곳을 바라보게 하는 것.
2. 부팅할 때 설정을 받아오는 흐름
핵심 동작은 단순하다. 서비스가 시작할 때, 자기 설정을 직접 들고 있는 게 아니라 Config Server에 물어본다. "나는 order-service이고 운영 환경인데, 내 설정 줘."
이름(order-service) + 환경(prod) 전달
order-service-prod.yml 등을 읽음
서비스는 이 값으로 빈을 구성
받은 설정으로 DB 연결 등 완료
- 1이름과 환경으로 설정을 특정
서비스는 자기 이름과 프로파일(prod/dev)을 들고 요청한다.
Config Server는
{이름}-{환경}.yml규칙으로 맞는 파일을 찾는다. 공통 값은application.yml에 두고, 서비스별·환경별 값으로 덮어쓰는 식으로 계층을 쌓는다. - 2Git 저장소에서 읽어 응답
Config Server의 백엔드는 보통 Git 저장소다.
설정이 Git에 있으니 변경은 커밋으로 남고, 리뷰·되돌리기가 코드와 동일하게 된다. 브랜치로 환경을 나누거나 특정 커밋으로 고정할 수도 있다.
- 3받은 값으로 서비스를 구성
서비스는 이 설정으로 DB 연결·기능 플래그 등을 세팅한다.
중요한 건 설정이 서비스 코드/이미지 밖에 있다는 점이다. 같은 이미지를 dev·prod 어디에 올려도, 받아오는 설정만 달라 동작이 갈린다.
3. 부팅 후에 값이 바뀌면? — 갱신 문제
설정은 부팅할 때만 필요한 게 아니다. 운영 중에 "기능 플래그를 켜고 싶다", "외부 API 주소가 바뀌었다" 같은 일이 생긴다. 문제는, 부팅 때 한 번 받아온 값은 서비스 메모리에 굳어 있어서 Git을 고쳐도 이미 떠 있는 서비스는 모른다는 점이다.
하나는 각 서비스의 /refresh 를 호출해 설정을 다시 읽게 하는
방식. 서비스가 많으면 일일이 부르기 번거롭다. 그래서 메시지 브로커
(Kafka·RabbitMQ)에 연결해 "설정 바뀜" 이벤트를 한 번 쏘면 모든
서비스가 동시에 갱신되는 방식(Spring Cloud Bus)을 함께 쓴다. 한 번의
신호로 전체가 새 값을 집어 든다.
DB 커넥션 풀처럼 부팅 때 한 번 만들어지는 자원은, 설정만 새로 읽는다고 즉시 바뀌지 않는다. 갱신으로 안전하게 바꿀 수 있는 값 (플래그·임계치 등)과, 재시작이 필요한 값을 구분해야 한다. "중앙화했으니 뭐든 실시간으로 바뀐다"는 오해를 경계하자.
4. 민감한 값은 평문으로 두지 않는다
설정을 Git에 둔다는 건 편리하지만, DB 비밀번호·API 키 같은 비밀을 평문으로 저장소에 올린다는 위험과 짝을 이룬다. 저장소가 유출되면 그대로 다 새어 나간다.
- 1암호화해서 저장
민감한 값은 암호문으로 두고, 받을 때 복호화한다.
Config Server는 값을
{cipher}...형태의 암호문으로 저장하게 해주고, 서비스에 내려줄 때 복호화한다. 저장소에는 암호문만 남으니 유출돼도 곧장 비밀이 새지 않는다. - 2전송 구간 보호와 접근 제어
Config Server 자체도 인증·HTTPS로 보호한다.
설정을 중앙화하면 그 중앙이 새 공격 표적이 된다. Config Server에 접근 인증을 걸고 전송을 암호화해, "한 곳을 뚫으면 전부 털리는" 구조가 되지 않게 한다.
정리하면 Config Server의 목표는 설정을 코드 밖, 한 곳에, 이력과 함께 두고 각 서비스에 일관되게 뿌리는 것이다. 흩어짐을 없애 재배포 지옥을 끊고, Git으로 추적을 얻고, 암호화로 비밀을 지킨다. 다만 갱신 전파와 중앙화된 표적이라는 새 숙제를 같이 떠안는다는 걸 잊지 말자.
한 장 요약
- 1문제
설정이 서비스마다 흩어져 값 하나 바꾸는 데 전부 재배포해야 한다.
- 2중앙화
설정을 Git 등 한 곳에 모으고 Config Server가 각 서비스에 뿌린다.
- 3부팅 흐름
서비스는 시작할 때 이름·환경으로 자기 설정을 받아와 구성된다.
- 4갱신
운영 중 변경은 /refresh나 메시지 버스로 전파 — 단 모든 값이 실시간은 아니다.
- 5보안
민감한 값은 암호화해 저장하고, 중앙 서버 자체도 인증·HTTPS로 보호.
- 6본질
설정을 코드 밖·한 곳·이력과 함께 두어 일관성을 얻는 도구.