[Spring Boot Core] 2.1. Externalized Configuration 개요와 JSON Application Properties 설정하기

2024. 11. 3. 17:11Spring/Basic

반응형
  1. 구성설정 외부화 개요
    1. 예제
  2. command line 프로퍼티 액세스
  3. JSON Application properties
    1. 예제 코드
    2. JSON Application Properties 설정하기
    3. 테스트

1. 구성설정 외부화 개요

Spring Boot 를 이용하면, configuration을 외부화하여 여러 환경에서 동일한 코드를 활용하여 애플리케이션을 실행시킬 수 있습니다.

Java Config 파일, YAML 파일, 환경변수 및 명령어 인수 등을 통해 다양한 외부 구성 소스를 활용할 수 있습니다.

Spring 에서는 아래 3가지 방식으로 값을 주입합니다.

  • @Value 애너테이션을 이용하여 Bean에 직접 주입
  • Spring 의 환경 추상화를 통한 접근
  • @ConfigurationProperties 로 객체에 바인딩하여 활용

Spring Boot는 값을 합리적으로 재정의할 수 있도록 설계되어있는 PropertySource 순서를 사용합니다.
Spring Boot에서는 여러방식으로 환경변수를 주입할 수 있는데, 이 후에 불려진 소스는 환경변수를 오버라이딩합니다.

프로퍼티는 다음과 같은 순서로 읽습니다.

  1. 기본 프로퍼티
    • SpringApplication.setDefaultProperties 메서드로 프로퍼티를 변경할 수 있습니다.
  2. @Configuration 클래스에 설정하는 @PropertySource 애너테이션
    • 이 프로퍼티 소스는 애플리케이션 컨텍스트를 새로 고칠 때 환경에 추가되는 값입니다.
    • 따라서, logging.* 이나 spring.main.* 같은 속성은 여기에 설정하면 동작되지 않습니다.
  3. 구성 데이터
    • application.yml 나 application.properties 와 같은 파일
  4. RandomValuePropertySource
    • random.* 프로퍼티 값만을 가지고 있는 프로퍼티 소스입니다.
  5. OS 환경 변수
  6. Java 시스템 프로퍼티
    • System.getProperties() 로 조회할 수 있습니다.
  7. JNDI 속성
    • java:comp/env
    • 애플리케이션이 서블릿 컨테이너나 애플리케이션 서버에서 실행되는 경우 사용할 수 있습니다.
  8. ServletContext 초기화 파라미터
  9. ServletConfig 초기화 파라미터
  10. SPRING_APPLICATION_JSON 프로퍼티
    • 환경변수나 시스템 속성에 포함된 인라인 JSON
  11. command line 인수
  12. 테스트에 사용되는 properties 속성
    • @SpringBootTest 나 애플리케이션의 특정 부분 테스트에 활용합니다
  13. 테스트에서 사용되는 @DynamicPropertySource
  14. 테스트에서 사용되는 @TestPropertySource
  15. DevTools 전역 프로퍼티
    • devtools가 활성화 되어있는 상태에만 활성화 됨
    • $HOME/.config/spring-boot 디렉토리 하위에 있는 전역 프로퍼티

config 데이터 파일은 다음 순서에 따라 고려 됩니다.

참고로, .properties, YAML 파일 모두 동일하게 지원되며, 아래에서는 application.yml 파일 하나로 설명하도록 하겠습니다.

  1. 패키징된 jar 내에 있는 애플리케이션 프로퍼티
    • application.yml
  2. 패키징된 jar 내에 있는 프로필별 애플리케이션 프로퍼티
    • application-{profile}.yml
  3. 패키징된 jar 밖에 있는 애플리케이션 프로퍼티
    • application.yml
  4. 패키징된 jar 밖에 있는 프로필별 애플리케이션 프로퍼티
    • application-{profile}.yml

Note

구성파일은 .yml(그 외의 YAML 변형파일 모두) 나 .properties 모두 지원하지만,
하나의 프로젝트 내에 동일한 형식을 구성하는 것이 관리면에서 권장합니다.

