Spring Boot 의 properties

2020. 11. 16. 13:02ㄱㅐㅂㅏㄹ/Spring

개요

properties 는 기본이면서도 설정에 가장 많이 사용하게 되는 요소입니다.

기본적으로는 .properies, .yml 등을 통해 설정할 수 있는데 관련 방법들도 많고 어떻게 써야 효과적인지도 명확하지 않습니다.
가장 많이 이용하게 되고 실제 유용한 방법들을 정리합니다.


 

외부화 구성(Externalized Configuration)

Spring Boot 는 다른 환경에서 동일한 코드로 작업할 수 있도록 구성을 외부화 할 수 있습니다. 
환경 변수, command-line arguments, 별도의 외부 파일 등을 이용할 수 있는데, 이 때 properties 의 효과가 발휘됩니다. YAML 파일, properties 파일들을 통해 지정된 속성 값은 @Value 주석을 사용하여 Bean 에 직접 주입하거나 Spring 의 Environment 추상화를 통해 접근하거나 @ConfigurationProperties 를 통해 구조화된 객체에 바인딩 할 수 있습니다.

정의된 값을 환경에 맞게 합리적으로 사용하도록 매우 특별한 PropertySource 순서를 사용하는데 순서는 아래와 같습니다.

 

  1. devtools 이 활성화 상태에서 $HOME/.config/spring-boot 디렉토리의 Devtools global settings properties

    • spring-boot-devtools.properties

    • spring-boot-devtools.yaml

    • spring-boot-devtools.yml

  2. Test 의 @TestPropertySource annotations

  3. Test 의 properties 속성. @SpringBootTest 와 application 의 특정 부분을 테스트 하기 위한 test annotations

    • spring-boot-test-autoconfigure 를 통해 '@...Test' annotation 으로 설정되는 것들(@SpringBootTest, @WebMvcTest 등)

  4. Command line 을 통해 입력된 arguments

  5. 환경 변수 또는 시스템 속성에 포함된 inline JSON 인 SPRING_APPLICATION_JSON 의 속성

  6. ServletConfig 의 초기 파라미터들

  7. ServletContext 의 초기 파라미터들

  8. java:comp/env 의 JNDI 속성

  9. Java 시스템 속성 (System.getProperties())

  10. OS 환경 변수

  11. random.* 에만 속성이 있는 RandomValuePropertySource - ${random.value} 등으로 접근

  12. 패키지된 jar 의 외부에 있는 특정 프로필별 application properties (application-{profile}.properties 나 YAML)

  13.  jar 의 내부에 패키지 되어 있는 특정 프로필별 application properties (application-{profile}.properties 나 YAML)

  14. 패키지된 jar 의 외부에 있는 Application properties (세부적으로는 아래와 같은 위치의 application.properties 파일을 읽음. 위가 우선순위 높음)

    • 현재 디렉토리의 /config 디렉토리

    • 현재 디렉토리

    • classpath 의 /config 패키지

    • classpath 의 root

  15. jar 의 내부에 패지키 되어 있는 Application properties (위와 동일)

  16. @Configuration  클래스들의 @PropertySource annotations

  17. 기본 속성(SpringApplication.setDefaultProperties 를 설정하여 지정)

 

SPRING_APPLICATION_JSON

SPRING_APPLICATION_JSON 은 아래와 같이 사용할 수 있습니다.

$ java -Dspring.application.json='{"key":"value"}' -jar myapp.jar

 

자리표시자(Placeholders) 를 통한 Properties 이용

application.properties 의 값은 사용될 때 기존 환경을 통해 필터링되므로 이전에 정의된 값을 다시 사용할 수 있습니다.

단, 사용되는 값은 반드시 앞서 선언이 되어 있어야 합니다.

app.name=MyApp
app.description=${app.name} is a Application Name
app.detail=${app.description} 's detail


Application 에서 Properties 접근

yml, yaml, properties 파일을 통해 선언된 속성 값들은 아래와 같은 방법으로 Properties 에 접근할 수 있습니다.

  • @Value 이용
  • @ConfigurationProperties 이용
  • Environment 클래스 주입

@ConfigurationProperties 이용

외부화 구성을 통해 선언된 속성 사용에 대한 주석입니다. 일부 외부 속성 (예 : .properties 파일에서) 을 바인딩하고 유효성을 검사하려면 @Configuration 클래스의 클래스 정의 또는 @Bean 에 이를 추가합니다.

바인딩은 주석이 추가 된 클래스에서 setter 를 호출하거나 @ConstructorBinding 이 사용 중인 경우 생성자 매개 변수에 바인딩하여 수행되고 @Value와 달리 속성 값이 외부화 구성되기 때문에 SpEL 식은 사용할 수 없습니다.

# application.yml

acme:    remote-address: 192.168.1.1

    security:

        username: admin

        roles:

          - USER

          - ADMIN



# additional configuration as required

---------------------------------------------------------------

// .properties 에 acme 로 지정된 값들을 클래스로 구성한다.

@ConfigurationProperties("acme")

public class AcmeProperties {



    private boolean enabled;

    private InetAddress remoteAddress;

    private final Security security = new Security();

    public boolean isEnabled() { ... }

    public void setEnabled(boolean enabled) { ... }

    public InetAddress getRemoteAddress() { ... }

    public void setRemoteAddress(InetAddress remoteAddress) { ... }

    public Security getSecurity() { ... }

    public static class Security {

        private String username;

        private String password;

        private List<String> roles = new ArrayList<>(Collections.singleton("USER"));

        public String getUsername() { ... }

        public void setUsername(String username) { ... }

        public String getPassword() { ... }

        public void setPassword(String password) { ... }

        public List<String> getRoles() { ... }

        public void setRoles(List<String> roles) { ... }

    }

}


외부 설정을 접두어(prefix)로 묶어서 계층 구조, 맵구조를 사용할 수 있다.
이런 방법으로 얻을 수 있는 점은 아래와 같습니다.

  • 해당 클래스의 필드에 기본 값을 설정하여 기본값을 쉽게 지정할 수 있다.

  • int, double 등 String 이외의 타입을 설정 프로퍼티 클래스의 프로퍼티에 사용할 수 있다. Spring 에서 해당 타입으로 convert 한다.

 

@Value  이용

일반적인 사용 사례는 #{systemProperties.myProp} 스타일의 SpEL 표현식을 사용하여 값을 삽입하는 것입니다. 또는 ${my.app.myProp} 스타일의 Placeholders 를 사용하여 값을 삽입할 수 있습니다.

해당 annotatino 의 실제 처리는 BeanPostProcessor 나 BeanFactoryPostProcessor  에 의해 수행되며 해당 형태들에서는 @Value 를 이용할 수 없습니다.

import org.springframework.stereotype.*;

import org.springframework.beans.factory.annotation.*;

@Component
public class MyBean {

    @Value("${name}")
    private String name;
    // ...
}

Spring 의 관련 클래스에서 @Autowired 같은 주입을 통해 Environment 클래스를 지정하여 환경 변수에 접근할 수 있습니다.

Environment 클래스 이용

@Autowired
private Environment env;

...
dataSource.setUrl(env.getProperty("jdbc.url"));
반응형
LIST