본문 바로가기

Study/Java

Spring Boot ConfigurationMetaData 사용해 보기

반응형

Spring Boot Configuration MetaData 소개

https://docs.spring.io/spring-boot/specification/configuration-metadata/index.html

Spring Boot는 java에서 @ConfigurationProperties 를 선언한 properties에 대한 정보를 /META-INF/spring-configuration-metadata.json 파일로 Configuration Metadata를 제공한다.

spring-boot-autoconfigure 에 있는 /META-INF/spring-configuration-metadata.json 파일을 보면 대략 다음과 같다.

{
  "groups": [
    {
      "name": "server",
      "type": "org.springframework.boot.autoconfigure.web.ServerProperties",
      "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
    },
    {
      "name": "server.compression",
      "type": "org.springframework.boot.web.server.Compression",
      "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties",
      "sourceMethod": "getCompression()"
    },
    // .. 이하 생략
}

Configuration MetaData는 보통 IDE를 사용하면 properties 파일을 관련 editor (Eclipse의 경우 Generic Editor - Spring Properties ) 에서 작성할 때 자동 완성을 안내해 주거나 deprecated 된 property에 대해 안내를 해주거나 metadata가 존재하지 않는 property에 대해 warning을 보여주는 등의 용도로 사용된다.

프로젝트에서 Configuration MetaData 만들고 사용하기

Configuration MetaData는 프로젝트에서 선언한 @ConfigurationProperties 에 대해서도 생성할 수 있다.

dependency를 다음처럼 추가하면 된다.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

이렇게 추가한 후 프로젝트 내에서 다음처럼 @ConfigurationProperties를 사용하면

@Data
@ConfigurationProperties(prefix = "test.prop")
public class TestProperties {

    /**
     * someKey1에 대한 설명 주석
     */
    private String someKey1 = "기본값이 있으면 이것도 안내해줌";

    /**
     * someKey2에 대한 설명 주석
     */
    private long someKey2;

}

해당 프로젝트의 /target/classes/META-INF/spring-configuration-metadata.json 위치에 다음과 같이 생성된 것을 확인할 수 있다.

{
  "groups": [
    {
      "name": "test.prop",
      "type": "net.luversof.web.config.TestProperties",
      "sourceType": "net.luversof.web.config.TestProperties"
    }
  ],
  "properties": [
    {
      "name": "test.prop.some-key1",
      "type": "java.lang.String",
      "description": "someKey1에 대한 설명 주석",
      "sourceType": "net.luversof.web.config.TestProperties"
    },
    {
      "name": "test.prop.some-key2",
      "type": "java.lang.Long",
      "description": "someKey2에 대한 설명 주석",
      "sourceType": "net.luversof.web.config.TestProperties"
    }
  ],
  "hints": []
}

에디터에서 해당 정보에 대해 자동 완성이 지원되는 것을 확인할 수 있다.

또한 @Deprecated 를 선언하면

@Data
@ConfigurationProperties(prefix = "test.prop")
public class TestProperties {

    /**
     * someKey1에 대한 설명 주석
     */
    @Deprecated
    private String someKey1 = "기본값이 있으면 이것도 안내해줌";

    /**
     * someKey2에 대한 설명 주석
     */
    private long someKey2;

}

해당 정보도 전달해 준다.

{
  "groups": [
    {
      "name": "test.prop",
      "type": "net.luversof.web.config.TestProperties",
      "sourceType": "net.luversof.web.config.TestProperties"
    }
  ],
  "properties": [
    {
      "name": "test.prop.some-key1",
      "type": "java.lang.String",
      "description": "someKey1에 대한 설명 주석",
      "sourceType": "net.luversof.web.config.TestProperties"
      "deprecated": true,
      "deprecation": {}
    },
    {
      "name": "test.prop.some-key2",
      "type": "java.lang.Long",
      "description": "someKey2에 대한 설명 주석",
      "sourceType": "net.luversof.web.config.TestProperties"
    }
  ],
  "hints": []
}

Editor에서 노란 줄로 warning이 생기고 설명에서 Deprecated 안내를 확인할 수 있다.

Configuration MetaData 좀 더 알아보기

https://docs.spring.io/spring-boot/specification/configuration-metadata/format.html

spring-configuration-metadata.json 의 json은 groups, properties, hints 3가지 항목으로 이루어져 있다.

{
    "groups" : [],
    "properties" : [],
    "hints" : []
}

spring 문서에서 안내하는 예제는 다음과 같다.

{"groups": [
    {
        "name": "server",
        "type": "org.springframework.boot.autoconfigure.web.ServerProperties",
        "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
    },
    {
        "name": "spring.jpa.hibernate",
        "type": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate",
        "sourceType": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties",
        "sourceMethod": "getHibernate()"
    }
    ...
],"properties": [
    {
        "name": "server.port",
        "type": "java.lang.Integer",
        "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
    },
    {
        "name": "server.address",
        "type": "java.net.InetAddress",
        "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
    },
    {
          "name": "spring.jpa.hibernate.ddl-auto",
          "type": "java.lang.String",
          "description": "DDL mode. This is actually a shortcut for the \"hibernate.hbm2ddl.auto\" property.",
          "sourceType": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate"
    }
    ...
],"hints": [
    {
        "name": "spring.jpa.hibernate.ddl-auto",
        "values": [
            {
                "value": "none",
                "description": "Disable DDL handling."
            },
            {
                "value": "validate",
                "description": "Validate the schema, make no changes to the database."
            },
            {
                "value": "update",
                "description": "Update the schema if necessary."
            },
            {
                "value": "create",
                "description": "Create the schema and destroy previous data."
            },
            {
                "value": "create-drop",
                "description": "Create and then destroy the schema at the end of the session."
            }
        ]
    }
]}

group 은 대상 @ConfigurationProperties 대상에 대한 정보이고
properties@ConfigurationProperties 대상에 설정된 properties 값 각각에 대한 정보이다.
hints 는 값에 대한 정보이다.

additional-spring-configuration-metadata.json 사용하기

spring-boot-configuration-processor 가 프로젝트에 현재 구성된 @ConfigurationProperties 를 기준으로 spring-configuration-metadata.json 을 만들어 주지만 모든 정보를 작성해 주지는 못한다.

따라서 추가적인 정보가 별도로 필요한 경우가 있다.

그러한 정보를 /META-INF/additional-spring-configuration-metadata.json 에 작성하면 /META-INF/additional-spring-configuration-metadata.json 의 정보와 함께 병합되어 최종 빌드 된 additional-spring-configuration-metadata.json (로컬 개발에선 target/classes/META-INF/additional-spring-configuration-metadata.json , jar 빌드 결과물은 /META-INF/additional-spring-configuration-metadata.json ) 에 추가되게 된다.

추가 정보 작성이 필요한 경우는 다음과 같다.

  • @Deprecated 된 property가 완전히 제거되었을 때 제거된 값을 변경해서 사용하라는 안내를 기존 properties 값을 설정한 경우 전달
  • 값에 대한 hint 정보 제공
    • 값에 대한 목록 제공
    • provider를 통한 정보 제공
      • class-reference : class 참조
      • handle-as : 개별 제공

삭제된 property 안내

예를 들어 앞서 예제에 대해 라이브러리 버전이 올라가면서 이전 버전에서 사용되던 값이 완전히 제거되었다고 가정하고 해당 값을 아래처럼 additional-spring-configuration-metadata.json 에 작성을 하면

{
    "groups": [],
    "properties": [
        {
            "name": "test.prop.some-key0",
            "deprecated": true,
            "deprecation": {
                "reason": "이 값은 더 이상 안씀",
                "level": "error"
            }
        }
    ],
    "hints": []
}

IDE에서는 properties에서 해당 값에 대해 warning을 표시하여 알려주게 된다.

만약 해당 property가 다른 proeprty로 대체되었다면 해당 내용에 대해서도 안내해 줄 수 있다.

Spring Boot에 현재 버전에서 아래 설정이 spring-boot-autoconfigure/META-INF/additional-spring-configuration-metadata.json 에 있고

{
    "name": "server.tomcat.max-http-post-size",
    "type": "org.springframework.util.unit.DataSize",
    "deprecation": {
        "replacement": "server.tomcat.max-http-form-post-size",
        "level": "error"
}

해당 값을 사용하고 있다면 warning이 발생하고 교체해야 할 값에 대해 안내해 준다.

 

hint를 통한 값에 대한 정보 사용하기

property 속성에 대한 자동 완성과 안내를 properties 에서 하고 있지만 어떤 값을 사용해야 하는지 가이드가 필요한 경우 hints 항목을 additional-spring-configuration-metadata.json 에 작성해 주면 된다.
(properties값처럼 자동으로 주석을 통해 만들어주지는 않음)

values를 사용한 값 열거

대략 다음과 같이 작성을 하면

{
    "groups": [],
    "properties": [],
    "hints": [
        {
            "name": "test.prop.some-key1",
            "values": [
                {
                    "value": "VALUE_AAA",
                    "description": "AAA 값 설명"
                },
                {
                    "value": "VALUE_BBB",
                    "description": "BBB 값 설명"
                }
            ]
        }
    ]
}

값 입력 부분에서 선택할 수 있게 자동 완성 된다.
STS 기준으로는 '=' 뒤에 커서가 위치했을 때 ctrl + space를 사용하면 확인할 수 있다.


(위 항목 중 descriptoin 은 굳이 작성하지 않아도 되는 optional 값임)

provider를 사용한 값 열거 (class-reference 사용 )

안내해야 할 값이 만약 특정 class의 상속 값인 경우 provider를 사용할 수 있다.

앞서 예제 property 중 class가 다음과 같이 추가되어 있고

@ConfigurationProperties(prefix = "test.prop")
public class TestProperties {

    /**
     * someKey1에 대한 설명
     */
    private String someKey1 = "기본값이 있으면 이것도 안내해줌";

    /**
     * someKey2에 대한 설명
     */
    private long someKey2 = 312;


    /**
     * 객체를 사용하는 경우 설명
     */
    private BlueskyProperties blueskyProperties;

}

해당 property에 대한 값을 다음과 같이 additional-spring-configuration-metadat.json 에 정의해 주면

{
    "groups": [],
    "properties": [],
    "hints": [
        {
            "name": "test.prop.bluesky-properties",
            "providers": [
                {
                    "name": "class-reference",
                    "parameters": {
                        "target": "io.github.luversof.boot.core.BlueskyProperties"
                    }
                }
            ]
        }
    ]
}

어떤 class를 추가하면 되는지 자동 완성으로 값을 제공해 준다.

 

provider를 사용한 값 열거 (handle-as 사용)

class-reference 외에도 handle-as 도 있지만 이 provider의 경우 IDE에서 해당 경우에 대해 제공하는 듯하다.
(vscode의 경우는 https://github.com/spring-projects/spring-tools/blob/main/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/types/TypeUtil.java#L679 와 같이 정의한 거 같은데 STS에서는 어떤 식으로 정의하였는지 찾지 못하였다.)

Locale이나 Charset도 이를 통해 값을 안내하고 있지만 사용자가 custom handle-as provider를 따로 정의해서 사용할 수 있는지 여부는 찾지 못하였다.
(IDE 지원 기능이라 아마 불가능할 듯싶다.)

앞서 소개했던 hintsvaluesprovider 는 혼용하여 사용할 수도 있다.

spring-boot-properties-migrator 로 report log 확인하기

spring boot가 spring-configuration-metadata.json 를 제공함으로써 값의 변경, 삭제에 대해 안내해주고 있지만 일일이 모든 properties파일을 열어 property의 warning을 확인하기는 번거롭다.

spring-boot-properties-migrator 를 사용하면 서버 startup report에 교체될 Spring Boot의 property 들을 report log로 안내해 준다.

내 프로젝트의 spring-configuration-metadata.json 를 migrator report log에 같이 출력하는 방법은 이전에 작성한 글을 참조하면 된다.

2024.06.16 - [Study/Java] - spring-boot-properties-migrator로 custom property report 하기

 

반응형