만일 같은 위치에 두가지 형식이 모두 있을 경우에는 .properties 파일을 더 우선합니다.

Note

환경변수를 사용할때, OS 에서 마침표로 구분된 환경변수명을 허용하지 않는 경우가 많습니다.
이 경우에는 마침표를 _로 대체하여 사용하 ㄹ수 있습니다.
예를들어, spring.config.name 프로퍼티를 환경변수로 설정하고 싶다면 SPRING_CONFIG_NAME 이라는 이름으로 사용 가능합니다.

참고: Binding From Environment Variables


1.1. 예제

불려지는 순서에 따라 프로퍼티값이 override 되는 것을 확인하기 위해 아래 예제를 살펴봅시다.

1.1.1. 예제 1

yml 데이터 파일에 아래와 같이 구성 설정을 할 경우,

name: jini

아래 api를 호출해보면, 프로퍼티 파일에 설정한 구성 값이 잘 출력되는 것을 확인할 수 있을 것입니다.

@RequiredArgsConstructor
@RequestMapping("/test")
@RestController
class TestController {

    private final AppConfig appConfig;

    @GetMapping
    public String hello() {
        return "name: " + appConfig.getName();
    }
}
http :8080/test
HTTP/1.1 200
Connection: keep-alive
Content-Length: 10
Content-Type: text/plain;charset=UTF-8
Date: Fri, 01 Nov 2024 10:25:50 GMT
Keep-Alive: timeout=60

name: jini

1.1.2. 예제 2

command line 인자로 값을 설정해주면, 기존에 패키징된 jar 내의 application.yml 파일 설정을 override 할 수 있습니다.
아래와 같이 command line 인자로 name 값을 정의해주면 해당 값이 덮어써지는 것을 확인할 수 있습니다.

java -jar spring-boot-0.0.1.jar --name="lily"
http :8080/ttt
HTTP/1.1 200
Connection: keep-alive
Content-Length: 10
Content-Type: text/plain;charset=UTF-8
Date: Fri, 01 Nov 2024 10:26:45 GMT
Keep-Alive: timeout=60

name: lily

Tip

envconfigprops 엔드포인트를 활용하면 프로퍼티에 특정 값이 들어있는 이유를 확인하는데에 유용합니다.
프로덕션 준비를 하기 전에 이부분을 검토하여 예상치 못한 속성 값을 진단하는 것이 좋습니다.
참고: [Spring Boot Core] Actuator를 이용한 환경 변수 모아보기


2. command line 프로퍼티 액세스

기본적으로 SpringApplication 은 -- 으로 시작되는 command line 인자값을 프로퍼티로 변환해주고, 이 프로퍼티들을 Spring Environment에 추가합니다.

예시: java -jar demo.jar --server.port=18080

만약 command line 인자값들을 Spring Environment에 추가하고 싶지 않다면,
SpringApplication.setAddCommandLineProperties(false) 설정으로 비활성화 시킬 수 있습니다.


3. JSON Application properties

환경변수와 시스템 프로퍼티들을 사용할 때, 종종 이름 설정의 제한을 마주할 때가 있습니다.

Spring에서는 단일 JSON 구조로 프로퍼티 블록을 인코딩하여 사용하는 것을 허용합니다.


3.1. 예제 소스코드

my 라는 prefix 에 name 과 age 프로퍼티를 설정한다고 하고, 그 프로퍼티를 읽어들일 코드를 작성해봅시다.

@Data
@ToString
@ConfigurationProperties(prefix = "my")
@Component
public class MyProperties {
    private String name;
    private Integer age;
}
@RequiredArgsConstructor
@RequestMapping("/properties")
@RestController
class PropertiesController {

    private final MyProperties myProperties;

    @GetMapping("/my")
    public String my() {
        return myProperties.toString();
    }
}

3.2. JSON Application Properties 설정하기

