프로젝트 환경 분리하기
- 설정 파일을 local(로컬), dev(개발), prod(운영) 세가지 환경에 맞추어 분리 해보자.
- Spring profile, Gradle(Maven) profile 대해 araboza.
프로젝트 생성
- spring initializer : springboot 2.5.4
- dependency
implementation 'org.springframework.boot:spring-boot-starter-web'
1. Spring Profile
- Spring Profile은 런타임 시 지정한 profile 값에 따라서 각 설정 파일을 로드 하도록 할 수 있다.
- 스프링 부트에서는 기본적으로 실행 시 resource 폴더에서 application.properties(yml)를 찾아 로드한다.
- 다음으로 profile 값이 있다면 application-${profile}.properties(yml) 파일을 찾아 로드한다.
- 설정 파일 내부의 설정 값들은 가장 마지막에 로드한 값으로 오버라이드 된다.
- profile 값을 넘겨주지 않으면 기본 값은 default 이다.
application.yml
- application.yml을 가장 먼저 로드 하므로 공통으로 사용할 설정 값을 지정 하거나 기본값(local)을 설정하고 profile 값이 있다면 다음 설정 파일에서 오버라이드 해서 사용 할 수도 있다.
- 개인적으로 명확한 분리를 위해서 공통 값만 사용하는 것이 좋은 것 같다.
- profile 기본 값을 local로 설정 하기 위해 profile 값을 local로 지정 한다.
spring:
profiles:
active: local
common: common
test: common
application-local.yml
test: local
application-dev.yml
test: dev
application-prod.yml
test: prod
LogApplication.java
- 애플리케이션 실행 시 common, test값을 출력해 보자
@SpringBootApplication
public class LogApplication {
@Value("${common}")
private String common;
@Value("${test}")
private String test;
public static void main(String[] args) {
SpringApplication.run(LogApplication.class, args);
}
@PostConstruct
private void start() {
System.out.println("common = " + common);
System.out.println("test = " + test);
}
}
빌드 및 실행
./gradlew bootJar
- 빌드 후 모든 설정파일이 컴파일 된 것을 확인 할 수 있다.
- jar 실행 시 지정한 profile 값에 따라서 각 파일이 로드 된다.
- 기본 값으로 실행
- application.yml, application-local.yml 파일이 로드
- 후에 로드된 application-local.yml 파일의 test 값이 우선순위를 가지게 되어 local 출력
java -jar build/libs/log-0.0.1-SNAPSHOT.jar
java -jar -Dspring.profiles.active=local build/libs/log-0.0.1-SNAPSHOT.jar
2. Gradle profile
- 지금까지는 각 환경에서 모두 필요하지 않지만 모든 설정파일을 컴파일 한 후 실행 시점에서 원하는 값을 로딩 했다.
- Gradle profile 설정을 하면 각 profile 값에 해당하는 설정 파일만 컴파일 할 수 있다.
- build.gradle 설정을 추가한다.
- 기본적으로 컴파일 시 resource 디렉토리에서 리소스 들을 찾지만 찾을 리소스 디렉토리를 추가 한다.
...
ext.profile = (!project.hasProperty('profile') || !profile) ? 'local' : profile
sourceSets {
main {
resources {
srcDirs "src/main/resources-env/${profile}"
}
}
}
- 각 파일을 다음과 같이 옮겨보자.
빌드 및 실행
기본값으로 빌드
./gradlew clean bootjar
- 로컬 설정 파일만 컴파일 된 것을 확인 할 수 있다.
기본값으로 실행
java -jar build/libs/log-0.0.1-SNAPSHOT.jar
profile 값 지정하여 빌드
./gradlew clean bootjar -Pprofile=dev
- dev 파일만 컴파일 된다.
profile 값 지정하여 실행
java -jar -Dspring.profiles.active=dev build/libs/log-0.0.1-SNAPSHOT.jar
profile include
- profile을 중복해서 사용할 수 있다.
- 지금까지 profile 별로 컴파일 하여 실행하였다.
- 만약 dev로 컴파일 하고 jar 실행 할 때 dev값을 넣어 주지 않는다면 기본값이 local이므로 application-dev.yml 파일은 로드 되지 않을 것이다.
- profile값을 적기 귀찮다면 profile include를 써보자. (배포 환경에서는 배포스크립트를 작성하여 해결 가능..)
- 구조 변경
application-common.yml
common: common
test: common
application.yml
- 각각 다음과 같이 변경
- 공통으로 들어갈 설정값은 application-common에 넣는다.
spring:
profiles:
include: common
active: dev(or local or prod)
test: dev(or local or prod)
빌드 및 실행
./gradlew clean bootjar -Pprofile=dev
-
다음과 같이 컴파일 되었다.
-
실행
java -jar build/libs/log-0.0.1-SNAPSHOT.jar
- 실행 결과 profile값이 common, dev 둘다 적용되었다.
- 주의할 점이 있다면 application.yml이 실행되고 include된 application-common.yml의 우선순위가 높기 때문에 test값이 common 이 출력되었다.
- common에는 중복값이 없도록 하는 것이 좋겠다..
Gradle을 잘 다루면 Gradle 설정으로 디테일 하게 원하는 대로 빌드가 가능할 것 같다.
안녕하세요.
application.yml을 가장 먼저 로드 하는 것이 아니라 bootstrap.yml을 가장 먼저 로드 하고 그 다음
application.yml을 로드하는 것이 아닌가요?