-
@ConfigurationProperties - 외부 설정 사용스프링/스프링부트 2023. 9. 30. 21:45
application.properties
my.datasource.url=local.db.com my.datasource.username=username my.datasource.password=password my.datasource.etc.max-connection=1 my.datasource.etc.timeout=3500ms my.datasource.etc.options=CACHE,ADMIN
my.datasource까지 중복된 것이기 때문에 객체로 관리하면 더 편할 것이다.
MyDataSourcePropertiesV1.class
@Getter @ConfigurationProperties("my.datasource") public class MyDataSourceProperties { private String url; private String username; private String password; private Etc etc; public MyDataSourceProperties(String url, String username, String password, Etc etc) { this.url = url; this.username = username; this.password = password; this.etc = etc; } @Getter public static class Etc { private int maxConnection; private Duration timeout; private List<String> options = new ArrayList<>(); public Etc(int maxConnection, Duration timeout, List<String> options) { this.maxConnection = maxConnection; this.timeout = timeout; this.options = options; } } }
클래스를 만들어서 객체처럼 만들어줬다. @ConfigurationProperties 어노테이션을 사용해서 my.datasource라는 시작점을 적어준다. url, username, password를 변수로 선언해주고, Etc라는 static class를 만들어서 나머지 etc.~~의 변수들을 넣어준다. 반환타입도 지정해주기 때문에 반환타입을 정확하게 설정할 수 있다.
MyDataSourceProperties은 스프링 빈으로 등록되지만 Setter가 포함되면 누군가 실수로 변경할 수도 있다. application.properties 설정 값을 그대로 읽어오려고 한 것이기 때문에 초기화에만 설정되고 변경하면 안되기 때문에 생성자로 설정해야 한다.
MyDataSourceConfigV1.class
@Slf4j @EnableConfigurationProperties(MyDataSourceProperties.class) public class MyDataSourceConfig { private final MyDataSourceProperties properties; public MyDataSourceConfig(MyDataSourceProperties properties) { this.properties = properties; } @Bean public MyDataSource myDataSource() { return new MyDataSource(properties.getUrl(), properties.getUsername(), properties.getPassword(), properties.getEtc().getMaxConnection(), properties.getEtc().getTimeout(), properties.getEtc().getOptions()); } }
@EnableConfigurationProperties라는 어노테이션은 사용할 ConfigurationProperties를 스프링 빈으로 주입받아서 사용할 수 있도록 해주는 것이다.
@ConfigurationPropertiesScan
@Import(MyDataSourceConfig.class) @SpringBootApplication(scanBasePackages = "hello.datasource") @ConfigurationPropertiesScan public class ExternalReadApplication { public static void main(String[] args) { SpringApplication.run(ExternalReadApplication.class, args); } }
main 메서드에 @ConfigurationPropertiesScan이라는 어노테이션을 붙이면 따로 Configuration에 @EnableConfigurationProperties를 붙이지 않아도 된다. 물론 괄호 안에 범위를 지정해줄 수도 있다.
@DefaultValue
@Getter @ConfigurationProperties("my.datasource") public class MyDataSourcePropertiesV2 { private String url; private String username; private String password; private Etc etc; public MyDataSourcePropertiesV2(String url, String username, String password, @DefaultValue Etc etc) { this.url = url; this.username = username; this.password = password; this.etc = etc; } @Getter public static class Etc { private int maxConnection; private Duration timeout; private List<String> options = new ArrayList<>(); public Etc(@DefaultValue("2") int maxConnection, Duration timeout, List<String> options) { this.maxConnection = maxConnection; this.timeout = timeout; this.options = options; } } }
@DefaultValue 어노테이션은 해당 값을 찾을 수 없으면 기본값을 사용한다.
my.datasource.url=local.db.com my.datasource.username=username my.datasource.password=password #my.datasource.etc.max-connection=1 #my.datasource.etc.timeout=3500ms #my.datasource.etc.options=CACHE,ADMIN
application.properties에서 etc.~~를 주석처리하고 실행한 결과 etc는 전부 default 값이 들어갔으며 @DefaultValue 값을 2로 지정해준 maxConnection만 2라는 값이 나왔다.
@ConfigurationProperties 검증
문자가 입력되는 범위나 길이같은 검증을 하는 방법 또한 스프링에서 제공한다. 자바 빈 검증기라는 표준 검증기가 있다.
이메일을 외부 설정에 입력했는데, 만약 이메일 형식에 맞는지 검증하는 방식으로도 사용할 수 있다.
@Getter @ConfigurationProperties("my.datasource") @Validated public class MyDataSourcePropertiesV3 { @NotEmpty // 필수 값 private String url; @NotEmpty private String username; @NotEmpty private String password; private Etc etc; public MyDataSourcePropertiesV3(String url, String username, String password) { this.url = url; this.username = username; this.password = password; this.etc = etc; } @Getter public static class Etc { @Min(1) @Max(999) private int maxConnection; @DurationMin(seconds = 1) @DurationMax(seconds = 60) private Duration timeout; private List<String> options = new ArrayList<>(); public Etc(int maxConnection, Duration timeout, List<String> options) { this.maxConnection = maxConnection; this.timeout = timeout; this.options = options; } } }
클래스 선언부에 @Validated 어노테이션을 붙이면 잘 아는 @NotEmpty, @Min, @DurationMin 등으로 검증할 수 있다.
지정된 값 이외의 값을 넣으면 에러가 발생해서 검증할 수 있다.
ConfigurationProperties 장점
- 외부 설정을 객체로 편리하게 변환해서 사용할 수 있다.
- 외부 설정의 계층을 객체로 편리하게 표현할 수 있다.
- 외부 설정을 타입 안전하게 사용할 수 있다.
- 검증기를 적용할 수 있다
'스프링 > 스프링부트' 카테고리의 다른 글
@Profile (0) 2023.09.30 YAML (0) 2023.09.30 @Value - 외부 설정 사용 (0) 2023.09.30 외부 설정의 우선순위 (0) 2023.09.30 외부 설정 4 - 설정 데이터 (0) 2023.09.30