외부설정 @ConfigurationProperties

justindevcode·2024년 6월 3일
0

스프링부트

목록 보기
4/39
post-thumbnail

외부설정 @ConfigurationProperties

@ConfigurationProperties

외부설정 깊이 네이밍따라서 그데로 객체로 만들어줄 수 있다.

  • 설정값 객체
@Data
 @ConfigurationProperties("my.datasource")
 public class MyDataSourcePropertiesV1 {
 private String url;
 private String username;
 private String password;
 private Etc etc = new Etc();
    @Data
 public static class Etc {
 private int maxConnection;
 private Duration timeout;
    }
 private List<String> options = new ArrayList<>();
 }

my.datasource라고 되어있는 url, username, password를 위 객체 그데로받고
설정파일에 my.datasource.etc로 한칸더 깊은건 내부 클래스로 하나더 만들어주면 그게 딱 들어가게된다.
기본 주입방식은 getter setter를 이용하기에 @Data를 붙여줬다.

  • 빈등록 클래스
@Slf4j
 @EnableConfigurationProperties(MyDataSourcePropertiesV1.class)
 public class MyDataSourceConfigV1 {
 private final MyDataSourcePropertiesV1 properties;
 public MyDataSourceConfigV1(MyDataSourcePropertiesV1 properties) {
 this.properties = properties;
    }
    @Bean
 public MyDataSource dataSource() {
 return new MyDataSource(
                properties.getUrl(),
                properties.getUsername(),
                properties.getPassword(),
                properties.getEtc().getMaxConnection(),
                properties.getEtc().getTimeout(),
                properties.getEtc().getOptions());
    }
 }

이렇게 넣어서 빈 등록하면 되고 기본적으로 MyDataSourcePropertiesV1에서 필드 자료형으로 타입이 맞지않으면 오류띄워준다.
그리고 기본적으로 설정파일에는 캐밥케이스? 인가 max-connection로 작성하는데 자동으로 maxConnection 낙타표기법으로 바꿔준다.

  • 컴포넌트 스켄수정
 //@Import(MyDataSourceValueConfig.class)
 @Import(MyDataSourceConfigV1.class)
 @SpringBootApplication(scanBasePackages = "hello.datasource")
 public class ExternalReadApplication {...}

이 방식에서는 빈등록할때 @EnableConfigurationProperties(MyDataSourcePropertiesV1.class)이런식으로 하나 하나 적어줘야하는데
@ConfigurationPropertiesScan을 사용하게되면 해당 어노테이션 하위로 @ConfigurationProperties된걸 다 인식해서 사용할 수 있어서 편해진다.

@SpringBootApplication
 @ConfigurationPropertiesScan({ "com.example.app", "com.example.another" })
 public class MyApplication {}

지금 이 방식의 문제는 setter를 사용하는 방식으로 빈등록과정에서 누가 setter로 값을 변경해서 빈등록할 수 있다.
설정파일의 핵심은 외부설정값 그데로 이용하는것인데 이때문에 생성자 주입 방식을 사용해야한다.

@ConfigurationProperties 생성자

  • MyDataSourcePropertiesV2
 @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;
public Etc(int maxConnection, Duration timeout, @DefaultValue("DEFAULT") 
List<String> options) {
 this.maxConnection = maxConnection;
 this.timeout = timeout;
 this.options = options;
        }
    }
 }

MyDataSourceConfigV2 ExternalReadApplication도 수정한다.

위처럼 getter와 생성자만 놔두면 생성자 주입 방식으로 넣어주게된다.

다만 마지막 문제는 기본적으로 타입 확인은 해주지만 int이긴한데 1~99까지만 가능 이런식으로 범위를 조절하고싶다면?

객체를 사용하기때문에 spring-boot-starter-validation를 사용할 수 있다 이를 적용하면된다.

@ConfigurationProperties 검증

  • build.gradle
implementation 'org.springframework.boot:spring-boot-starter-validation'
  • MyDataSourcePropertiesV3
 @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, Etc etc) {
 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;
 public Etc(int maxConnection, Duration timeout, List<String> options) {
 this.maxConnection = maxConnection;
this.timeout = timeout;
 this.options = options;
        }
    }
 }

@Validated 붙여주고
jakarta.validation.constraints.Max의 공식 검증 어노테이션이나 org.hibernate.validator.constraints.time.DurationMax같은 추가 구현체를 사용하면된다.
공식은 아니더라도 대부분 하이버네이트 사용해서 상세한 검증은 이를 그냥 써도된다.

MyDataSourceConfigV3 ExternalReadApplication도 수정한다.

maxConnection=0으로 설정하게되면

 Property: my.datasource.etc.maxConnection
    Value: "0"
    Origin: class path resource [application.properties] - 4:34
    Reason: 1 이상이어야 합니다

이런식으로 오류코드 띄워준다.

profile
("Hello World!");

0개의 댓글