스프링 - Spring Cloud Config 예제

스프링 - Spring Cloud Config 예제

개요

  • Spring Cloud Config
  • 스프링 설정파일을 외부로 분리할 수 있는 스프링 클라우드 Config 에 대한 핸즈온 (Hands-On) 예제


Spring Cloud Config 란

아래는 Spring Cloud Config 에 들어가면 나오는 설명 요약이다.

  • Spring Cloud Config 는 분산 시스템에서 설정파일을 외부로 분리하는 것을 지원한다.
  • Spring Cloud Config 를 사용하면 외부 속성을 중앙에서 관리할 수 있다.
  • 스프링 애플리케이션은 물론, 다양한 애플리케이션에서 동일하게 설정파일을 사용할 수 있다.
  • 설정파일 구성의 기본은 git 을 사용한다.

필자의 수준으로 요약하면 스프링 프로젝트의 설정파일을 외부로 분리하여 다양한 환경에서 사용하도록 할 수 있고, 설정이 변경되었을 때 애플리케이션의 재배포 없이 적용가능하다 정도로 받아들였다.

MSA 에서는 수많은 애플리케이션들이 생겨나게 되는데, 수많은 애플리케이션들의 설정파일을 한곳에서 중앙집중관리를 할 수 있도록 해주는 것이 장점인 것 같다.


TL;DR (Too Long; Didn’t Read)

바로 예제 돌려보고 시작하길 원하는 사람은 아래 Repository 를 참고하면 된다.


잡생각
MSA(Micro Service Architecture: 마이크로 서비스 아키텍처) 
공부중에 Spring Cloud Netflix 와 Spring Cloud Config  알게됨

MSA 뭐 있나? 그냥 쪼개면 되는거아냐? 하고 무식한 생각을 했던 자신에 대한 반성과 함께...
참 무지하다 갈길이 멀다... 
Spring Cloud Netflix 도 하나씩 사용해봐야겠다.

애플리케이션을 잘게 쪼개면서 생기는 다양한 문제들 을 해결하기 위한 도구로
(로그관리, 모니터링, 부하분산, 써킷브레이킹, 상태파악 등등 갈길이 멀다..) 
자바진영에서는 Spring Cloud Netflix 를 많이 사용하는 것 같다.

MSA 를 공부하다보니... 최근(?)에 화두가 되는 
* CI / CD / Docker / Kubernetes
* ELK(ElasticSearch Logstash Kibana)
* TDD
* Spring Cloud / Spring Boot 
등등 다양한 기술들이 왜 그렇게 화두가 되는지 이제 아주 아주 아~~주 조금 알 것 같다. 


살펴볼 내용

총 3가지를 만들 것이다.

  1. Github Repository 에 설정파일 저장
  2. Spring Cloud Config Server (이하 Config Server) - 설정파일 배달부
  3. Spring Cloud Config Client (이하 Config Client) - 설정파일 사용자

클라이언트 앱이 기동할 때 사용하는 설정파일은 Config Server 에서 돌려준 설정파일을 사용할 것인데, Config Server 에서 돌려줄 설정파일이 Github Repository 에 세팅해 둔 설정파일이 되도록 할 것이다.


1. Github Repository 에 YAML 파일 저장

Github Repository 를 하나 파고 아래 두 파일을 만들어 저장한다. YAML 파일이름의 경우 ${ApplicationName}-${EnvironmentName}.yml 로 해주는 것이 디폴트이다. 왜 그렇게 하는지는 아래 3. Spring Cloud Config Client 세팅에서 설명한다.

yaboong-dev.yml
who:
  am:
    i: dev-yaboong
yaboong-live.yml
who:
  am:
    i: live-yaboong


2. Spring Cloud Config Server

2-1. Dependency 추가

클라이언트에게 설정파일에 대한 요청을 반환해 때, 앞서 Github Repository 에 만들어 둔 설정파일을 반환하는 서버를 만들 차례다. 스프링 부트 프로젝트를 하나 생성하고 dependency 를 아래와 같이 설정해준다.

dependencies {
    implementation('org.springframework.cloud:spring-cloud-config-server')
}


2-2. Spring Cloud Config Server 설정파일 설정

src/main/resources/application.yml 파일을 아래와 같이 설정해준다. 스프링 부트 프로젝트를 생성하면 자동으로 생성되는 application.properties 파일을 사용해도 되지만 YAML 파일이 타이핑을 덜 해도 돼서 좋다.

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/yaboong/spring-cloud-config-repository

uri 에는 1번 단계에서 생성한 Github Repository 의 uri 를 적어준다. 환경변수로 SPRING_PROFILES_ACTIVE 를 별도 지정하지 않았다면 디폴트 설정파일인 application.yml 을 읽어 실행하게 된다.

