오늘 알아볼 내용은 아직 릴리즈는 되지 않았지만 조만간 릴리즈될 Spring boot 2.0의 대해서 알아볼 예정이다. 아직 릴리즈전이라 바뀔 가능성이 있어 깊게는 살펴보지 않을 것이다.
또한 혹시나 기존(이전버전)과 동일한 기능을 마치 신기능처럼 이야기하거나 틀린이야기를 할 경우에는 피드백을 주길 바란다.

필자가 Spring boot를 좋아하는 이유중 하나도 Configuration Binding을 아주 손쉽게 해주기 때문이다. 하지만 기존의 버전과 2.0의 버전이 조금 달라졌다. 오늘은 그 내용을 살펴볼 예정이다.

ConfigurationProperties prefix

ConfigurationProperties 어노테이션은 아주 손쉽게 properties를 바인딩 해준다. 기존에는 underscore, camelcase를 prefix에서 지원했지만 이제는 그렇지 못하다. spring boot2.0 부터는 소문자kebab-case만 지원한다.

@ConfigurationProperties("foo_bar")
public class FooProperties {

  private String firstName;

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
}

만약 위와 같이 사용할 경우 아주 이쁜 에러를 내뱉는다.

***************************
APPLICATION FAILED TO START
***************************

Description:

Configuration property name 'foo_bar' is not valid:

    Invalid characters: '_'
    Bean: commandLineRunner
    Reason: Canonical names should be kebab-case ('-' separated), lowercase alpha-numeric characters and must start with a letter

Action:

Modify 'foo_bar' so that it conforms to the canonical names requirements.

camelcase 역시 마찬가지로 위와 같은 에러가 발생한다. 에러를 발생 시키지 않으려면 다음과 같이 작성해야 한다.

@ConfigurationProperties("foo-bar")
public class FooProperties {
  // ..
}

혹은

@ConfigurationProperties("foobar")
public class FooProperties {
  // ..
}

위와 같이 kebab-case나 혹은 소문자로 이어진 문장만 가능하다. 하지만 속성은 기존과 동일하게 모두다 가능하다.

foo-bar.firstname=wonwoo
foo-bar.first-name=wonwoo
foo-bar.first_name=wonwoo
foo-bar.firstName=wonwoo

Binder

RelaxedPropertyResolver 클래스는 환경정보를 가져오는데 매우 좋은 클래스였다. 하지만 RelaxedPropertyResolver 클래스는 더이상 사용 되지 않는다. 아니 삭제되었다. Deprecated 된것도 아니고 그냥 삭제 해버렸다. 그 대체할 수 있는 클래스는 Binder 클래스이다. 실제로 바인딩 하는 패키지도 거의 대부분 변경되었다.
기존에는 다음과 같이 RelaxedPropertyResolver 사용해서 손쉽게 properties 정보를 가져올 수 있었다.

RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
        environment, "foo-bar.");
String firstName = resolver.getProperty("firstName");
// ...

하지만 이제는 좀더 타입세이프하게 FooProperties를 바로 가져올 수 있다.

FooProperties fooProperties = Binder.get(environment)
        .bind("foo-bar", Bindable.of(FooProperties.class)).get();

List

기존의 버전에서 List를 사용할 때 다음과 같이 작성해도 문제는 없었다.

@ConfigurationProperties("foo-bar")
public class FooProperties {

  private List<String> url;

  public void setUrl(List<String> url) {
    this.url = url;
  }

  public List<String> getUrl() {
    return url;
  }
}

위와 같이 List를 사용할 때에는 배열의 인덱스와 상관없이 작성하는 것이 가능했다.

foo-test.url[0]=http://localhost:8080
foo-test.url[2]=http://localhost:8081

하지만 2.0 부터는 엔덱스는 순서대로 작성해야 한다. 만약 그렇지 않을 경우 예쁜 에러는 만날 것이다.

***************************
APPLICATION FAILED TO START
***************************

Description:

Binding to target [Bindable@11a7ba62 type = java.util.List<java.lang.String>, value = 'provided', annotations = array<Annotation>[[empty]]] failed:

    Property: foo-bar.url[2]
    Value: http://localhost:8081
    Origin: class path resource [application.properties]:7:16
    Reason: The elements [foo-bar.url[2]] were left unbound.

Action:

에러를 발생시키지 않으려면 다음과 같이 작성해야 된다.

foo-bar.url[0]=http://localhost:8080
foo-bar.url[1]=http://localhost:8081

spring-boot-properties-migrator

몇일전에 spring-boot-properties-migrator 라는 모듈이 추가 되었다. 이 모듈은 1.x에서 2.0으로 마이그레이션을 할 때 사용하는 모듈로 보인다. 현재 마일스톤7 버전에는 존재하지 않고 스냅샷에만 존재한다.

이 모듈은 마이그레이션할 때 유용한 모듈이다. 변경된 프로퍼티 혹은 삭제된 프로퍼티들을 레포트 해주고 만약 변경된 프로퍼티일 경우에는 실제 런타임시 변경된 프로퍼티의 정보를 변경해준다.

일단 말로는 힘드니 한번 살펴보자.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-properties-migrator</artifactId>
</dependency>

일단 다음과 같이 디펜더시를 받자. 그리고 나서 2.0에서 변경된 프로퍼티를 작성해보자.

server.context-path=/test

실제 이 프로퍼티는 server.servlet.context-path로 변경 되었다. 위와 같이 작성한 뒤에 어플리케이션을 동작시키면 다음과 같은 로그메세지를 리포트 해준다.

2018-01-28 19:50:28.585  WARN 1401 --- [           main] o.s.b.c.p.m.PropertiesMigrationListener  : 
The use of configuration keys that have been renamed was found in the environment:

Property source 'applicationConfig: [classpath:/application.properties]':
    Key: server.context-path
        Line: 9
        Replacement: server.servlet.context-path


Each configuration key has been temporarily mapped to its replacement for your convenience. To silence this warning, please update your configuration to use the new keys.

프로퍼티의 파일명과 그에 대한 라인수 까지 리포트를 해주고 변경된 프로퍼티명도 함께 리포트 해준다. 아주 우용한 모듈이다. 만약 삭제된 프로퍼티라면 log level이 ERROR로 출력 된다.

2018-01-28 19:52:20.571 ERROR 1404 --- [           main] o.s.b.c.p.m.PropertiesMigrationListener  : 
The use of configuration keys that are no longer supported was found in the environment:
...
...

만약 위 모듈과 함께 작성한다면 환경정보에 새로운 프로퍼티명으로 환경정보가 작성되어 있다.

String oldPath = environment.getProperty("server.context-path");
String newPath = environment.getProperty("server.servlet.context-path");

oldPath와 newPath 둘다 모두 동일한 정보가 들어가 있다.

오늘은 이렇게 새로운 Spring boot 2.0에 대해서 조금 알아봤다. 아주 심각한 내용은 아니기에 한번씩 그냥 살펴보는것도 좋은 듯 싶다.
2.0은 언제 나올려나.. 지금 예상은 2월20일로 되어있는데 좀 더 걸릴듯 싶다. 그 때 나오면 좋고.