Spring 의 Properties

Spring 의 Properties

Spring 과 Spring Boot 에서 프로퍼티를 세팅하고 사용하는 방법을 알아보자

Properties 파일 불러오기

Annotation 방식

우선 Spring 3.1 에서 소개된 @PropertySource 어노테이션을 이용하여 properties 파일을 불러오고, 사용할 수 있다.
@PropertySource 은 @Configuration 과 함께 사용되어야 한다.

@Configuration
@PropertySource("classpath:foo.properties")
public class PropertiesWithJavaConfig {
//...
}

런타임에 동적으로 파일을 선택할 수도 있다.

@PropertySource({ 
"classpath:persistence-${envTarget:mysql}.properties"
})
...

와 같이 작성하면 구동 환경에 따라 여러개의 properties 파일을 만들어 두고, 실행시 간편하게 선택할 수 있다.

여러개의 파일을 지정할 수도 있다.

@PropertySource("classpath:foo.properties")
@PropertySource("classpath:bar.properties")
public class PropertiesWithJavaConfig {
//...
}

Java 7 이하라면 아래와 같이도 할 수 있다

@PropertySources({
@PropertySource("classpath:foo.properties"),
@PropertySource("classpath:bar.properties")
})
public class PropertiesWithJavaConfig {
//...
}

만약 property 이름이 중복되는 경우에는 나중에 로드된 property 가 우선권을 갖는다.

XML 방식

<context:property-placeholder location="classpath:foo.properties, classpath:bar.properties"/>

Properties 사용/주입 하기

파일로부터 불러온 Properties 를 사용하는 방법은 여러가지다.

  • @Value 어노테이션
  • XML 에서 bean 설정
  • Environment API

@Value 어노테이션

@Value( "${jdbc.url}" )
private String jdbcUrl;

디폴트 값을 설정할 수도 있다.

@Value( "${jdbc.url:aDefaultUrl}" )
private String jdbcUrl;

in XML

<bean id="dataSource">
<property name="url" value="${jdbc.url}" />
</bean>

Environment API

@Autowired
private Environment env;
...
dataSource.setUrl(env.getProperty("jdbc.url"));

Spring Boot 에서 Properties 불러오기

스프링 부트에서는 간편한 설정(부트의 주 목표 중 하나)을 위해 추가 기능을 지원한다.

디폴트 프로퍼티 파일

부트에서는 디폴트 프로퍼티 파일로 src/main/resources 내의 application.properties 를 사용한다.
그러므로 @PropertySource 를 등록해 줄 필요가 없다.
또한, 만일 다른 프로퍼티 파일을 사용해야 한다면 런타임에 지정해줄 수도 있다.

java -jar app.jar --spring.config.location=classpath:/another-location.properties

Spring Boot 2.3 부터는 프로퍼티 파일 지정에 와일드카드도 사용할 수 있다.

java -jar app.jar --spring.config.location=config/*/

환경별 프로퍼티 파일

“src/main/resources” 디렉터리 안에 “application-environment.properties” 의 형태로 파일을 만들어두고
profile 을 해당 environment 와 같은 이름으로 설정해주면
디폴트 properties 가 로드된 이후에 해당 profile-specific 한 properties 파일인 application-environment.properties가 로드된다.
나중에 로드된 properties 가 높은 우선순위를 가지므로 중복된 프로퍼티는 profile-specific 프로퍼티를 따른다.

@TestPropertySource 어노테이션

테스트 시에 다음과 같이 디폴트 property 보다 높은 우선순위로 특정 property 파일을 로드할 수 있다.

@RunWith(SpringRunner.class)
@TestPropertySource("/foo.properties")
public class FilePropertyInjectionUnitTest {

@Value("${foo}")
private String foo;

@Test
public void whenFilePropertyProvided_thenProperlyInjected() {
assertThat(foo).isEqualTo("bar");
}
}

파일을 사용하기 싫다면 다음과같이 바로 name 과 value 를 줄 수도 있다.

@RunWith(SpringRunner.class)
@TestPropertySource(properties = {"foo=bar"})
public class PropertyInjectionUnitTest {

@Value("${foo}")
private String foo;

@Test
public void whenPropertyProvided_thenProperlyInjected() {
assertThat(foo).isEqualTo("bar");
}
}

또한, @SpringBootTest 어노테이션의 properties 인자로도 동일한 효과를 낼 수 있다.

@RunWith(SpringRunner.class)
@SpringBootTest(
properties = {"foo=bar"}, classes = SpringBootPropertiesTestApplication.class)
public class SpringBootPropertyInjectionIntegrationTest {

@Value("${foo}")
private String foo;

@Test
public void whenSpringBootPropertyProvided_thenProperlyInjected() {
assertThat(foo).isEqualTo("bar");
}
}

계층형 프로퍼티

@ConfigurationProperties 로 여러 프로퍼티를 하나의 자바 객체로 묶을 수 있다.

database.url=jdbc:postgresql:/localhost:5432/instance
database.username=foo
database.password=bar

의 경우에는 아래와 같은 형태의 객체로 매핑할 수 있다.

@ConfigurationProperties(prefix = "database")
public class Database {
String url;
String username;
String password;

// standard getters and setters
}

YAML 파일

properties 파일과의 차이점은 확장자가 다르다는 것과 SnakeYAML 라이브러리에 대한 의존성이 classpath 에 있어야 한다는 것이다.

명령행 인자

파일을 사용하지 않고 명령행 인자로 바로 프로퍼티를 줄 수도 있다.

java -jar app.jar --property="value"
java -Dproperty.name="value" -jar app.jar

환경변수

스프링 부트는 환경변수도 감지하여 프로퍼티로 취급한다.

export name=value
java -jar app.jar

Raw Bean

PropertyPlaceholderConfigurer(스프링 3.0), 혹은 PropertySourcesPlaceholderConfigurer(스프링 3.1) 을 사용하는 방법도 있다.
장황하며 대부분의 경우 불필요하지만, 직접 property configuration bean 을 정의하여 configuration 을 완벽하게 제어할 수가 있다.
여기서는 다루지 않겠다.

참조: https://www.baeldung.com/properties-with-spring

Comments