[Spring Boot] 외부 설정과 프로필
스프링 부트의 외부 설정에 대해서
※ 코드는 강의에서 사용된 것과 다릅니다.
<a href = https://github.com/jaewon-ju/Learning_Spring>jaewon-ju Github Address</a>
✏️ 외부 설정이란?
하나의 애플리케이션을 여러 다른 환경에서 사용해야 할 때가 있다.
예를 들어, 현재 개발중인 【 주식 분석 어플리케이션 】 에서는 다음 두 가지의 환경이 존재할 수 있다.
- 개발 환경: 개발 서버, 개발 DB 사용
- 운영 환경: 운영 서버, 운영 DB 사용
<문제>문제>
개발 DB에 접근하려면
dev.db.com에 접속해야 하고, 운영 DB에 접근하려면prod.db.com에 접속해야 한다.
위의 문제를 해결하려면 어떻게 해야될까?
- 개발용, 운영용 코드를 각각 빌드한다.
- 이 경우, 검증 문제가 발생할 수도 있고 유연성도 떨어진다.
- 설정 값(db URL)을 실행 시점에 주입한다.
- 빌드도 한번만 하면 되고, 새로운 환경이 추가되어도 유연하게 대처할 수 있다.
2번 해결책과 같이, 실행 시점에 설정값을 주입하는 방법을 외부 설정이라 한다.
■ 외부 설정 방법
외부 설정은 일반적으로 다음 4가지 방법이 존재한다.
- OS 환경 변수
- 자바 시스템 속성
- 자바 커맨드 라인 인수
- 외부 파일
✏️ OS 환경 변수
OS 환경 변수는 해당 OS를 사용하는 모든 프로그램에서 읽을 수 있는 설정값이다.
애플리케이션에서 OS 환경 변수를 읽을 때는 다음과 같은 메소드를 사용한다.
System.getenv(): OS 환경 변수를 Map으로 조회System.getenv(key): OS 환경 변수의 값을 String으로 조회
1
2
3
4
5
6
7
8
9
10
11
@Slf4j
public class externalSet{
public static void main(String[] args){
Map<String, String> envMap = System.getenv();
for(String key : envMap.keySet()){
// 환경 변수 사용
}
}
}
OS 환경변수는 모든 프로그램에서 접근할 수 있다는 장점이자 단점을 가지고 있다.
✏️ 자바 시스템 속성
자바 시스템 속성은 실행한 JVM 안에서 접근 가능한 외부 설정이다.
자바 시스템 속성은 다음과 같이 자바 프로그램을 실행할 때, -D 옵션을 통해 설정한다.
java -Durl=dev.db.com -jar myApplication.jar- 반드시
-D옵션이-jar옵션보다 먼저 와야 한다.
어플리케이션에서 해당 속성을 사용하려면, 다음과 같은 메소드를 사용한다.
System.getProperties(): 자바 시스템 속성을Properties클래스로 반환System.getProperties(key): 특정 속성 값을 조회
1
2
3
4
5
6
7
8
9
10
11
@Slf4j
public class externalSet{
public static void main(String[] args){
Properties properties = System.getProperties();
for(Object key : properties.keySet()){
// 시스템 속성 사용
}
}
}
✏️ 커맨드 라인 인수
커맨드 라인 인수는 애플리케이션 실행 시점에, 외부 설정 값을
main()메소드의 파라미터로 넘기는 외부 설정이 방법이다.
커맨드 라인 인수는 다음과 같이 자바 프로그램을 실행할 때, 파라미터로 넘겨준다.
java -jar myApplication.jar url=dev.db.com
주의해야 할 점은, url=dev.db.com이 단어 1개로 처리된다는 것이다.
➜ Key=Value로 파싱하는 것은 개발자가 직접 해야한다.
1
2
3
4
5
6
7
8
@Slf4j
public class externalSet{
public static void main(String[] args){
for(String arg : args) {
// 커맨드 라인 인수 사용
}
}
}
■ 커맨드 라인 옵션 인수
커맨드 라인 인수를
Key=Value형식으로 파싱해주는 스프링만의 표준 방식이다.
--key=value형식으로 사용한다.java -jar myApplication.jar --url=dev.db.com- 해당 인수는
DefaultApplicationArguments클래스를 통해 파싱할 수 있다.
1
2
3
4
5
6
7
8
9
10
@Slf4j
public class externalSet{
public static void main(String[] args){
ApplicationArguments appArgs = new DefaultApplicationArguments(args);
List<String> url = appArgs.getOptionValues("url");
// --url=dev.db.com 을 자동으로 파싱한다.
// 하나의 키에 여러 값을 포함할 수 있기 때문에 List로 반환한다.
}
}
커맨드 라인 옵션 인수는 자바의 표준 기능이 아니라, 스프링의 편의 기능임을 기억하자!
✏️ 통합
위에서 알아본 3가지 방법을 떠올려 보자.
- OS 환경변수
- 자바 시스템 속성
- 커맨드 라인 인수
위의 방법들은 모두 key=value로 외부 설정을 가져온다.
key=value를 사용한다는 것을 같지만, 사용하는 메소드는 각각 다르다!
➜ 불편해
이러한 불편함을 해결하기 위해, 스프링은 Environment라는 인터페이스로 모든 설정 정보를 조회할 수 있는 기능을 제공한다.
- OS 환경변수 ➜
ResourcePropertySource클래스에 저장- 자바 시스템 속성 ➜
SystemEnvironmentPropertySource클래스에 저장- 커맨드 라인 옵션 인수 ➜
CommandLinePropertySource클래스에 저장
Environment인터페이스로 각 클래스에 접근해서key=value방식으로 외부 설정을 조회할 수 있다.
이후에 배울 【 외부 파일 】 방식에도 똑같이 적용가능하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Slf4j
@RequiredArgsConstructor
@Component
public class testClass {
private final Environment env;
@PostConstruct
public void init() {
String url = env.getProperty("url");
log.info("env url={}", url);
}
}
// OS, 커맨드 라인, 시스템 설정, 외부 파일 등 어떤 방식을 사용하더라도 Environment로 조회 가능
✏️ 외부 파일
앞서 배운 방법들은, 설정하는 key=value 값들이 늘어날수록 사용하기 불편해진다.
➜ 설정들을 외부 파일로 분리한 다음, 애플리케이션 로딩 시점에 해당 파일을 읽어오는 방식을 사용한다.
개발서버 application.properties 파일
1 url = dev.db.com
운영 서버 application.properties 파일
1 url = prod.db.com
- 각 서버에서 위와 같이
application.properties파일을 생성한 뒤, 똑같은 key(url) 값에 다른 value를 넣어놓는다. -
해당 파일을 빌드된 jar 파일
myApplication.jar과 동일한 위치에 놓는다. - 애플리케이션을 실행한 뒤에
application.properties를 읽는다. Environment인터페이스를 사용한다.
단점
- 외부 설정 파일 자체를 관리하기가 번거롭다
- 설정 값의 변경 이력을 확인하기 어렵다.
■ 내부 파일
설정 파일을 외부에서 관리하는 것은 상당히 번거롭다. ➜ 설정 파일 자체를 프로젝트 내부에 포함해서 빌드한다.
main/resources에 다음 파일을 추가한다.
application-dev.properties 파일
1 url = dev.db.com
application-prod.properties 파일
1 url = prod.db.com
애플리케이션 실행 시점에 내부에서 설정 파일을 선택한다.
⚠️ 대신, 외부에서 개발 환경인지, 운영 환경인지는 프로필을 통해 알려줘야 한다.
ex) dev 프로필이 넘어오면 application-dev.properties를 설정 정보로 사용
프로필은 다음과 같은 방법으로 애플리케이션에 넘길 수 있다.
--spring.profiles.active=dev-Dspring.profiles.active=prod
■ 내부 통합 파일
내부 설정 파일을 하나의 물리적인 파일로 통합할 수 있다.
application.properties 파일
1 2 3 4 5 6 7 url = local.db.com #--- spring.config.active.on-profile=dev url = dev.db.com #--- spring.config.active.on-profile=prod url = prod.db.com
#---을 사용해서 논리적으로 파일을 분리할 수 있다.!---도 가능하다.- yml 파일에서는
---로 분리한다.
- 프로필을 지정하지 않으면
default라는 이름의 프로필이 활성화 된다.spring.config.active.on-profile를 지정하지 않으면default프로필로 인식된다.
✏️ 우선순위
아래로 갈수록 우선순위가 높다.
- 설정 데이터(
application.properties) - OS 환경변수
- 자바 시스템 속성
- 커맨드 라인 옵션 인수
@TestPropertySource
설정 데이터 내부에서는 다음과 같이 우선순위가 적용된다.
- jar 내부
application.properties - jar 내부 프로필 적용 파일
application-{profile}.properties - jar 외부
application.properties - jar 외부 프로필 적용 파일
application-{profile}.properties
우선순위의 규칙
- 더 유연한 것이 우선권을 가진다.
- 범위가 좁은 것이 우선권을 가진다.