(참고로 SPRING_PROFILES_ACTIVE 를 test 로 지정하고 실행하면 스프링 부트 앱 기동시 application-test.yml 파일을 찾아 실행한다)


2-3. YourApplication.java

스프링 부트 프로젝트를 생성하면 자동 생성되는 main() 함수가 담긴 클래스에 아래와 같이 @EnableConfigServer 어노테이션을 추가해준다.

@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}


2-4. 실행

실행로그 중 Github 에 만들어둔 yaboong-dev.yml, yaboong-live.yml 파일을 가져와서 어딘가에 Add 해 두는 것을 볼 수 있다.

Adding property source: file:/var/folders/mz/7nk42g591rzd1v3x18ln5jpm0000gn/T/config-repo-8358493613395248430/yaboong-dev.yml
Adding property source: file:/var/folders/mz/7nk42g591rzd1v3x18ln5jpm0000gn/T/config-repo-8358493613395248430/yaboong-live.yml


2-5. 설정파일 가져오기

yaboong-dev.yml

$ curl -X GET http://localhost:8080/yaboong/dev
{
  "name": "yaboong",
  "profiles": [
    "dev"
  ],
  "label": null,
  "version": "ad12fd3da589a62c58c095b4c84a87345e8972e9",
  "state": null,
  "propertySources": [
    {
      "name": "https://github.com/yaboong/spring-cloud-config-repository/yaboong-dev.yml",
      "source": {
        "who.am.i": "dev-yaboong"
      }
    }
  ]
}

yaboong-live.yml

$ curl -X GET http://localhost:8080/yaboong/live
{
  "name": "yaboong",
  "profiles": [
    "live"
  ],
  "label": null,
  "version": "4d0b729cd29631d27f4ef68146c39beddd21572d",
  "state": null,
  "propertySources": [
    {
      "name": "https://github.com/yaboong/spring-cloud-config-repository/yaboong-live.yml",
      "source": {
        "who.am.i": "live-yaboong"
      }
    }
  ]
}

JSON 형태로 반환하기 때문에 다른 프레임워크나 언어로 된 애플리케이션에서도 가져다 쓸 수 있다. 이것으로 Github Repository 의 설정파일을 반환해주는 서버설정은 끝이다.


3. Spring Cloud Config Client

이제 설정파일을 Config Server 로부터 받아와서 애플리케이션을 빌드할 클라이언트를 만들차례다. Config Server 가 8080 포트를 사용중이므로 Config Client 는 8081 포트를 사용하도록 설정하겠다.

3-1. Dependency 추가
dependencies {
    implementation('org.springframework.boot:spring-boot-starter-web')
    implementation('org.springframework.cloud:spring-cloud-starter-config')
    implementation('org.springframework.boot:spring-boot-starter-actuator')
}

actuator 를 반드시 추가해주어야 한다.


3-2. Spring Cloud Config 클라이언트 설정파일 설정

서버의 경우 application.yml 만 사용했지만, 클라이언트의 경우 application.yml 이 아닌 다른 설정파일을 사용할 것이다. bootstrap.yml 파일의 경우 스프링부트 앱 기동시 application.yml 보다 먼저 로드되므로 src/main/resources/bootstrap.yml 파일의 설정정보를 아래와 같이 수정해준다.

server:
  port: 8081

spring:
  application:
    name: yaboong
  cloud:
    config:
      uri: http://localhost:8080

server.port 값은 8081 에 Config Client 를 띄울것이라는 설정이고, Spring Cloud Config Client 와는 전혀 무관한 설정이다. 그냥 Config Server 가 8080 포트를 사용중이므로 충돌을 피하기 위함이다.

spring.application.name 값은 1번 단계에서 설정파일의 이름을 ${ApplicationName}-${EnvironmentName}.yml 으로 하는 것이 디폴트라고 한 것과 상관있다.

$SPRING_PROFILES_ACTIVE 값을 dev 로 설정한 경우, 위 설정을 바탕으로한다면 http://localhost:8080/yaboong/dev 의 설정을 읽어와 애플리케이션을 실행하게 된다.

spring.application.name 값을 yaboong 이 아닌 yb 로 한다면, http://localhost:8080 에 떠있는 Config Server 가 바라보고 있는 Github Repository 에 yb-dev.yml 파일이 있어야 한다.


3-3. 설정파일을 내용을 동적으로 반영할 컨트롤러 작성

아래와 같이 컨트롤러를 하나 만들어 준다. Github Repository 에 만들어둔 설정파일에서 who.am.i 값을 읽어와 반환하는 Rest Controller 이다.

@RestController
@RefreshScope
public class ConfigClientController {

    @Value("${who.am.i}")
    private String identity;

