자주 사용되는 객체나 메서드, 설정에 대해서는 Spring Configuration을 이용해 빈(Bean)을 스프링 컨테이너에 등록해 사용합니다.
그러나 환경 변수를 선언하고 이를 빈 컨테이너에 등록해 사용하는 방법도 있습니다.
프로젝트를 진행하는 도중 여러 환경 변수가 필요한 때가 있습니다.
(예: OAuth2.0 로그인을위해 필요한 시크릿 키를 설정해야 할 때, 혹은 Google SMTP를 사용하기위해 포트번호나 username, password의 등록이 필요할 때, CORS 설정을 config 이곳 저곳에 해 두었는데 여기 할당할 도메인이나 아이피를 전역변수로 편하게 관리하고 싶을 때 등)
이를 위해 스프링 프로젝트의 설정파일인 .properties 혹은 .yml에서 환경변수 설정방법을 알아봅니다.
아래와 같은 흐름으로 설명합니다.
1. .properties? .yml?
2. 환경변수 설정하기
3. 환경변수 사용하기
1. .properties ? .yml ?
두 파일형식 모두 보통 application.properties 혹은 application.yml의 형태로 프로젝트 경로(src/main/resources)에 포함되게 됩니다. 딱히 Maven이나 Gradle처럼 빌드도구를 달리한다고 해서 파일형태식이 지정되는 것이 아니라, 프로젝트의 성격에 따라 개발자가 프로젝트 생성 단계에서 정하게 됩니다.
두 파일형식의 차이는 아래와 같습니다.
a. properites 파일형식
- Key-Value pair 형식: 키와 값을 = 또는 ;로 구분합니다.
- 계층구조의 표현은 .을 통해 나타냅니다.
- 주석은 #을 사용합니다.
- 배열을 나타낼 때는 중복된 키를 사용합니다.
# 서버설정 properties
server.port=8080
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=admin
spring.datasource.password=secret
# 배열
spring.datasource.config[0]=jdbc:mysql://host1:3306/db1
spring.datasource.config[1]=jdbc:mysql://host2:3306/db2
b. yml 파일형식 (YAML: YAML Ain't Markup Language)
- :으로 키와 값을 구분합니다.
- 계층구조의 표현은 들여쓰기를 통해 나타냅니다.
- 주석은 #을 사용합니다.
- 배열을 나타낼 때는 -기호를 사용합니다.
# 서버설정 properties
server:
port: 8080
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: admin
password: secret
# 배열
spring:
datasource:
config:
- jdbc:mysql://host1:3306/db1
- jdbc:mysql://host2:3306/db2
- Spring boot에서는 환경별 설정파일을 이용해 환경에 따라 다른 설정을 적용할 수 있습니다.
(예: 로컬개발환경에서의 파일경로설정 → C:\...(윈도우), 배포환경에서의 파일경로설정 → /home/user/...(리눅스))
.properties 파일형식을 사용하는 경우, 다음과 같은 규칙으로 환경별 설정 파일을 정의할 수 있습니다.
(한 파일에서 관리할 수도 있으나, 개별파일로 작성하는것이 관리에 더 유리합니다.)
application-{profile}.properties
- application.properties: 기본 설정
- application-dev.properties: 개발 환경
- application-prod.properties: 운영 환경
- application-test.properties: 테스트 환경
이후 기본설정파일에 spring.profiles.active=dev 형식으로 작성해 어떤 환경의 설정파일을 적용할 지 정할 수 있습니다.
(중복되는 설정이 있다면 기본 설정위에 활성화된 설정파일이 덮어씌워집니다.)
.jar 파일을 실행할땐 CLI환경에서 java -jar 파일명.jar -Dspring.profiles.active=dev 형식으로 설정파일을 적용해 실행할 수 있습니다.
.yml 파일형식을 사용하는 경우에도 환경별 설정을 한 파일에서 혹은 개별 파일로 관리할 수 있습니다.
- application.yml: 기본 설정
- application-dev.yml: 개발 환경
- application-prod.yml: 운영 환경
- application-test.yml: 테스트 환경
어떤 기준으로 설정파일 형식을 정하고, 어떻게 관리할 것 인가 ?
- 환경별 설정 파일 개수가 많아지는 경우 → 파일을 개별로 나누어 관리하는 것이 용이합니다.
- properties 형식과 yml 형식의 차이는 다음과 같습니다.
- 개별 파일 관리가 기본적이고 권장되는 경우 → properties 형식: 계층구조 표현이 키-값 형태라 설정이 복잡해지는 경우, 하나의 파일에 모든 설정을 작성하면 읽기가 굉장히 어려워집니다.
- yml형식: 계층구조 표현이 읽기 용이해 하나의 파일 안에서 관리가 쉬울것으로 판단되는 경우. 그러나 계층구조 표현이 읽기 쉬워도, 설정이 많아지면 개별파일로 관리하는 것이 용이합니다.
Relaxed Binding
: 위의 예시들에서 모든 환경변수가 소문자로 작성되었는데, 본래는 Windows OS에서는 대소문자와 . _ 구분에 상관없이 환경변수에 따른 설정이 잘 적용됩니다.
그러나 Linux/Mac OS에서는 환경변수이름을 대문자로 작성해야하며 .대신 _기호를 사용하는 것이 안전합니다.
다만, Spring Boot에서 지원(2.4 이상에서 더 강화되었음)하는 Relaxed Binding 기능이 다양한 형식의 매핑을 지원합니다. Docker 컨테이너 역시도 대소문자에 관대합니다.
다만, 권장사항은 '환경변수는 대문자에 _기호를 조합해 작성하는 것이 가장 안전.' 입니다.
2. 환경 변수 설정하기
환경변수는 파일형식에 따라 아래와 같이 설정할 수 있습니다.
# properties 파일 환경변수 설정
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=admin
# yml 파일 환경변수 설정
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: admin
사용할 환경변수의 성격에 따라 개발자 임의로 이름을 짓고, 값을 할당할 수 있습니다.
그런데, 이미 존재하는 환경변수에 임의로 작성하게 된다면 어떻게 될까요 ?
예를들어, spring.jpa.hibernate.ddl-auto라는 JPA관련 환경변수 설정과 개발자가 임의로 작성할 환경변수 이름이 겹친다고 가정해보겠습니다.
Spring Boot는 설정값을 가져올 때 아래와 같은 순서를 따릅니다.
- 명령줄 인자(--spring.jpa.hibernate.ddl-auto=none)
- JVM 옵션(-Dspring.jpa.hibernate.ddl-auto=none)
- 환경변수(SPRING_JPA_HIBERNATE_DDL_AUTO=NONE)
- application.properties 또는 application.yml
- 기본 설정 값(스프링 내부 기본 값)
따라서 우선순위가 높은곳에 정의된 값이 우선으로 적용됩니다.
# application.properties 파일에서의 설정
spring.jpa.hibernate.ddl-auto=create
# 환경변수에서의 설정
export SPRING_JPA_HIBERNATE_DDL_AUTO=update
# 명령어 실행
java -jar myapp.jar
환경마다 각 설정값이 다르게 설정해 실행하면, 환경변수에서의 설정이 설정파일에서의 설정보다 높은 우선순위를 가져 해당 옵션은 update로 설정됩니다.
3. 환경변수 사용하기
예시: Google SMTP를 이용해 이메일을 보내려고 합니다.
SMTP 설정법에 따라 host, port, username, password 등을 설정파일에 작성해서 설정파일로 사용하려고 합니다.
# Google SMTP 설정 (properties 파일 내부)
spring.mail.host = smtp.gmail.com
spring.mail.port = 587
spring.mail.username = 이메일 작성부분
spring.mail.password = 비밀번호 작성 부분
spring.mail.properties.mail.smtp.auth = true
spring.mail.properties.mail.smtp.starttls.enable = true
spring.mail.properties.mail.smtp.starttls.required = true
spring.mail.properties.mail.smtp.ssl.trust = smtp.gmail.com
spring.mail.properties.mail.smtp.ssl.enable = true
이를 EmailConfig.java라는 설정 클래스 파일에서 다음과 같이 사용할 수 있습니다.
@Configuration
public class EmailConfig {
// SMTP 이메일 전송을 위한 설정클래스
@Value("${spring.mail.host}")
private String host;
@Value("${spring.mail.port}")
private int port;
@Value("${spring.mail.username}")
private String username;
@Value("${spring.mail.password}")
private String password;
....
}
혹은, Environment 객체를 통해 전역 변수를 프로그램 내에서 직접 읽어오는 방법도 있습니다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@Component
public class EnvironmentReader {
@Autowired
private Environment environment;
public String getAppName() {
return environment.getProperty("app.name");
}
public String getAppVersion() {
return environment.getProperty("app.version");
}
}
'Java > Spring Framework' 카테고리의 다른 글
| 유효성 검사, Validation (2) (7) | 2025.01.03 |
|---|---|
| 유효성 검사, Validation (1) (4) | 2025.01.02 |


