Cloud Config 란 서비스의 환경설정을 Config Server-Client 를 통해 관리할 수 있도록 제공한다.Config Server 를 이용해 중앙 집중적으로 관리할 수 있다.Git Repository 기반으로 관리되는 Config Server 의 설정 값이 변경되면 Config Server 를 바라보고 있는 Config Client 들에게 변경사항을 전파하여 설정 값을 갱신할 수 있다.간단히 말해, 서버의 빌드/배포 없이 운영중인 서비스의 환경설정을 변경할 수 있다.
전체 코드는 GitHub 에서 확인할 수 있습니다.
환경설정 프로퍼티는 아래와 같은 규약을 따른다.
{label} : 옵션 값으로 Git branch 이름을 뜻한다.{application} : Config Client 애플리케이션의 이름을 뜻한다. spring.application.name{profile} : Config Client 의 active profile 을 뜻한다. spring.profiles.active/{application}/{profile}[/{label}] 
/{application}-{profile}.yml 
/{label}/{application}-{profile}.yml 
/{application}-{profile}.properties 
/{label}/{application}-{profile}.properties 
/{application}-{profile}.yml 규약에 따라 파일을 각각 만들어줬다.
# msa-dev.yml
application:
  message: "Message From <DEV> Git Repository"
  
# msa-st.yml
application:
  message: "Message From <ST> Git Repository"
Environment : Spring Boot 2.1.5, Gradle
Spring Initializer 로 프로젝트 생성시 web 과 config server 를 선택하거나 아래 의존성을 추가한다.
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.cloud:spring-cloud-config-server'
}
@EnableConfigServer  어노테이션을 달아주면 관련 설정을 자동으로 해준다.
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}
{Git Repo} 에는 자신의 Git Repository 경로를 설정한다.
# application.yml
server:
  port: 8888
spring:
  application:
    name: "config-server"
  cloud:
    config:
      server:
        git:
          uri: {Git Repo}
Environment : Spring Boot 2.1.5, Gradle
Spring Initializer 로 프로젝트 생성시 web 과 config client, actuator 를 선택하거나 아래 의존성을 추가한다.
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.cloud:spring-cloud-config-client'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
}
@ConfigurationProperties 어노테이션에는 앞서 .yml 의 프로퍼티 값을 설정한다.
@Component
@ConfigurationProperties("application")
@Getter @Setter
public class ConfigProperties {
    private String message;
}
앞서 설정한 ConfigProperties 빈을 주입 받아 프로퍼티 설정값을 잘 가져오는지 확인할 수 있는 API를 생성한다.
@RestController
@RequiredArgsConstructor // lombok
public class ConfigController {
    private final ConfigProperties configProperties;
    @GetMapping("/config")
    public ResponseEntity config() {
        return ResponseEntity.ok(configProperties.getMessage());
    }
}
Config Client 애플리케이션 이름과 바라볼 Config Server 의 주소를 설정한다. 설정 파일명은 bootstrap 이어야 한다.
# 앞서 설정한 {application}과 일치하도록 설정
spring:
  profiles:
    active: dev
  application:
    name: msa
# Config Server 주소 설정
---
spring:
  profiles: dev
  cloud:
    config:
      uri: http://localhost:8888
---
spring:
  profiles: st
  cloud:
    config:
      uri: http://localhost:8888
클라이언트를 실행시킨 후 아래와 같이 API를 호출할 수 있다.

active profile 에 따라 설정 값을 정상적으로 가져오는 것을 확인해보자.
active profile : dev
   GET http://127.0.0.1:8080/config
   
   HTTP/1.1 200 
   Content-Type: text/plain;charset=UTF-8
   Content-Length: 39
   Date: Thu, 30 May 2019 23:46:41 GMT
   
   Message From <DEV> Git Repository
   
   Response code: 200; Time: 168ms; Content length: 39 bytes
