Property Binding
스프링부트 프로젝트를 생성하면 외부 프로퍼티 설정파일을 만들게 된다.(application.yml, application.properties ...) 여기 정의한 키-값들이 결국 어플리케이션이 기동되면서 클래스로 바인딩 되는데 이 과정에 대해 알아본다.
먼저 클래스에서 외부 프로퍼티 값들을 가져오는 방식을 살펴보자. 아래 3가지를 이용할 수 있다.
- @Value : 소스코드에서 바로 프로퍼티에 주입받아 사용
- Environment : 외부설정이 바인딩 된 Environment 빈을 주입받아 사용
- @ConfigurationProperties : 외부설정이 바인딩 될 Bean(객체)을 생성하여 사용
가장 빈번하게 사용하는 방식은 @Value("${property}") 방식일 듯 싶지만 불러올 프로퍼티의 갯수가 많거나, 계층형의 구조를 가지고 있는 경우 등에는 적절하지 않다. 또한 프로퍼티명이나 타입을 직접 입력해야 하므로 오류에 대한 여지도 있다. @Value와 Environment 빈에 대한 예시는 아래와 같다.
application.properties에 다음과 같이 프로퍼티 키-값 정의 : yangs.name=brand
@Component
public class SimpleRunner implements ApplicationRunner {
@Autowired
Environment environment; // Environment 타입의 빈 주입
@Value("${yangs.name}") // ${}내부에 작성된 프로퍼티키에 해당하는 값을 세팅
String name1;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("Value 애노테이션의 yangs.name : " + name1);
String name2 = environment.getProperty("yangs.name");
System.out.println("Environment bean의 yangs.name : " + name2);
}
}
// 아래는 콘솔 출력결과 Environment bean의 yangs.name : brand |
간단한 몇 개의 값이라면 @Value를 사용하여 바인딩할 수 있지만, 검증이나 Type-safe, 계층형 구조 등을 처리할 수 있는 @ConfigurationProperties를 이용한 방법이 있다,
application.yml의 예시와 이 값을 @ConfigurationProperties를 어떻게 사용하여 바인딩 하는지 예제로 살펴본다.
application.yml 예시
일반적으로 프로퍼티명은 아래 is-main-tester처럼 소문자와 대쉬(-)를 구분자로 하는 명칭이 권장된다.
프로퍼티명 앞의 대쉬(-)는 리스트형을 나타낼때 사용한다.
test: |
@ConfigurationProperties(prefix = “test”) 로 프로퍼티클래스에 값 바인딩하기
프로퍼티가 맵핑될 클래스(아래의 TesterProperties)를 작성하고 @ConfigurationProperties을 마킹한다. 이 클래스는 프로퍼티값이 맵핑될 클래스라는 의미로 애노테이션에는 프로퍼티명의 prefix(아래의 prefix = "test")를 지정할 수 있다.
프로퍼티 파일에서 리스트형으로 작성한 sub-testers를 맵핑할 수 있도록 List<Subster> subTesters 로 선언한 것을 볼 수 있고,
작성된 위의 프로퍼티 파일은 kebab case(- 가 구분자)로 작성하였으나 클래스 변수명은 camel case이다.
스프링부트에서는 프로퍼티명의 camel case, kebab case, underscore notation 간의 변환을 모두 지원한다.
subTesters - sub-testers - sub_testers 모두 변환하여 바인딩이 가능하다.
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
// 읽어들인 프로퍼티 중 해당 prefix의 프로퍼티값을 바인딩한다.
@ConfigurationProperties(prefix = "test")
public class TesterProperties {
private String name;
private int cnt;
private boolean isMainTester;
private List<SubTester> subTesters = new ArrayList<>();
// Getter, Setter, ToString 생략
static class SubTester {
private String name;
private int cnt;
private boolean isMainTester;
// Getter, Setter, ToString 생략
}
}
@EnableConfigurationProperties(TesterProperties.class)로 프로퍼티클래스 사용하기
바인딩이 완료된 TesterProperties를 빈으로 등록하여 사용하기 위해 @EnableConfigurationProperties를 마킹한다.
주로 프로퍼티 값을 사용할 @Configuration 파일에 마킹하며, @ConfigurationProperties가 마킹된 클래스를 빈으로 등록해주는 역할이다. 만일 프로퍼티 클래스가 다수라면 @ConfigurationPropertiesScan({"base.package1", "base.package2"}) 으로 여러 패키지를 스캔하여 등록할 수도 있다.
프로퍼티가 제대로 바인딩 됬는지 테스트를 위해 ApplicationRunner를 작성 후 콘솔로그를 찍어본다.
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@EnableConfigurationProperties(TesterProperties.class)
public class PropertyRunner implements ApplicationRunner {
private final TesterProperties testerProperties; // 값이 바인딩된 빈이 의존성 주입된다.
public PropertyRunner(TesterProperties testerProperties) {
this.testerProperties = testerProperties;
}
@Override
public void run(ApplicationArguments args) throws Exception {
// 바인딩이 제대로 되었는지 콘솔 출력
System.out.println("=================================");
System.out.println("TesterProperties : " + testerProperties);
System.out.println("=================================");
}
}
================================= |
String, int, boolean 및 List 형까지 바인딩이 제대로 된 것을 확인할 수 있다. 혹여 바인딩시 Validation을 하고 싶다면 아래와 같이 스프링의 @Validated 와 JSR-303에 정의된 javax.validation 애노테이션을 사용할 수 있다.
@ConfigurationProperties(prefix = "test")
@Validated // 검증대상임을 표시
public class TesterProperties {
@NotNull
private String name;
@Max(90)
private int cnt;
private boolean isMainTester;
@Valid // 내부 프로퍼티에 검증이 적용되려면 @Valid를 마킹한다.
private List<SubTester> subTesters = new ArrayList<>();
static class SubTester {
@NotNull
private String name;
@Min(20)
private int cnt;
private boolean isMainTester;
}
// Getter, Setter, ToString 생략
}
요약하면
- 외부에서 설정된 프로퍼티 파일을 코드에서 사용하는 방법은 여러가지가 있다.
- 만일 읽어올 프로퍼티가 많거나 계층형이라면 객체에 바인딩하여 사용하는 것을 고려하자.
- 프로퍼티값을 객체에 바인딩하여 빈으로 등록 후 사용을 위해서는 @ConfigurationProperties(prefix = "test"), @EnableConfigurationProperties, @ConfigurationPropertiesScan({"base.package1", "base.package2"}) 같은 애노테이션을 조합한다.
- 프로퍼티 바인딩시 검증을 위해서는 @Validated와 javax.validation 애노테이션을 사용한다.
'개발 > Spring & Spring Boot' 카테고리의 다른 글
스프링부트 프로파일(Springboot Profile)로 다른 환경 구성하기 (0) | 2020.12.06 |
---|---|
SpringBoot 프로퍼티(외부설정) (0) | 2020.12.05 |
ApplicationRunner, CommandLineRunner (0) | 2020.12.02 |
SpringApplication(FailureAnalyzers, Application Events and Listeners, WebApplicationType) (0) | 2020.12.02 |
Springboot의 자동설정(starter 라이브러리) (0) | 2020.12.02 |