[Springboot] 24. Externalized Configuration

2022. 10. 14. 14:35JAVA/Spring

43a2795a063e8ce4b6ce79144fd44add
155352484
-3143923589894034969
8
4fc7f846-5653-42c7-a95c-d64b0425aeae
16191

1. 사용할 수 있는 외부 설정

  • properties
  • YAML
  • 환경 변수
  • 커맨드 라인 매개변수

2. 프로퍼티 우선순위

  1. 유저 홈 디렉토리에 있는 spring-boot-dev-tools.properties
  2. 테스트 코드에 있는 @TestPropertySource 애노테이션
  3. 테스트 코드에 있는 @SpringBootTest 애노테이션의 properties 속성
  4. 커맨드 라인 매개변수들
  5. SPRING_APPLICATION JOSN(환경 변수 도는 시스템 속성에 내장된 JSON 형식)의 프로퍼티들
  6. ServiceConfig 파라미터들
  7. ServletContext 파라미터들
  8. "java:comp/env" JNDI 속성들
  9. 자바 시스템 프로퍼티들(System.getProperties())
  10. OS 환경 변수들
  11. RandomValuePropertySource
  12. JAR 밖에 있는 특정 프로파일용 application properties
  13. JAR 안에 있는 특정 프로파일용 application properties
  14. JAR 밖에 있는 application properties
  15. JAR 안에 있는 application properties (resources/application.properties)
  16. @PropertySource
  17. 기본 프로퍼티(SpringApplication.setDefaultProperties)

 

3. 프로퍼티 참조(@Value)

프로퍼티를 참조하기 위해서는 @Value 애노테이션을 사용하면 됩니다.

1. resources/application.properties 파일에 참조하고 싶은 속성을 정의합니다.

yonghwan.name="YongHwan"

2. @Value 애노테이션을 적용한 필드 멤버를 정의합니다.

@Component
public class SampleRunner implements ApplicationRunner {

    @Value("${yonghwan.name}")
    private String name;
    
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("name is " + name);
    }
}

 

3. SpringApplication을 실행하여 결과를 확인합니다.

name is YongHwan

 

4. 테스트 코드에 있는 @TestPropertySource 애노테이션

@TestPropertySource 애노테이션은 테스트 코드에서 사용하며, 테스트에서만 사용하는 속성들을 참조할때 유용한 애노테이션입니다.

 

1. test/resources/test.properties 정의

yonghwan.name=YongHwan
yonghwan.age=20

 

2. 테스트 코드 정의하고 실행하여 테스트가 통과되는지 확인

@TestPropertySource(locations = {"classpath:/application.properties", "classpath:/test.properties"})
@SpringBootTest
public class SpringBootApplicationTest {
    
    @Value("${yonghwan.name}")
    private String name;

    @Test
    public void test(){
        //given

        //when
        String actual = name;
        //then
        assertThat(actual).isEqualTo("YongHwan");
    }
  • @TestPropertySource 애노테이션은 프로퍼티들을 문자열 배열로 직접 명세하는 방법도 있지만 locations 옵션을 이용해서 특정 파일을 프로퍼티 파일로 명세할 수 있습니다.

 

 

5. main 코드와 test 코드의 application.properties 파일 주의사항

예를 들어 main/resources/application.properties 파일을 정의하고 test/resources/application.properties 파일을 동일하게 정의한 경우 빌드시 테스트 디렉토리의 application.properties 파일이 main 디렉토리의 application.properties을 덮어쓰게 됩니다. 이유는 빌드시 main 디렉토리를 classpath에 놓기 때문입니다.

 

위와 같은 문제를 해결하기 위해서는 테스트 디렉토리의 application.properties 파일명을 다른 파일명으로 변경하고 @TestPropertySource 애노테이션의 locations 옵션을 사용하여 지정하는 것이 적절한 방법입니다.

 

만약 파일명을 동일하게 한 경우 main 디렉토리의 소스코드가 테스트 디렉토리의 application.properties 파일의 프로퍼티를 참조하게 되어 없는 속성을 참조하여 컴파일 오류가 발생할 수 있습니다.

 

6. 랜덤 값 설정하기

RandomValuePropertySource는 랜덤 값을 주입하는데 유용합니다. 랜덤 값은 Integers, Long, uuids, strings 타입을 생성할 수 있습니다.

my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}

 

1. 테스트 코드를 정의합니다.

@TestPropertySource(locations = {"classpath:/application.properties", "classpath:/test.properties"})
@SpringBootTest
public class SpringBootApplicationTest {

    @Value("${my.secret}")
    private String mySecret;

    @Value("${my.number}")
    private long myNumber;

    @Value("${my.bignumber}")
    private long myBigNumber;

    @Value("${my.uuid}")
    private String myUuid;

    @Value("${my.number.less.than.ten}")
    private long myNumberLessThanTen;

    @Value("${my.number.in.range}")
    private long myNumberInRange;

    @Test
    public void randomValueTest(){
        //given

        //when
        String actual1 = mySecret;
        long    actual2 = myNumber;
        long    actual3 = myBigNumber;
        String actual4 = myUuid;
        long    actual5 = myNumberLessThanTen;
        long    actual6 = myNumberInRange;
        //then
        System.out.println(actual1);
        System.out.println(actual2);
        System.out.println(actual3);
        System.out.println(actual5);
        System.out.println(actual4);
        System.out.println(actual6);
    }

}
43a2795a063e8ce4b6ce79144fd44add
155352484
-3143923589894034969
8
4fc7f846-5653-42c7-a95c-d64b0425aeae
16191

 

 

7. Command Line Properties에 접근하기

커맨드 라인에 "--server.port=9000"와 같은 형식으로 매개변수를 정의하면 속성으로 저장됩니다.

@Value("${server.port}")
private int port;
$ java -jar .\springboot_utilization-0.0.1-SNAPSHOT.jar --server.port=9000

 

8. application.properties 파일 우선순위

  1. 프로젝트 디렉토리/config/application.properties (우선순위 제일 높음)
  2. 프로젝트 디렉토리/application.properties
  3. classpath/config/application.properties
  4. classpath/application.properties

 

References

https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/boot-features-external-config.html#boot-features-external-config