JSON Application Properties를 설정하는 방법은 다양합니다.
아래 3가지 방법중 편한 방법대로 설정하면 됩니다.

3.2.1. command line 인자로 설정

java -jar spring-boot.jar \
 --spring.application.json="{\"my\":{\"name\":\"coco\", \"age\":22}}"

3.2.2. 시스템 프로퍼티로 설정

java -Dspring.application.json="{\"my\":{\"name\":\"coco\", \"age\":22}}" -jar spring-boot.jar

3.2.3. 환경변수로 설정

사용하고 있는 터미널의 환경변수 설정파일에 들어가서

vim ~/.zshrc

하단에 SPRING_APPLICATION_JSON 환경 export를 추가해줍니다.

export SPRING_APPLICATION_JSON="{\"my\":{\"name\":\"coco\", \"age\":22}}"

수정사항을 반영해주고

source ~/.zshrc

echo명령어로 환경변수가 잘 설정되어있는지 확인해줍니다.

echo $SPRING_APPLICATION_JSON
{"my":{"name":"coco2", "age":22}}

설정한 환경변수가 잘 조회된다면 애플리케이션을 실행해봅니다.

java -jar spring-boot.jar

3.3. 테스트

3.3.1. api 테스트

HTTPie 로 실행한 결과입니다.
사용하고 있는 http client 를 이용하여 api를 조회해봅시다.

http :8080/properties/my
HTTP/1.1 200
Connection: keep-alive
Content-Length: 31
Content-Type: text/plain;charset=UTF-8
Date: Sun, 03 Nov 2024 07:50:05 GMT
Keep-Alive: timeout=60

MyProperties(name=coco, age=22)

GET http://localhost:8080/actuator/env
...
{
  "name": "spring.application.json",
  "properties": {
    "my.name": {
      "value": "coco",
      "origin": "\"spring.application.json\" from property source \"commandLineArgs\""
    },
    "my.age": {
      "value": 22,
      "origin": "\"spring.application.json\" from property source \"commandLineArgs\""
    }
  }
},

3.3.2. env 테스트

env 테스트에 대한 상세한 설명은 아래 게시물을 참고해주세요.

[Spring Boot Core] Actuator를 이용한 환경 변수 모아보기


3.3.2.1. command line 인자 설정 결과

command line 인자로 설정한 후 Actuator env를 REST Client로 조회한 결과입니다.

GET http://localhost:8080/actuator/env
{
  "propertySources": [
    {
      "name": "commandLineArgs",
      "properties": {
        "spring.application.json": {
          "value": "{\"my\":{\"name\":\"coco\", \"age\":22}}"
        }
      }
    },
    {
      "name": "spring.application.json",
      "properties": {
        "my.name": {
          "value": "coco",
          "origin": "\"spring.application.json\" from property source \"commandLineArgs\""
        },
        "my.age": {
          "value": 22,
          "origin": "\"spring.application.json\" from property source \"commandLineArgs\""
        }
      }
    },
    ...
  ]
}

3.3.2.2. 환경변수 설정 결과

SPRING_APPLICATION_JSON 환경변수로 설정한 후 Actuator env를 REST Client로 조회한 결과입니다.

GET http://localhost:8080/actuator/env
{
  "propertySources": [
    {
      "name": "spring.application.json",
      "properties": {
        "my.name": {
          "value": "jini",
          "origin": "System Environment Property \"SPRING_APPLICATION_JSON\""
        },
        "my.age": {
          "value": 28,
          "origin": "System Environment Property \"SPRING_APPLICATION_JSON\""
        }
      }
    },
    {
      "name": "systemProperties",
      "properties": {
        ...
        "SPRING_APPLICATION_JSON": {
          "value": "{\"my\":{\"name\":\"jini\",\"age\":28}}",
          "origin": "System Environment Property \"SPRING_APPLICATION_JSON\""
        },
        ...
      }
    }
  ]
}

++

  • Externalized Configuration
728x90
반응형