해당 코드는 Github에 공개되어 있습니다.

Spring Boot 2.2 버전에서부터는 Immutable으로 Properties 설정을 할 수 있습니다. 커스텀 하게 설정한 값들은 Properties 객체로 관리하는 것이 좋습니다. 해당 내용은 Properties 설정값 가져오기를 참조하시면 됩니다. 기존 Properties의 단점은 Mutable이라는 점입니다. 아래 예제 코드에서 설명드리겠습니다.

기존 Mutable Properties 방법#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration
@ConfigurationProperties(prefix = "user")
@Validated
public class SampleProperties {
@Email
private String email;
@NotEmpty
private String nickname;
private int age;
private boolean auth;
private double amount;

// getter, setter
}

기존 방식은 위처럼 setter 기반으로 바인딩 되기 때문에 해당 Properties 설정은 언제든지 변경될 가능성이 있습니다. 이런 단점을 스프링 부트 2.2에서는 생성자 바인딩을 지원해서 해결했습니다.

Immutable Properties 방법#

해당 예제는 Kotlin data class 기준으로 작성했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@ConstructorBinding
@ConfigurationProperties(prefix = "user")
@Validated
data class UserProperties(
@field:Email
val email: String,

@field:NotEmpty
val nickname: String,

@field:Min(10)
val age: Int,

@field:NotNull
val auth: Boolean,

@field:Min(10)
val amount: Double,

@DateTimeFormat(pattern = "yyyy-MM-dd")
@field:NotNull
val date: LocalDate
)

사용법은 간단합니다. @ConstructorBinding을 추가하고 data class으로 넘겨받을 값을 생성자로 지정합니다. 위처럼 작성하면 객체는 Immutable 상태가 됩니다. 스프링 부트 2.2.1 버전부터는 @ConfigurationProperties scanning 방식이 disabled 되면서 @EnableConfigurationProperties을 따로 지정해야 합니다. 자세한 내용은 여기를 참고하세요.

1
2
3
4
5
6
7
@SpringBootApplication
@EnableConfigurationProperties(UserProperties::class)
class KotlinJunit5Application

fun main(args: Array<String>) {
runApplication<KotlinJunit5Application>(*args)
}

2.2.1 버전 부터는 @EnableConfigurationProperties으로 클래스를 지정해야합니다. @Validated 어노테이션으로 properteis에 대한 검증도 가능합니다.

1
2
3
4
5
6
7
user:
email: "yuntest.com"
nickname: ""
age: 9
auth: true
amount: 1
date: "2019-10-10"

위 처럼 유효하지 않은 값들에 대해서 아래 화면처럼 검증할 수 있습니다.

스프링 부트가 구동될 때 해당 값에 대한 유효성 검사를 어노테이션 기반으로 쉽게 검증할 수 있습니다. 해당 값이 유효하지 않은 경우 스프링이 구동되지 않기 때문에 장점이 있습니다.

1
2
3
4
5
6
7
user:
email: "yun@test.com"
nickname: "yun"
age: 28
auth: false
amount: 101
date: "2019-10-10"

yml 처럼 유효한 값을 입력하면 정상적으로 동작하는 것을 확인할 수 있습니다.

1
2
3
4
5
6
7
8
@Component
class AppRunner(private val userProperties: UserProperties) :ApplicationRunner{
override fun run(args: ApplicationArguments?) {
println("=====================")
println(userProperties.toString())
println("=====================")
}
}


값들이 유요한 경우 객체에 바인딩 되는 것을 학인할 수 있습니다.