외부 설정이란?
하나의 애플리케이션을 여러 다른 환경에서 사용해야 할 때가 있다. 문제는 환경마다 설정 값이 따로 존재하는데, 이때 애플리케이션을 실행할 때 필요한 여러 설정 값들을 어플리케이션 외부 또는 내부에 정의할 수 있는 기능을 말한다.
외부 설정 4가지 방법
- OS 환경 변수 - OS에서 지원하는 외부 설정, 해당 OS를 사용하는 모든 프로세스에서 사용
- 자바 시스템 속성 - 자바에서 지원하는 외부 설정, 해당 JVM안에서 사용
- 자바 커맨드 라인 인수 - 커맨드 라인에서 전달하는 외부 설정, 실행시 main(args) 메서드에서 사용
- 외부 파일(설정 데이터): 프로그램에서 외부 파일을 직접 읽어서 사용
- 애플리케이션에서 특정 위치의 파일을 읽도록 해둔다. 예)
data/hello.txt
- 그리고 각 서버마다 해당 파일안에 다른 설정 정보를 남겨둔다.
- 개발 서버 hello.txt : url=dev.db.com
- 운영 서버
hello.txt : url=prod.db.com
외부 설정 - OS 환경 변수
OS 환경 변수(OS environment variables)는 해당 OS를 사용하는 모든 프로그램에서 읽을 수 있는 설정값이다. 한마디로 다른 외부 설정과 비교해서 사용 범위가 가장 넓다.
외부 설정 - 자바 시스템 속성
자바 시스템 속성(Java System properties)은 실행한 JVM 안에서 접근 가능한 외부 설정이다. 추가로 자바가 내부에서 미리 설정해두고 사용하는 속성들도 있다.
- Jar 실행
- java -Durl=dev -jar app.jar
- IDE에서 실행시 VM 옵션 추가
- -D VM 옵션을 통해서 key=value 형식을 주면 된다.
외부 설정 - 커맨드 라인 인수
커맨드 라인 인수(Command line arguments)는 애플리케이션 실행 시점에 외부 설정값을 main(args) 메서드의 args 파라미터로 전달하는 방법이다.
- Jar 실행
- 예) java -jar app.jar dataA dataB
- 필요한 데이터를 마지막 위치에 스페이스로 구분해서 전달하면 된다. 이 경우 dataA , dataB 2개의 문자가 args 에 전달된다.
- IDE에서 실행시 커맨드 라인 인수 추가
- dataA dataB
- 커맨드 라인 인수는 공백(space)으로 구분한다.
하지만 커맨드 라인 인수는 파싱되지 않은 통 문자 형식으로 key=value 형식으로 사용하기 위해선 스프링에서 정의한 커맨드 라인 옵션 인수를 사용한다.
커맨드 라인 옵션 인수
일반적인 커맨드 라인 인수
aaa bbb -> [aaa, bbb] 값 2개
hello world -> [hello, world] 값 2개
"hello world" -> [hello world] (공백을 연결하려면 "를 사용하면 된다.) 값 1개
key=value -> [key=value] 값 1개
스프링에서는 커맨드 라인 인수를 key=value 형식으로 편리하게 사용할 수 있도록 스프링 만의 표준 방식을 정의했는데, 그것이 바로 커맨드 라인 옵션 인수이다.
--key=value 형식으로 사용한다.
--username=userA --username=userB 하나의 키에 여러 값도 지정할 수 있다.
외부 설정 - 스프링 통합
커맨드 라인 옵션 인수, 자바 시스템 속성, OS 환경변수는 모두 외부 설정을 key=value 형식으로 사용할 수 있다. 하지만 어디에 있는 외부 설정값을 읽어야 하는지에 따라서 각각 읽는 방법이 다르다는 단점이 있다. 스프링은 이 문제를 Environment 와 PropertySource 라는 추상화를 통해서 해결한다
스프링의 외부 설정 통합

PropertySource
- org.springframework.core.env.PropertySource
- 스프링은 PropertySource 라는 추상 클래스를 제공하고, 각각의 외부 설정를 조회하는 XxxPropertySource 구현체를 만들어두었다.
- 스프링은 로딩 시점에 필요한 PropertySource 들을 생성하고, Environment 에서 사용할 수 있게 연결해둔다.
Environment
- org.springframework.core.env.Environment
- Environment 를 통해서 특정 외부 설정에 종속되지 않고, 일관성 있게 key=value 형식의 외부 설정에 접근할 수 있다.
- environment.getProperty(key) 를 통해서 값을 조회할 수 있다.
- Environment 는 내부에서 여러 과정을 거쳐서 PropertySource 들에 접근한다.
- 같은 값이 있을 경우를 대비해서 스프링은 미리 우선순위를 정해두었다.
- 모든 외부 설정은 이제 Environment 를 통해서 조회하면 된다.
우선순위
우선순위는 위에서 아래로 적용된다. 아래가 더 우선순위가 높다.
자주 사용하는 우선순위
- 설정 데이터( application.properties )
- OS 환경변수
- 자바 시스템 속성
- 커맨드 라인 옵션 인수
- @TestPropertySource (테스트에서 사용)
설정 데이터 우선순위
- jar 내부 application.properties
- jar 내부 프로필 적용 파일 application-{profile}.properties
- jar 외부 application.properties
- jar 외부 프로필 적용 파일 application-{profile}.properties
우선순위 이해 방법
- 더 유연한 것이 우선권을 가진다. (변경하기 어려운 파일 보다 실행시 원하는 값을 줄 수 있는 자바 시스템 속성이 더 우선권을 가진다.)
- 범위가 넒은 것 보다 좁은 것이 우선권을 가진다.
- OS 환경변수 보다 자바 시스템 속성이 우선권이 있다.
- 자바 시스템 속성 보다 커맨드 라인 옵션 인수가 우선권이 있다.