NoTimeForDawdling

Spring Boot properties 값 주입 방법 본문

SpringBoot

Spring Boot properties 값 주입 방법

Room_Energy 2021. 2. 3. 20:59

Spring Boot를 사용하여 외부의 특정 값들을 주입받아야 할 때가 있다. 예로 API를 사용하기 위한 API key나 token 값이 될 수 있습니다.

 

이런 값들은 application.propertiesapplication.**yml**과 같은 파일에 적어두고 사용할 수 있고, .jar 파일을 실행하기 위한 커맨드에 직접 값을 넘겨주기도 합니다.

 

여기서는 외부 파일(.properties, .yml)에 있는 값들을 소스 코드에 주입하는 방법을 알아보겠습니다.

properties -> yml 을 사용했을 시 이점

properties 값 주입 방법을 알아보기에 앞서 properties 대신 yml이 주는 이점을 알아보겠습니다.

1. 가독성

-  yml은 계층 구조로 표현합니다. 그렇기 때문에 properties를 사용하는 것 보다 가독성이 좋습니다.

-  불필요한 prefix의 중복 제거가 가능합니다.

 

properties

spring.datasource.url=jdbc:h2:tcp://localhost/~/testdb
spring.datasource.username: sa
spring.datasource.password:
spring.datasource.driver-class-name: org.h2.Driver

 

yml

spring:
  datasource:
    url: jdbc:h2:tcp://localhost/~/testdb
    username: sa
    password:
    driver-class-name: org.h2.Driver

2. 여러 값 들의 표현

-  하이픈(-)으로 시작하는 한 줄에 하나의 요소를 표현합니다.

 

properties

test.servers[0]=local.example.com
test.servers[1]=dev.example.com

yml

test:
  servers:
    - local.example.com
    - dev.example.com

3. Pofile 적용

-  한 파일 내에서 여러 파일을 사용하는 것처럼 분리가 가능합니다.

-  application.yml 파일 하나로 여러개의 yml을 생성한 것과 같이 처리 가능합니다.

 

properties

 

-  application-{file-name}.properties 형식으로 생성할 수 있습니다.

    -  application-local.properties

    -  application-dev.properties

 

 

yml

-  profiles를 선언하여 한 yml파일 내에서 구분이 가능합니다.

spring:
  profiles:
    active: local #적용할 profile 선택
    
 --- #local 환경
 spring:
   profiles: local
 logging:
   level:
     root: debug

 --- #dev 환경
 spring:
   profiles: dev
 logging:
   level:
     root: info

 

외부 파일 값 주입하기

@ConfigurationProperties

yml 예제 코드

cafeteria:
  :url: example.com
  :key: mykey

 

Properties 클래스

@Getter
@Setter
@ConfigurationProperties(prefix = "cafeteria")
public class CafeteriaProperties {
    private String url;
    private String key;
}
  • 위와 같이 properties클래스를 정의해서 사용합니다.
  • @ConfigurationProperties를 사용할 때 prefix를 적어줘야 합니다.
  • 위 코드를 보면 @Setter를 정의해 준걸 볼 수 있습니다. setter가 없으면 Caused by: java.lang.IllegalStateException: No setter found for property가 발생합니다.

@ConstructorBinding

@ConfigurationProperties를 사용한 코드를 보면 final 필드로 인스턴스 변수를 생성할 수 없습니다. 또한 setter가 공개되어 있기 때문에 중간에 값을 변경할 수 있는 위험이 있습니다. 이를 해결하기 위한 방법으로 @ConstructorBinding를 사용하면 됩니다.

 

@ConstructorBinding어노테이션은 final 필드에 대해 값을 주입해 줍니다. final을 명시해 주지 않으면 setter를 이용해서 값을 binding하려 하기 때문에 주의해야 합니다.

 

@ConstructorBinding 예제 코드

@Getter
@RequiredArgsConstructor
@ConstructorBinding
@ConfigurationProperties(prefix = "cafeteria")
public class CafeteriaProperty {
    private final String url;
    private final String key;
}

 

@EnableConfigurationProperties

@ConstructorBinding 예제 코드는 다음과 같은 에러 메시지를 보여줍니다.

Not registered via @EnableConfigurationProperties, marked as Spring component, or scanned via @ConfigurationPropertiesScan 

해결 방법으로 @EnableConfigurationProperties을 이용해서 Properties 클래스의 클래스 타입을 명시해주면 됩니다.

@Configuration
@EnableConfigurationProperties(FreeCafeteriaProperty.class)
public class PropertiesConfig {
}