    @GetMapping("/test")
    public String test() {
        return identity;
    }
}

포인트는 @RefreshScope 어노테이션이다. 이 어노테이션이 붙은 클래스에는 특정행동 수행시 변경된 설정파일의 설정이 애플리케이션의 재배포과정 없이 실시간으로 반영된다.


3-4. 설정파일 변경내용 반영을 위한 설정추가

Github Repository 의 설정파일을 변경하고 Push 하면 바로 설정이 반영되면 좋겠지만 그렇게 되지는 않는다. 직전 단계 (3-3) 에서 특정행동 수행시 라고 했는데, 설정파일이 변경되면 변경사항을 반영하기위해 Config Client 에 POST 요청을 하나 날려줘야 한다.

일단 아래와 같이 application.yml 파일을 설정해두고 애플리케이션을 실행시키고 어떻게 되는지 살펴보자.

management:
  endpoints:
    web:
      exposure:
        include: refresh

위와 같이 설정해두면 http://localhost:8081/actuator/refresh 로 POST 요청을 보내면 설정파일을 새로 읽어들여서 애플리케이션이 재기동된다.

일단 클라이언트앱을 실행시켜보자. 실행시킬 때 SPRING_PROFILES_ACTIVE 값을 live 로 주고 실행시켜보자. Github Repository 에 있는 yaboong-live.yml 설정파일을 읽어와 애플리케이션을 실행하게 될 것이다.

Intellij 에서 실행한다면, 우측상단의 Run 버튼 왼쪽의 YourApplication 을 클릭하고 Edit Configuration 으로 가서 Active profiles 값을 live 로 설정해주면 된다.

CLI 에서 실행한다면, build.gradle 파일을 아래와 같이 추가설정을 해주고 (환경변수로 지정해도 된다)

bootRun {
    systemProperties = System.properties
}

프로젝트 디렉토리로 가서 아래와 같이 실행시켜도 된다.

$ gradle bootRun -Dspring.profiles.active=live


3-5. 실행

실행로그 중 첫 세줄이 중요하다.

Fetching config from server at : http://localhost:8080
Located environment: name=yaboong, profiles=[live], label=null, version=4d0b729cd29631d27f4ef68146c39beddd21572d, state=null
Located property source: CompositePropertySource {name='configService', propertySources=[MapPropertySource {name='configClient'}, MapPropertySource {name='https://github.com/yaboong/spring-cloud-config-repository/yaboong-live.yml'}]}
  • Config Server 로 떠있는 http://localhost:8080 에서 설정을 가져온다.
  • 가져올때는 http://localhost:8080/yaboong/live 로 요청을 보내 가져왔을 것이다.
  • 실제로 가져온 파일은 https://github.com/yaboong/spring-cloud-config-repository/yaboong-live.yml 이다.

아래와 같이 /test 로 GET 요청을 보내면, Github Repository 에 있는 yaboong-live.yml 파일의 who.am.i 필드값을 반환하는 것을 확인할 수 있다. (좀 더 정확히 말하면 Config Server 에 캐시해둔 yaboong-live.yml 파일이 되겠다)

$ curl -X GET http://localhost:8081/test
live-yaboong


3-6. Github Repository 의 설정파일 변경

yaboong-live.yml 파일의 내용을 변경하고 클라이언트 애플리케이션에 반영되는 것을 보자.

파일 내용을 간단하게 아래와 같이 수정하고 push 한다.

yaboong-live.yml

who:
  am:
    i: live-yaboong, it's working!

이제 클라이언트 애플리케이션의 /actuator/refresh 로 POST 요청을 보내서 변경된 설정파일이 적용되도록 해보자.

$ curl -X POST http://localhost:8081/actuator/refresh

클라이언트 애플리케이션의 실행로그를 보고 있다면, POST 요청을 받자마자 설정파일을 Config Server 로부터 새로 받아와서 애플리케이션이 재시작 되는 것을 볼 수 있다. 변경된 설정의 경우 @RefreshScope 어노테이션이 적용되어 있는 클래스에만 적용된다.

이제 다시 /test 로 요청을 보내서 새로운 설정을 읽어왔는지 확인해보면

$ curl -X GET http://localhost:8081/test
live-yaboong, it's working!


이렇게 Spring Cloud Config 에 대한 헬로월드는 마무리… 신기하당


참고한 자료

Comments

Yaboong's Picture

Yaboong

오스카 쉰들러는 흔해빠진 기회주의자요 부패한 사업가였다. 그러나 거대한 악이 세상을 점령하는 것처럼 보일 때 그 악에 대항해서 사람의 생명을 구한 것은 귀족도 지식인도 종교인도 아닌 부패한 기회주의자 오스카 쉰들러였다.

Seoul, South Korea https://github.com/yaboong