프로젝트를 진행할 때, API 구현이 끝나면 로컬 환경에서 swagger로 테스트해 보고 git push 한 뒤 PR을 올리기로 했었다. PR이 승인되면 develop 브랜치에 머지하고, 배포(개발) 환경에서 잘 돌아가는지 확인하고 나서야 안심했던 기억이 있다. 로컬 환경에서 테스트할 때나 PR을 올리기 전 매번 application.yml을 수정해야 했는데, 이게 참 간단하면서도 번거로웠다.
아래에 application.yml의 일부를 가져와 봤다.
- spring.datasource.url(username, password) 부분에서 로컬 환경과 배포(개발) 환경의 값을 다르게 설정해야 정상적으로 테스트할 수 있다.
spring: # 로컬
datasource:
url: jdbc:mysql://localhost:3306/name
username: username
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
---
spring: # 배포(개발)
datasource:
url: ${DEV_MYSQL_URL}
username: ${DEV_MYSQL_USERNAME}
password: ${DEV_MYSQL_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
다음 프로젝트를 진행할 땐 이 문제를 겪고 싶지 않아서 application.yml 설명과 프로필 분리 방법에 대해 작성해보려고 한다.
참고
여기서 ${...} 부분은 Property PlaceHolders로, 환경변수에 설정한 값을 긁어온다는 의미다.
${spring.datasource.url}처럼 이미 설정한 다른 키의 값을 가져올 수도 있다.
[HaruchiApplication] - [Edit Configurations...] - [Environment variable]에 A=B; 형식으로 입력하면 A라는 환경변수에 B 값을 저장할 수 있다. (ex. AWS Access Key, AWS Secret Key)
External Configuration
1. Java API
SpringApplication은 빈 프로퍼티 setter를 갖고 있어서, 아래 코드처럼 Java API를 사용해 application을 만들 때 동작을 수정할 수 있다.
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MyApplication.class);
application.setBannerMode(Banner.Mode.OFF);
}
}
2. application.properties(yml)
직접 코드로 작성하지 않고도 spring.main.* 위치에 프로퍼티를 설정해서 Configuration을 외부화할 수 있다.
- Spring Boot 프로젝트를 만들면 src/main/resources/ 경로에 application.properties 파일이 존재한다. 이 파일에 프로퍼티를 작성하면 된다. 위에 있는 application.setBannerMode(Banner.Mode.OFF); 코드를 아래처럼 설정할 수 있다.
spring.main.banner-mode=off
- properties 확장자 대신 yml(yaml) 확장자를 쓰면 프로퍼티를 아래처럼 나타낼 수 있다. Configuration을 계층 구조로 나타내기 좋아서 자주 사용된다.
- YAML은 properties의 대안으로 사용되며, SnakeYAML 라이브러리를 classpath에 추가하면 사용할 수 있다.
- SnakeYAML은 spring-boot-starter 의존성을 추가하면 자동으로 사용할 수 있다.
spring:
main:
banner-mode: off
이때, 외부에 정의된 프로퍼티는 Java API로 설정된 값을 override한다. 예를 들어, Java API론 Banner가 나타나지 않도록 설정하고 외부 프로퍼티엔 Banner가 콘솔에 뜨도록 설정한다면 Banner가 콘솔에 뜨게 된다.
프로필 분리하기
아래 application.yml의 로컬 환경과 배포(개발) 환경 프로필을 분리해 보자.
spring: # 로컬 - local
datasource:
url: jdbc:mysql://localhost:3306/name
username: username
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
---
spring: # 배포(개발) - dev
datasource:
url: ${DEV_MYSQL_URL}
username: ${DEV_MYSQL_USERNAME}
password: ${DEV_MYSQL_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
1. Profile-specific Properties Files
로컬/배포 환경마다 application.yml 파일을 따로 만들어두는 방법이 있다.
- 파일을 만들 때 application-{profile}.yml 형식을 지켜야 한다. profile 부분에 local, dev 등 만들고 싶은 프로필의 이름을 넣으면 된다.
application.yml
- 기본 yml로 사용되며, spring.profiles.active에 설정된 프로필 이름(name)에 맞는 applicaion-name.yml을 기본 yml에 이어서 추가한다.
- 만약 src/main/resources/ 경로에 yml 디렉터리를 만들고 그 아래에 application-local.yml과 application-dev.yml을 뒀다면, spring.config.import 아래에 classpath를 입력해야 해당 파일을 찾을 수 있다.
- 여러 프로필을 하나의 그룹으로 묶어서 활성화하고 싶다면, spring.profiles.group에 {그룹명}:{프로필1, 프로필2} 형식으로 값을 넣어야 한다.
- 이후 active에 {그룹명}을 작성하면 그룹 단위로 프로필이 활성화된다.
spring:
config:
import:
- classpath:/yml/application-local.yml
- classpath:/yml/application-dev.yml
profiles:
group:
gname: dev, local
active: local
application-local.yml
spring: # 로컬 - local
config:
activate:
on-profile: local
datasource:
url: jdbc:mysql://localhost:3306/name
username: username
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
application-dev.yml
spring: # 배포(개발) - dev
config:
activate:
on-profile: dev
datasource:
url: ${DEV_MYSQL_URL}
username: ${DEV_MYSQL_USERNAME}
password: ${DEV_MYSQL_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
2. Multi-document Properties Files
파일을 여러 개 만들지 않고, 한 개의 물리적인 파일 안에 여러 개의 논리적인 문서를 생성할 수 있다.
- 문서는 위에서 아래로 순차적으로 처리되며, 더 밑에 있는 문서가 위에 정의된 문서를 override한다.
- '---' 표시로 문서의 끝을 나타낸다.
- yml 확장자 대신 properties 확장자를 사용하면 '---' 대신 '!---'나 '#---'를 사용해야 한다.
application.yml
spring:
profiles:
active: local
---
spring: # 로컬 - local
config:
activate:
on-profile: local
datasource:
url: jdbc:mysql://localhost:3306/name
username: username
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
---
spring: # 배포(개발) - dev
config:
activate:
on-profile: dev
datasource:
url: ${DEV_MYSQL_URL}
username: ${DEV_MYSQL_USERNAME}
password: ${DEV_MYSQL_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
참고
spring.profiles.active와 spring.profiles.default는 Profile-specific Files에서 사용할 수 없다. 따라서 기본 yml 같은 곳에서만 사용해야 한다. 또, spring.config.activate.on-profile로 활성화된 문서와 함께 사용할 수 없다.
3. 참고자료