개요
properties, yml 설정 파일에 있는 설정 값을 활용하는 간단한 방법은 @Value 어노테이션을 활용하는 것이다.
//예시
@Value("${host.url}")
private String url;
문제는 사용해야 하는 설정 값이 점점 많아졌을 때 어노테이션과 프로퍼티 값이 2라인씩 차지하기 때문에 가독성도 떨어지고 비슷한 설정들을 묶어 놓는 것도 애매해지기 때문에 이럴때 pojo 형식의 ConfigurationProperties가 유용하기 때문에 한번 알아보자.
ConfigurationProperties 사용하기
먼저 컨피그로 활용할 객체에 @Configuration, @ConfigurationProperties와 prefix를 지정해 해당 값 이하의 설정값들을 사용한다.
@Configuration
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
private String hostName;
private int port;
private String from;
// standard getters and setters
}
설정값 세팅이 끝났으면 app main 클래스에 EnableConfigurationProperties 어노테이션과 설정 클래스를 value로 집어넣는다.
@SpringBootApplication
@EnableConfigurationProperties(ConfigProperties.class)
public class EnableConfigurationDemoApplication {
public static void main(String[] args) {
SpringApplication.run(EnableConfigurationDemoApplication.class, args);
}
}
그럼 이제 ConfigProperties는 각 컴포넌트에 의존성으로 주입해 사용할 수 있는 설정 객체로 사용 가능해진다.
프로퍼티로 매핑되는 설정 네이밍 규칙은 아래 예시 포멧에 대해 모두 지원한다.
mail.hostName
mail.hostname
mail.host_name
mail.host-name
mail.HOST_NAME
좀 더 간단하게 ConfigurationProties를 사용하는 방법
기존에는 설정값으로 활용할 객체에 ConfigurationProties와 Bean으로 생성할 수 있는 어노테이션(@Configuration, @Component 등)을 달고 EnableConfigurationProperties 어노테이션에 해당 클래스를 입력해야 했다.
설정 객체가 많아지다보면 Enable 어노테이션에 설정값 객체 클래스들을 붙여나가는 것도 가독성이 떨어지고 귀찮아지기 때문에 스프링 부트 2.2 버전 이상부터는 다음과 같이 좀 더 쉽게 사용할 수 있게 되었다.
1. 컨피그 클래스
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
private String hostName;
private int port;
private String from;
// standard getters and setters
}
2. 컴포넌트 클래스
@SpringBootApplication
@ConfigurationPropertiesScan
public class EnableConfigurationDemoApplication {
public static void main(String[] args) {
SpringApplication.run(EnableConfigurationDemoApplication.class, args);
}
}
스프링 서버 구동시 ConfigurationPropertiesScan가 존재하는 패키지 이하에서 프로퍼티 스캔을 진행하게 된다.
그래서 꼭 메인 클래스가 아니더라도 프로퍼티 클래스와 동일한 패키지나 상위 패키지의 컴포넌트 객체에 설정해도 된다.
또한, @ConfigurationPropertiesScan("com.example.demo.mail") 같은 형태로 프로퍼티 스캔을 할 루트 패키지를 지정할 수도 있다.
여기서 프로퍼티 스캔시 프로퍼티 클래스를 @Configuration, @Component 어노테이션 같이 Bean으로 설정하는 경우 프로퍼티 스캔에 포함되지 않는다.
Nested Properties
스프링에서는 중첩 프로퍼티를 설정 객체에 넣어 사용할 때 Map, List, Object 타입을 각각 지원한다.
다음 예제에서 Credentials 객체와 해당 객체를 갖는 ConfigProperties에 컨피그 값을 설정해본다.
public class Credentials {
private String authMethod;
private String username;
private String password;
// standard getters and setters
}
public class ConfigProperties {
private String hostname;
private int port;
private String from;
private List<String> defaultRecipients;
private Map<String, String> additionalHeaders;
private Credentials credentials;
// standard getters and setters
}
#Simple properties
mail.hostname=mailer@mail.com
mail.port=9000
mail.from=mailer@mail.com
#List properties
mail.defaultRecipients[0]=admin@mail.com
mail.defaultRecipients[1]=owner@mail.com
#Map Properties
mail.additionalHeaders.redelivery=true
mail.additionalHeaders.secure=true
#Object properties
mail.credentials.username=john
mail.credentials.password=password
mail.credentials.authMethod=SHA1
- 가장 간단한 String, int 값부터 array 타입으로 넣거나 map, 객체 내부의 프로퍼티로 설정할 수 있는 걸 볼 수 있다.
@Bean 어노테이션에 ConfigurationProperties 적용하기
설정 값으로 사용하고자 하는 클래스가 내 프로젝트가 아닌 서드 파티 컴포넌트에 포함돼 있는 경우에 유용하다.
public class Item {
private String name;
private int size;
// standard getters and setters
}
@Configuration
public class ConfigProperties {
@Bean
@ConfigurationProperties(prefix = "item")
public Item item() {
return new Item();
}
}
ConfigurationProperties 불변 객체로 활용하기
@ConstructorBinding
어노테이션을 생성자에 사용하면 setter를 모두 삭제하고 immutable 객체로 사용할 수 있다.
@ConfigurationProperties(prefix = "mail.credentials")
public class ImmutableCredentials {
private final String authMethod;
private final String username;
private final String password;
@ConstructorBinding
public ImmutableCredentials(String authMethod, String username, String password) {
this.authMethod = authMethod;
this.username = username;
this.password = password;
}
public ImmutableCredentials(String username, String password) {
this.username = username;
this.password = password;
this.authMethod = "Default";
}
public String getAuthMethod() {
return authMethod;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
}
자바 16 버전부터 사용가능한 record 타입을 활용하기
- 객체의 상태 값을 변경할 경우 다양한 사이드 이펙트가 발생할 수 있기 때문에 코틀린 데이터 클래스 같은 immutable한 record 타입이 자바에 도입 되었는데 이 record 타입에도 컨피그 값으로 사용할 수 있다.
@ConstructorBinding
@ConfigurationProperties(prefix = "mail.credentials")
public record ImmutableCredentials(String authMethod, String username, String password) {
}
기타
configuration 값에 대해서 어노테이션 기반으로 해당 설정이 올바른 값인지 체크하는 기능도 있다.
그 기능이 사용하고자 한다면 해당 의존성을 주입하고
implementation 'org.springframework.boot:spring-boot-starter-validation'
하단 참고 자료의 링크를 따라가서 활용해보자.
참고 자료
'개발 > spring' 카테고리의 다른 글
[Java/Spring] JVM Warm up (0) | 2024.03.25 |
---|---|
[Spring] spring cloud reactive gateway 사용시 주의할 점 (1) | 2024.02.26 |
[spring] application event 사용해보기 (1) | 2024.02.05 |
[Spring/MongoDB] MongoDB에 Entity를 저장할 때 필요 없는 필드 제외하기 - 2 (0) | 2021.09.01 |
[Spring/MongoDB] MongoDB에 Entity를 저장할 때 필요 없는 필드 제외하기 (0) | 2021.06.22 |