2022. 3. 30. 17:37ㆍSpring/Basic
1. Externalized Configuration
Spring Boot는 설정의 외부화를 통해 다양한 환경에 따라 설정을 달리할 부분들을 별도로 관리할 수 있습니다.
설정의 외부화(Externalized Configuration)는 properties 또는 YAML 파일, 환경변수, Command-line 인자값 등을 통해 설정할 수 있습니다.
1.1. @ConfigurationProperties vs @Value
YAML 파일에 설정한 프로퍼티를 Spring Boot로 주입하는 방법은 크게 2가지가 있습니다.
- @ConfigurationProperties 로 동일한 계층에 위치한 프로퍼티들을 한번에 주입
- @Value 애너테이션으로 빈에 직접 값을 주입
위의 2가지 방법의 특징에 대해 간략히 요약하자면 아래와 같습니다.
@ConfigurationProperties | @Value | |
---|---|---|
Relaxed binding | 지원 | 제한적 지원 |
Meta-data | 지원 | 지원x |
SpEL | 지원x | 지원 |
@ConfigurationProperties 는 계층단위로 한꺼번에 프로퍼티를 주입할 수 있으며, 컬렉션과 POJO 프로퍼티를 쉽게 읽어들일 수 있습니다.
1.2. 작성 방법
아래와 같은 YAML 파일이 정의되어 있을 때, 각 프로퍼티값을 읽어들이는 방법을 알아봅시다.
spring: datasource: hikari: auto-commit: false connection-test-query: SELECT 1 minimum-idle: 10 maximum-pool-size: 50 pool-name: pool-jiniworld_demo
1.2.1. @Value
@Value 방식은 @Value("${property}")
방식으로 속성을 주입합니다.
@Data @Component public class ValueProperties { @Value("${spring.datasource.hikari.auto-commit}") private boolean autoCommit; @Value("${spring.datasource.hikari.connection-test-query}") private String connectionTestQuery; @Value("${spring.datasource.hikari.minimum-idle}") private int minimumIdle; @Value("${spring.datasource.hikari.maximum-pool-size}") private int maximumPoolSize; @Value("${spring.datasource.hikari.pool-name}") private String poolName; }
만일 여러개의 속성을 주입해야하는 상황이라면 위와같이 동일한 prefix를 가지는 프로퍼티 정의에 반복적인 코드를 입력해야하는 번거로움이 있습니다.
@ConfigurationProperties 를 이용하면 spring.datasource.hikari
를 prefix로 가지는 프로퍼티값들을 한꺼번에 주입할 수 있습니다.
@Data @Component @ConfigurationProperties(prefix = "spring.datasource.hikari") public class DemoProperties { private boolean autoCommit; private String connectionTestQuery; private int minimumIdle; private int maximumPoolSize; private String poolName; }
@ConfigurationProperties 를 사용할 때 주의 사항은 prefix는 반드시 kebab case로 정의해야한다는 것입니다.
2. Relaxed Binding
아래와 같은 프로퍼티를 기준으로 Relaxed Binding을 설명하겠습니다.
playground: relaxed-binding: userId: demo123 PASSWORD: 1234 api-key: vnhfM8vJjwzJEvGCqvNue9h8w77fhxPS secret_key: qEX3PSHHgm2mvaHur3RG2VD2eYbKc75j sites: - https://java.applebox.xyz - http://localhost:8080 sites2: https://java.applebox.xyz, http://localhost:8080 option: name: test flag: false
2.1. @ConfigurationProperties에 적용되는 Relaxed Binding
Spring Boot 에서는 @ConfigurationProperties를 이용한 프로퍼티 바인딩을 매우 유연하게 제공합니다.
prefix는 무조건 kebab-case 형식으로 작성해야하지만, 이하 프로퍼티에 대해서는 Relaxed Binding을 제공합니다.
kebab-case, snake_case, camelCase로 작성한 프로퍼티는 모두 camelCase 로 정의한 필드에 바인딩 되며, UPEERCASE로 작성된 프로퍼티는 lowercase로 변환되어 바인딩 됩니다.
playground.relaxed-binding
아래에 있는 프로퍼티 키 값인 userId, PASSWORD, api-key, secret_key 는 모두 각기 다른 case로 설정이 되어있습니다.
그렇지만 @ConfigurationProperties 는 Relaxed Binding 을 지원하기 때문에 어떤 case로 쓰여있건 모두 camelCase 형식으로 읽어들일 수 있습니다.
아래 코드는 위의 프로퍼티를 읽어들이는 컴포넌트 클래스입니다.
@ToString @Setter @Component @ConfigurationProperties(prefix = "playground.relaxed-binding") public class RelaxedBinding { private String userId; private String password; private String apiKey; private String secretKey; @Getter private final List<String> sites = new LinkedList<>(); @Getter private final List<String> sites2 = new LinkedList<>(); @Getter private final Option option = new Option(); @ToString @Setter public static class Option { private String name; private boolean flag; } }
prefix를 playground.relaxed-binding
라고 설정한것 외에 별도의 설정을 하지 않아도 모두 camelCase형식의 필드값 설정으로 프로퍼티값을 주입할 수 있습니다.
2.2. @Value에 적용되는 Relaxed Binding
playground.relaxed-binding
아래에 있는 프로퍼티 키 값인 userId, PASSWORD, api-key, secret_key 는 모두 각기 다른 case로 설정 되어있지만 아래와 같이 Kebab case로 모든 값을 읽어들일 수 있습니다.
단, 최하단 프로퍼티값만 relaxed binding을 지원하고, 상위 계층은 반드시 Kebab case로 설정해야합니다.
@ToString @Setter @Component public class ValueProperties { @Value("${playground.relaxed-binding.user-id}") private String userId; @Value("${playground.relaxed-binding.password}") private String password; @Value("${playground.relaxed-binding.api-key}") private String apiKey; @Value("${playground.relaxed-binding.secret-key}") private String secretKey; @Value("${playground.relaxed-binding.sites2}") @Getter private final List<String> sites2 = new ArrayList<>(); }
참고로, @Value 는 POJO 프로퍼티나
playground.relaxed-binding.sites
과같은 값은 읽어들일 수 없습니다.
,
를 이용한 array는 읽어들일 수 있습니다.
3. 테스트 결과
3.1. ConfigurationProperties 테스트 결과
@SpringBootTest class RelaxedBindingTest { @Autowired private RelaxedBinding relaxedBinding; @Test void test() { System.out.println(relaxedBinding); } }
RelaxedBinding(userId=demo123, password=1234, apiKey=vnhfM8vJjwzJEvGCqvNue9h8w77fhxPS, secretKey=qEX3PSHHgm2mvaHur3RG2VD2eYbKc75j, sites=[https://java.applebox.xyz, http://localhost:8080], sites2=[https://java.applebox.xyz, http://localhost:8080], option=RelaxedBinding.Option(name=test, flag=false))
3.2. @Value 테스트 결과
@SpringBootTest class ValuePropertiesTest { @Autowired private ValueProperties valueProperties; @Test void test() { System.out.println(valueProperties); } }
ValueProperties(userId=demo123, password=1234, apiKey=vnhfM8vJjwzJEvGCqvNue9h8w77fhxPS, secretKey=qEX3PSHHgm2mvaHur3RG2VD2eYbKc75j, sites2=[https://java.applebox.xyz, http://localhost:8080])
4. 참고
프로퍼티에 설정된 값을 컴포넌트로 읽어들이는 것은 표준 Java Bean property descriptor에 의해 이뤄지며, 보통 NoArgsConstructor와 getter, setter를 필수적으로 가지는 편입니다.
간단하게, Lombok의 @Data 지정으로 한번에 읽어들일 수도 있겠으나, 먼저 아래의 특성이 있다는걸 알아두면 좋습니다.
4.1. 초기화 할거라면 getter 필수
Setter는 필수
Collection이나 POJO 프로퍼티에 final 설정을 하기위해서는 초기화가 필요하다.
이들을 초기화할 할 경우에는 반드시 getter 설정을 해야한다.
@ToString @Setter @Component @ConfigurationProperties(prefix = "playground.relaxed-binding") public class RelaxedBinding { private String userId; private String password; private String apiKey; private String secretKey; @Getter private final List<String> sites = new LinkedList<>(); @Getter private final List<String> sites2 = new LinkedList<>(); @Getter private final Option option = new Option(); @ToString @Setter public static class Option { private String name; private boolean flag; } }
4.2. 초기화 안한다면 getter는 필수아님
컬랙션이니 POJO 프로퍼티를 초기화하지 않은 경우, getter를 설정하지 않아도 값을 읽어들일 수 있습니다.
@ToString @Setter @Component @ConfigurationProperties(prefix = "playground.relaxed-binding") public class RelaxedBinding { private String userId; private String password; private String apiKey; private String secretKey; private List<String> sites; private List<String> sites2; private Option option; @ToString @Setter public static class Option { private String name; private boolean flag; } }
※ GitHub 에서 java-playground(v1.0.1)를 다운받아 볼 수 있습니다.
+++
- Externalized Configuration
- Spring Boot Relaxed Binding
- JavaBean properties binding
- JavaBean에 프로퍼티 바인딩하기
References
'Spring > Basic' 카테고리의 다른 글
[Spring Docs] DevTools (0) | 2024.10.04 |
---|---|
[Spring] yml 파일의 값을 상수로 초기화 하기 (0) | 2022.04.08 |
[Spring Boot] REST API의 request header, body logging 설정하기 (0) | 2020.10.20 |
[Thymeleaf] inline javascript에서 유니코드로 표기된 한글문자 한글로 표기 (0) | 2020.06.18 |
[Spring Boot] 프로퍼티 파일(yml) 여러개 설정하기 (0) | 2020.05.29 |