active profile : st
   GET http://127.0.0.1:8080/config
   
   HTTP/1.1 200 
   Content-Type: text/plain;charset=UTF-8
   Content-Length: 38
   Date: Thu, 30 May 2019 23:47:38 GMT
    
   Message From <ST> Git Repository
   
   Response code: 200; Time: 125ms; Content length: 38 bytes
active profile : real
msa-real.yml 이란 파일은 존재하지 않음
   GET http://127.0.0.1:8080/config
   
   HTTP/1.1 200 
   Content-Length: 0
   Date: Thu, 30 May 2019 23:44:33 GMT
    
   <Response body is empty>
    
   Response code: 200; Time: 131ms; Content length: 0 bytes
Config Client 가 Config Server 의 변경된 설정을 인지하기 위해서는 추가 설정이 필요하다.
Config Server 로 부터 갱신된 설정을 받아올 수 있는 URI(/actuator/refresh)를 노출하도록 Config Client 의 bootstrap.yml 에 아래 설정을 추가해준다.
management:
  endpoints:
    web:
      exposure:
        include: "refresh"
@RefreshScope 어노테이션은 설정 값이 변경되었을 때 Config Server 의 변경된 값을 갱신하기 위해 추가한다.
@Component
@RefreshScope
@ConfigurationProperties("application")
@Getter @Setter
public class ConfigProperties {
    private String message;
}
active profile : dev
refresh 유무를 확인하기 위해 Config Client 2대를 각각 다른 포트로 실행한다.
아래와 같이 각 VM Options 에 8081 포트와 8082 포트로 설정했다.

먼저 8081 포트로 실행한 클라이언트에서 호출하면 프로퍼티 값을 잘 가져온다.
   GET http://127.0.0.1:8081/config
   
   HTTP/1.1 200 
   Content-Type: text/plain;charset=UTF-8
   Content-Length: 39
   Date: Thu, 30 May 2019 23:46:41 GMT
    
   Message From <DEV> Git Repository
    
   Response code: 200; Time: 168ms; Content length: 39 bytes
Git Repository 에 있는 msa-dev.yml 의 프로퍼티 값을 변경해주고 refresh 요청을 한다.
   POST http://127.0.0.1:8081/actuator/refresh
    
   HTTP/1.1 200 
   Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8
   Transfer-Encoding: chunked
   Date: Sun, 02 Jun 2019 23:39:04 GMT
    
   [
       "config.client.version",
       "application.message"
   ]
    
   Response code: 200; Time: 1146ms; Content length: 2 bytes
application.message 의 변경이 감지되었으니 변경된 값을 가져오는지 확인해보자.
   GET http://127.0.0.1:8081/config
    
   HTTP/1.1 200 
   Content-Type: text/plain;charset=UTF-8
   Content-Length: 56
   Date: Sun, 02 Jun 2019 23:40:15 GMT
    
   Message From <DEV> Git Repository - refresh test -
    
   Response code: 200; Time: 21ms; Content length: 56 bytes
다음은 8082 포트로 실행한 클라이언트의 값을 확인해보자.
   GET http://127.0.0.1:8082/config
   
   HTTP/1.1 200 
   Content-Type: text/plain;charset=UTF-8
   Content-Length: 39
   Date: Thu, 30 May 2019 23:46:41 GMT
   
   Message From <DEV> Git Repository
   
   Response code: 200; Time: 168ms; Content length: 39 bytes
8081 포트로 실행한 클라이언트에서만 refresh 를 호출하였으므로 8082 포트로 실행한 클라이언트에서는 여전히 갱신되지 않은 값을 가져온다.
Config Client 가 여럿으로 구성된 경우에는 각 클라이언트마다 refresh 호출해줘야 하는 번거로움이 있다.
Spring Cloud Bus 를 이용하여 구현하면 message broker 나 webhook 을 통해 변경을 전파하여 자동으로 갱신시킬 수 있다.