환경 변수 관리
✒️ 2025-07-24 18:40 내용 수정
프로젝트 설정 파일
1. properties 파일
- 참고 자료 : 위키백과 .properties
- 파라미터를 문자열의 일부로 저장하며, 한 문자열은 key 값을, 다른 문자열은 value를 저장한다.
# key=value
spring.datasource.url=jdbc:postgresql:/localhost:5432/postgres
spring.datasource.username=user
spring.datasource.password=password
2. yml 파일
- 참고 자료 : 위키백과 yaml
- 공백 문자를 사용한 들여쓰기로 구조체를 구분한다.
spring:
datasource:
url: jdbc:postgresql:/localhost:5432/postgres
username: user
password: password
환경 변수
환경 변수 작성 방법
- 기본 형식은
${...}로 환경 변수 이름을 작성한다.
# 기본 문법
property: ${ENV_VARIABLE}
- 기본값 설정 : 환경 변수 값이 없을 때의 기본값 설정을
${..:default}처럼:다음에 지정할 수 있다.
# 기본값 지정
property: ${ENV_VARIABLE:defaultValue}
- 환경 변수 값이 설정되지 않을 때 Spring에서 해당 Property의
@Value를 null로 처리하고 싶다면${..:#{null}}로 사용한다.
# 필수값 (없으면 에러)
property: ${ENV_VARIABLE:#{null}}
env 파일
.env파일은 github에 올라가면 안되는 중요한 파일이다..gitignore에.env파일을 추가해서 github에 올라가는 것을 방지한다..env파일은 보안 설정된 메일이나 기타 안전한 환경에서 공유한다.
# .gitigonre에 등록
### .env 파일 ###
.env
# .env
# Spring Boot 설정
SPRING_PROFILES_ACTIVE=dev
SERVER_PORT=8080
# 데이터베이스 설정
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp
DB_USER=myuser
DB_PASSWORD=secretpassword
# 기타 API 키
GOOGLE_API_KEY=api_key
우선순위 설정
- 설정 방식에 따른 우선 순위
| 순위 | 설정 방식 | 설명 |
|---|---|---|
| 1 | Devtools 전역 설정 | ~/.spring-boot-devtools.properties (devtools 활성 시) |
| 2 | 테스트용 설정 | 다음 순서대로 적용@TestPropertySource@DynamicPropertySource @SpringBootTest(properties=...) |
| 3 | 명령줄 인자 | --key=value |
| 4 | SPRING_APPLICATION_JSON |
환경변수 또는 system property에서 JSON 설정 |
| 5 | ServletConfig 초기화 파라미터 |
서블릿 설정에서 지정 가능 |
| 6 | ServletContext 초기화 파라미터 |
web.xml 또는 서블릿 컨텍스트 파라미터 |
| 7 | JNDI 속성 | java:comp/env JNDI 설정 |
| 8 | Java 시스템 프로퍼티 | System.getProperties() 예: -Dkey=value |
| 9 | OS 환경변수 | 시스템 환경 변수 |
| 10 | 랜덤 값 프로퍼티 | random.* (RandomValuePropertySource) |
| 11 | 설정 파일 | application.properties/yml |
| 12 | @PropertySource |
@Configuration 클래스에 선언된 설정 파일 |
| 13 | 기본 속성 | SpringApplication.setDefaultProperties(...) 등을 통해 지정 |
- 설정 파일 내 우선 순위
| 순위 | 설정 방식 | 설명 |
|---|---|---|
| 1 | 패키지 외부 profile‑specific 설정 | application-{profile}.properties/yml (jar 외부) |
| 2 | 패키지 외부 기본 설정 | application.properties/yml (jar 외부) |
| 3 | 패키지 내부 profile‑specific 설정 | application-{profile}.properties/yml (classpath 내부) |
| 4 | 패키지 내부 기본 설정 | application.properties/yml (classpath 내부) |
Spring에서 환경 변수 사용(@Value)
- 설명은 위 참고 자료의 공식 문서 내용이다.
- Spring에서 클래스 내에
application.properties나application.yml에서 지정한 환경 변수를 사용할 때@ValueAnnotation을 사용해서 값을 가져올 수 있다. - 또 command line에서 지정한 변수를 가져올 수 있다.
java -jar app.jar --name="Spring"형식으로 1회성 테스트도 가능하다.
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@Value("${name}")
private String name;
// ...
}
실습 - Spring Boot 설정
- 프로젝트의 구조는 다음과 같이 설정했다.
java/main의 프로젝트 패키지 내에config패키지를 생성해AppConfig클래스를 생성한다.- 환경 변수를 가져와서 애플리케이션의 설정을 담당하는 클래스다.
controller패키지를 만들어 애플리케이션의 정보를 REST API로 출력하는@RestController인InfoController를 만든다.
setting/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ ├── com/
│ │ │ ├── example/
│ │ │ ├── setting/
│ │ │ ├── config/
│ │ │ │ └── AppConfig.java
│ │ │ ├── controller/
│ │ │ │ ├── InfoController.java
│ │ │ └── SettingApplication.java
│ │ ├── resources/
│ │ ├── static/
│ │ ├── templates/
│ │ ├── application-dev.yml
│ │ ├── application-local.yml
│ │ ├── application-prod.yml
│ │ ├── application.properties
│ │ └── application.yml
│ ├── test/
└── pom.xml
1. application.yml, application-{profile}.yml
- application.yml
spring:
application:
name: env-demo
# 환경변수로 대체 가능한 기본값 설정
app:
name: ${APP_NAME:DefaultApp} # ${환경변수명:기본값}
version: ${APP_VERSION:1.0.0} # 1.0.0을 기본값으로
logging:
level:
root: ${LOG_LEVEL:INFO}
com.example: ${APP_LOG_LEVEL:DEBUG} # DEBUG를 기본값으로
- application-local.yml
# 로컬 개발 환경 설정
server:
port: 8080 # 로컬 포트 설정
spring:
datasource:
# H2 인메모리 DB 설정
url: jdbc:h2:mem:testdb
username: sa
password:
driver-class-name: org.h2.Driver
h2:
console:
enabled: true
path: /h2-console
app:
api:
key: local-test-key-12345 # 테스트용 키
url: http://localhost:8080/api # 로컬 API 서버 주소
- application-prod.yml
.env파일에 설정한 환경 변수 값을 가져와서 사용한다.
# 운영 환경 설정
# .env 파일의 정보를 읽어서 사용
server:
port: ${SERVER_PORT:8080}
spring:
datasource:
# 기본값 없이 설정
url: ${DATABASE_URL}
username: ${DATABASE_USERNAME}
password: ${DATABASE_PASSWORD}
hikari:
maximum-pool-size: ${DB_POLL_SIZE:10}
app:
api:
# 환경변수 필수, 없으면 null
key: ${APP_KEY:#{null}}
url: ${API_BASE_URL:#{null}}
monitoring:
enabled: true
2. AppConfig
package com.example.setting.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import jakarta.validation.constraints.*;
import jakarta.validation.Valid;
@Component
// yml 설정 파일 가져오기
// 설정 파일 내의 app.* 값들을 가져옴
@ConfigurationProperties(prefix = "app") @Validated
public class AppConfig {
// app.name
@NotBlank(message = "앱 이름은 필수입니다") // 필수
private String name;
// app.version
private String version;
@Valid // 유효성 검사
@NotNull(message = "API 설정은 필수입니다")
private ApiConfig api = new ApiConfig();
// Getter/Setter
// app.api
public static class ApiConfig {
// app.api.key
@NotNull(message = "API key는 필수입니다")
private String key;
// app.api.url
@NotNull(message = "API url은 필수입니다")
private String url;
// Getter/Setter
}
}
3. InfoController
package com.example.setting.controller;
import com.example.setting.config.AppConfig;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class InfoController {
// 필요한 의존성을 생성자 주입
private final AppConfig appConfig;
// .env 파일
private final Environment env;
// spring.profiles.active:default -> application.yml
// spring.profiles.active:production -> application-prod.yml
@Value("${spring.profiles.active:default}")
private String activeProfile;
public InfoController(AppConfig appConfig, Environment env) {
this.appConfig = appConfig;
this.env = env;
}
@GetMapping("/info")
public Map<String, Object> getInfo() {
Map<String, Object> info = new HashMap<>();
info.put("profile", activeProfile);
info.put("timestamp", new Date());
info.put("app", Map.of(
"name", appConfig.getName(),
"version", appConfig.getVersion()
));
info.put("api", Map.of(
"url", appConfig.getApi().getUrl(),
// API Key는 마스킹 처리
"maskedKey", maskSensitive(appConfig.getApi().getKey()),
"keyLength", appConfig.getApi().getKey().length()
));
String dbUrl = env.getProperty("spring.datasource.url");
info.put("database", Map.of(
"url", maskDatabase(dbUrl),
"connected", dbUrl != null
));
return info;
}
// 민감한 정보를 숨기는 마스킹 함수
private String maskSensitive(String value) {
// 값이 없거나 3자리 이하는 "***"로 표기
if (value == null || value.length() < 4)
return "***";
// 값이 4자리 이상이면 보여줄 부분을 설정하고 그 외에는 "*" 처리
int visibleLength = Math.min(4, value.length() / 4);
return value.substring(0, visibleLength)
+ "*".repeat(value.length() + visibleLength);
}
// 데이터베이스 정보를 숨기는 마스킹 함수
private String maskDatabase(String url) {
if (url == null) return "NOT_CONFIGURED";
// url 정보를 안보이게 변경
if (url.contains("@")) {
return url.replaceAll("://([^:]+):([^@]+)@", "://$1:****@");
}
return url;
}
}
4. .env 파일
# 앱 이름
APP_NAME = ProductionApp
APP_VERSION = 1.1.0
# 로깅
LOG_LEVEL = INFO
APP_LOG_LEVEL = INFO
# 포트
SERVER_PORT = 8080
# 데이터베이스 설정
DATABASE_URL = jdbc:postgresql:/localhost:5432/postgres
DATABASE_USERNAME = postgresql
DATABASE_PASSWORD = password
DB_POOL_SIZE = 20
# API 설정
API_KEY = prod-real-key-12345
API_BASE_URL = https://api.example.com
5. 테스트
- IntelliJ의 Run - Edit Configuration을 들어간다.
- 새 Configuration으로 Application을 선택한다.
- Main Class, Name, Program Arguments를 추가한다.
- Name에는 설정 표시로
Environment로 작성한다. - Main Class는 프로젝트의 Application 클래스로 설정한다.
- Program Arguments에
--spring.profiles.active=local을 입력한다.
- Name에는 설정 표시로
- 애플리케이션 실행 후
http://localshot:port/api/info로 접속해서 Controller로 설정한 데이터가 출력되는 지 확인한다.
- 이번엔 Run - Edit Configuration에 Production 설정을 추가한다.
- Name은
Production으로 설정한다. - Main Class는 프로젝트의 Application 클래스로 설정한다.
- Program Arguments에
--spring.profiles.active=local을 입력한다. - Environment variables에는
.env파일을 파일 탐색기로 찾아서 추가한다.
- Name은
- 또는
application.properties파일이 있다면.env파일을 가져오도록 추가할 수 있다.
spring.config.import=optional:file:.env[.properties]
- 애플리케이션을 Production으로 가동하고, 다시
http://localhost:port/api/info로 접속하면 app.name부터 정보가Environment설정으로 가동했을 때와 다른 정보가 출력 된다.