ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • @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
Designed by Tistory.