[Spring] Spring Cloud Config는 어떻게 동작하지?
Background
사내 MSA 서버에 들어갈 외부 설정값들은 Spring cloud config 서버에서 중앙 관리하고 있다. 그런데 config 서버가 꽤나 오랫동안 존재했던지라, properties로 관리되는 설정값이 대다수였다. 그런데 YML 파일로 관리했을 때의 이점이 더 많기 때문에, 해당 설정값을 만질 일이 있을 때마다 Properties를 YML로 바꾸자는 것이 사내 컨벤션이었다.
이때 잠깐, 왜 properties보다 YML로 관리하는 게 더 좋을까? 이는 이전 글에서도 언급한 내용이지만 간단히 짚고 넘어가면
- 계층 구조 → 중복 코드를 줄일 수 있음.
- 가독성이 좋음(중복코드가 줄어들고 계층이 나뉘니까)
- 하나의 YML 파일에서 여러 profile을 관리할 수 있음
- 기존 properties의 경우, profile 별로 파일을 따로 만들었어야 했다.
dev: application-dev.properties
//application-dev.properties
spring.datasource.hikari.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.hikari.jdbc-url=jdbc:mariadb://localhost:3306/testdb
spring.datasource.hikari.username=root spring.datasource.hikari.password=root
spring.datasource.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.datasource.jpa.properties.hibernate.format_sql=true spring.datasource.jpa.show-sql=true
spring.datasource.jpa.generate-ddl=true
stage: application-stage.properties
//application-dev.properties
spring.datasource.hikari.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.hikari.jdbc-url=jdbc:mariadb://localhost:3306/testdb
spring.datasource.hikari.username=root spring.datasource.hikari.password=root
spring.datasource.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.datasource.jpa.properties.hibernate.format_sql=true spring.datasource.jpa.show-sql=true
spring.datasource.jpa.generate-ddl=true
하지만 YML에서는 하나의 파일 안에 다 때려넣기가 가능해서 관리가 수월하다. 심지어 다른 profile 간에 공통 설정값이 있다면 그만큼 중복 코드도 줄일 수 있어서 좋다.
application.yml
→ 내부에 dev/stage/prod 전부 관리
# application.yml
spring:
profiles: dev, stage, prod # -> 하나의 파일에서 모두 관리
datasource:
hikari:
driver-class-name: org.mariadb.jdbc.Driver
jdbc-url: jdbc:mariadb://localhost:3306/testdb
username: root
password: root
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
format_sql: true
show-sql: true
generate-ddl: true
---
그런 상황인데, 이번에 주어진 과제는 하나의 마이크로서버에 들어가는 모든 properties를 전부 YML로 바꾸는 것. 부분만 바꾸는 게 아니라 통으로 들어내고 갈아끼우는 것이다보니 config 서버와 클라이언트가 전체적으로 어떻게 동작하는지를 이해할 필요가 있었다.
Spring cloud config: How it works?
Spring cloud config는 분산 시스템에서의 외부 설정값을 클라이언트 사이드 / 서버 사이드 각각에서 관리하기 편하게 지원하는 스프링 기반 서버이다. config server를 이용하면 서로 다른 MSA 각각의 환경설정 변수를 한 곳에서 모아서 관리할 수 있다는 이점이 있다. 찾아보니 해당 config 서버의 컨셉은 스프링에서 제공하는 환경설정 인터페이스인 Environment와 PropertySource를 추상화한 개념인지라, 다른 언어로 돌아가는 애플리케이션에서도 사용 가능하나 스프링 기반 애플리케이션과의 호환성이 좋다고 한다.
이렇게 config 서버를 사용하면 애플리케이션이 배포 파이프라인을 통해 dev → test → prod로 옮겨갈 때 해당 환경 간의 설정값을 관리하고 앱 실행에 필요한 것들이 잘 갖춰졌는지 쉽게 확인할 수 있다.
config 서버 내 스토리지 구현은 git을 사용하는데, 아래에서 언급되겠지만 구성을 브랜치별로 동적으로 변경할 수 있어 유연하게 설정값을 갈아끼울 수 있다는 이점이 있다.
cloud config를 도식화하면 위와 같다. 크게 세 가지 파트로 구성된다.
- Cloud config client: 보통은 분산 환경에서 해당 config 아키텍쳐를 이용할 테니, MSA 서버가 client 역할을 할 것이다. 각각의 서버는 config 서버에 요청해 환경변수를 받아온다.
- Cloud config server: 우리가 이번 주제에서 다루는 config 서버로, 서로 다른 클라이언트에 대한 모든 설정값을 하나의 중앙 서버에서 관리한다. 이때, config 서버는 클라이언트의 HTTP 요청을 받고 그에 맞는 설정값을 반환해주는 역할만 한다. 실제로 전달해주고자 하는 설정값은 따로 관리한다.
- Environment Repository(Git): config 서버가 환경변수를 전달하려면 해당 환경변수를 저장하는 스토리지가 있어야 한다. 그런데 config 서버의 특징은, 이를 서버가 자체적으로 관리하지 않는다는 점이다. 백엔드 스토리지로 Git을 이용함으로써 구성값을 유연하게 관리할 수 있다. 이때, git은 로컬/원격 둘다 가능한데, 위와 같이 다양한 서버에 대해 고가용성으로 대응하기 위해서는 원격 리포지토리로 관리하고 있다.
(To be continue)
- Config 클라이언트 요청 시 어떻게 config 서버가 꺼내주니?
- ex). cms.yml 파일 어떻게 꺼내주는데?
- 클라이언트와 서버가 잘 붙었는지 확인하는 방법
- UP 체크하는 것도 있고
- 내가 한 것처럼 따로 브랜치 파서 잘 붙었는지 체크