[Springboot] 24. Externalized Configuration #2 @ConfigurationProperties

2022. 10. 28. 17:13JAVA/Spring

1. 타입-세이프 프로퍼티 @ConfigurationProperties

  • 여러 프로퍼티를 묶어서 읽어올 수 있습니다.
  • 타입-세이프하다는 의미는 @Value 애노테이션의 사용과 같이 @Value(”${yonghwan.name}”)의 value 문자열 값의 오타가 나지 않게 하는 방법입니다.
    • 예를 들어 필드 멤버를 정의하고 getter 메서드로 접근하는 것은 타입-세이프한 방법입니다.
  • 빈으로 등록해서 다른 빈에 주입할 수 있습니다.
    • @EnableConfigurationProperties
    • @Component
    • @Bean
  • 융통성 있는 바인딩
    • context-path (케밥)
    • context_path (언더스코어)
    • contextPath (카멜)
    • CONTEXTPATH
  • 프로퍼티 타입 컨버전(Conversion)
    • @DurationUnit
  • 프로퍼티 값 검증
    • @Validated
    • JSR-303 (@NotNull, …)
  • 메타 정보 생성
  • @Value
    • SpEL을 사용할 수 있지만 위에 있는 기능들은 전부 사용 못합니다.

 

2. @ConfigurationProperties 실습

@ConfigurationProperties 애노테이션을 적용하여 application.properties 파일에 명세한 속성들을 가져와 주입합니다.

  1. application.properties 파일에 속성 정의
  2. @ConfigurationProperties 애노테이션을 적용할 Properties 클래스 정의 및 빈으로 등록
  3. 클라이언트 코드를 작성하여 Properties 의존 객체에 자동 주입
  4. Properties 의존 객체를 이용하여 필드 멤버(속성) 참조

0. application.properties 파일에 참조할 속성을 정의합니다.

yonghwan.name=YongHwan
yonghwan.age=30
yonghwan.fullName=${yonghwan.name} Kim

1. @ConfigurationProperties 애노테이션을 적용할 클래스 정의

@ConfigurationProperties("yonghwan")
@Component
@Getter
@Setter
public class YonghwanProperties {
    private String name;
    private int age;
    private String fullName;
}

 

2. @ConfigurationProperties 애노테이션 적용시 Springboot Configuration Annotation Processor 경고 문구가 발생할 경우 build.gradle 파일에 메타 정보를 생성해주는 의존성을 추가합니다.

dependencies {
    annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
}

 

3. 클라이언트 코드를 작성합니다.

@Component
@AllArgsConstructor
public class SampleRunner implements ApplicationRunner {

    private final YonghwanProperties yonghwanProperties;

    @Override
    public void run(ApplicationArguments args){
        System.out.println("===================");
        System.out.println(yonghwanProperties.getName());
        System.out.println(yonghwanProperties.getAge());
        System.out.println("===================");
    }
}

실행 결과는 다음과 같습니다.

===================
YongHwan
30
===================

 

 

위 실행결과와 같이 @ConfigurationProperties 애노테이션을 사용하면 여러 프로퍼티를 묶어서 가져오고 참조할 수 있습니다.

 

3. 융통성 있는 바인딩(Relaxed Binding)이란 무엇인가?

예를 들어 필드 멤버로 fullName이라는 멤버가 있고 속성명을 다음 중 하나로 정의할 수 있습니다.

  • full-name (케밥)
  • full_name (언더스코어)
  • fullName (카멜)
  • FULLNAME (대문자)

4. 프로퍼티 타입 컨버전(Property Type Conversion)

프로퍼티 파일 안에서 기본적으로 모든 값들은 문자열입니다.

yonghwan.name=YongHwan
yonghwan.age=30
yonghwan.FULLNAME=${yonghwan.name} Kim

yonghwan.age=30이라고 설정하였지만 30은 문자열입니다.

 

하지만 스프링이 제공하는 커버전 서비스를 통해서 필드 멤버에 바인딩될때 타입 컨버전(Type Conversion)이 발생하고 정수 타입 필드 멤버에 타입 변환되어 저장되는 것입니다.

 

스프링부트가 제공하는 컨버전 타입중 @DurationUnit을 제공합니다. @DurationUnit은 시간정보를 가지고 싶을때 사용합니다.

 

@DurationUnit 애노테이션 적용

@DurationUnit(ChronoUnit.SECONDS)
private Duration sessionTimeout = Duration.ofSeconds(30);

Duration 타입의 sessionTimeout 멤버는 초(seconds)로 바인딩 받겠다는 의미이고 만약 바인딩되는 값이 없다면 기본값으로 30초로 저장하겠다는 의미입니다.

 

프로퍼티 파일에 시간 정보 속성 정의

yonghwan.sessionTimeout=40
또는
yonghwan.sessionTimeout=40s
  • 40s와 같이 정의하면 @DurationUnit 애노테이션을 적용하지 않아도 됩니다.

 

5. 프로퍼티 값 검증(@Validated)

@Validated 애노테이션을 적용하여 필드 멤버에 바인딩 되는 값들을 검증할 수 있습니다.

프로퍼티 값 검증 (@Validated) 실습

  1. 바인딩되는 클래스에 @Validated 애노테이션 적용
  2. spring-boot-start-validation 의존성 추가
  3. 바인딩되는 클래스의 필드 멤버에 검증 애노테이션(@NotEmpty 등) 적용
  4. 클라이언트 코드를 실행
  5. 바인딩되는 클래스에 @Validated 애노테이션을 적용합니다.
@ConfigurationProperties("yonghwan")
@Validated
@Component
@Getter
@Setter
public class YonghwanProperties {
	...
}
  1. 검증을 위한 의존성 추가
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-validation'
}
  1. 클래스의 검증하고자 하는 필드멤버에 검증 애노테이션을 적용
@ConfigurationProperties("yonghwan")
@Validated
@Component
@Getter
@Setter
public class YonghwanProperties {
    @NotEmpty
    private String name;
		...
  • @NotEmpty : null이거나 비어있는지 검증하는 애노테이션

application.properties

#yonghwan.name=YongHwan
yonghwan.age=30
yonghwan.fullName=${yonghwan.name} Kim
yonghwan.sessionTimeout=40

yonghwan.name 속성을 주석 처리합니다.

  1. 클라이언트 코드를 실행하고 실행결과를 확인합니다.
Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'yonghwan' to kr.yh.external_config.YonghwanProperties failed:

    Property: yonghwan.name
    Value: "null"
    Reason: 비어 있을 수 없습니다

Action:

Update your application's configuration

위와 같이 yonhwan.name 속성의 값이 null이기 때문에 실행을 중지하였습니다.

 

References

source code : https://github.com/yonghwankim-dev/springboot_study/tree/main/springboot_utilization/src/main/java/kr/yh/external_config
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config
[인프런] 스프링 부트 개념과 활용