logo

Petefolio

ArticlesClippingAbout me
@ConfigurationProperties

Web

@ConfigurationProperties

8/14/2024

스프링에서는 @ConfigurationProperties 애노테이션을 통해 외부 설정을 객체로 만들어 시스템 내에서 사용할 수 있게 해준다. 이를 통해 단순히 외부 설정을 매핑하는 것 뿐만 아니라 객체의 이점을 살리는 방식으로 프로그래밍을 할 수 있게 도와준다.

@ConfigurationProperties

사용하고자 하는 속성들이 존재하는 클래스를 생성한 뒤, 애노테이션 엘리먼트에 해당 속성들의 기본 주소를 작성한다. 이후 이 클래스를 등록하면, 스프링은 기본 주소와 변수명을 토대로 외부 설정값을 읽어와 값을 저장한다.

기본 주입 방식은 Java Bean Property 방식인 getter, setter를 사용하므로 이에 해당하는 코드는 작성해주어야 한다.

@Data
@ConfigurationProperties("db.mysql")
public class MySQLProperties {
  private String host;
  private Integer port;
  private String db;
}

위와 같이 작성한 경우 application.properties 등으로 제공한 db.mysql.host, db.mysql.port, db.mysql.db 의 정보를 읽어서 각 필드에 매핑한다. 사실 위 코드만으로 동작하지는 않고, 해당 클래스가 구성정보를 읽어올 수 있도록 추가적인 정보를 스프링 측에 알려야 한다.

@Configuration
@EnableConfigurationProperties(MySQLProperties.class)
public class ConfigurationPropertiesConfig {}

위 코드까지 작성된 이후라면, 스프링은 컨테이너 초기화 시점에서 MySQLProperties의 빈을 등록한다. 이 과정에서 타입 검증을 수행해, 맞지 않는 경우 오류를 내뱉고 프로그램을 중지시킨다.

***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to bind properties under 'db.mysql.port' to java.lang.Integer:

    Property: db.mysql.port
    Value: "port"
    Origin: class path resource [application.properties] - 5:15
    Reason: failed to convert java.lang.String to java.lang.Integer (caused by java.lang.NumberFormatException: For input string: "port")

Action:

Update your application's configuration

심지어 Intellij는 Java 코드를 읽어 필요한 환경변수를 분석하고, 타입이 다른 경우 경고를 띄워주기도 한다.

@ConfigurationPropertiesScan

@EnableConfigurationProperties는 등록하고자 하는 환경변수를 하나하나 작성해줘야 한다는 번거로움이 있는데, 이 문제를 해결하기 위해서는 @ConfigurationPropertiesScan을 사용할 수 있다. 애노테이션 속성인 basePackage를 설정하지 않는다면 @ConfigurationPropertiesScan이 붙어있는 설정클래스와 같은 패키지거나 하위 패키지를 대상으로 @ConfigurationProperties가 붙은 클래스를 읽어 설정 정보 빈을 등록한다.

@Configuration
//@EnableConfigurationProperties(MySQLProperties.class)
@ConfigurationPropertiesScan
public class ConfigurationPropertiesConfig {
}

생성자 방식 등록

하지만 getter setter가 존재하는 객체는 객체의 생명주기 내에서 값이 변화될 가능성을 낳는다. 이러한 문제를 방지하기 위해서 설정 정보를 생성자를 통해 주입시킬 수 있다. 스프링은 생성자가 하나라면 해당 생성자를 통해 설정 정보를 주입해준다.

@Getter
@ConfigurationProperties(prefix = "db.mysql")
public class MySQLProperties {

    private final String host;
    private final Integer port;
    private final String db;

    public MySQLProperties(String host, Integer port, String db) {
        this.host = host;
        this.port = port;
        this.db = db;
    }
}

구성정보 검증

위 기술만으로 간단한 타입 검증은 되지만 값 자체를 정밀하게 검증할 수는 없다. 스프링은 Java Bean Validator를 통해 구성정보를 검증할 수 있게 도와준다.

@ConfigurationProperties(prefix = "db.mysql")
@Validated
public class MySQLProperties {

    private final String host;
    private final Integer port;
    private final String db;

    @Min(1)
    @Max(100)
    private final Integer poolSize;

    public MySQLProperties(String host, Integer port, String db, Integer poolSize) {
        this.host = host;
        this.port = port;
        this.db = db;
        this.poolSize = poolSize;
    }
}

위와 같이 클래스 레벨에 @Validated 애노테이션과 필드에 Validator 애노테이션을 부착해놓으면 초기화 시점에 검증을 수행하고, 실패한 경우 에러 문구와 함께 프로그램을 종료시킨다.

***************************
APPLICATION FAILED TO START
***************************

Description:

Binding to target com.example.demo.MySQLProperties failed:

    Property: db.mysql.poolSize
    Value: "1000"
    Origin: class path resource [application.properties] - 6:20
    Reason: 100 이하여야 합니다


Action:

Update your application's configuration

0

AI Summary

Beta

📬 새 글이 올라올 때 알려드려요!

새 글 알림받기