이 글에서 다루는 내용

Spring Boot에서 환경변수를 설정하는 다양한 방법과 각 방식의 네이밍 규칙, 그리고 Spring Boot가 서로 다른 형식의 키를 동일하게 인식하는 Relaxed Binding 동작 원리를 다룹니다. OS 환경변수에서 케밥케이스를 사용할 수 없는 이유와 각 환경(Docker, Kubernetes, 커맨드라인)에서 올바른 형식을 선택하는 기준도 함께 설명합니다.

환경변수 설정 방법

1. application.properties / application.yml

가장 기본적인 방법입니다.

# application.properties
server.port=8080
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=myuser
spring.datasource.password=mypassword
my.custom.value=hello
# application.yml
server:
  port: 8080
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: myuser
    password: mypassword
my:
  custom:
    value: hello

2. 프로파일별 설정 분리

resources/
├── application.yml          # 공통
├── application-local.yml    # 로컬 개발
├── application-dev.yml      # 개발 서버
└── application-prod.yml     # 운영 서버

활성화 방법:

# application.yml
spring:
  profiles:
    active: local

또는 실행 시 지정:

java -jar app.jar --spring.profiles.active=prod

3. OS 환경변수 연동

Spring Boot는 OS 환경변수를 자동으로 읽습니다. 키 변환 규칙은 대문자 + 언더스코어 → 점 표기법입니다.

export SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/mydb
export SPRING_DATASOURCE_PASSWORD=secret

.env 파일을 사용하고 싶다면 dotenv 라이브러리를 추가합니다.

<!-- pom.xml -->
<dependency>
  <groupId>me.paulschwarz</groupId>
  <artifactId>spring-dotenv</artifactId>
  <version>4.0.0</version>
</dependency>
# .env
DB_PASSWORD=secret123
# application.yml
spring:
  datasource:
    password: ${DB_PASSWORD}

4. @Value로 코드에서 주입

@Component
public class MyService {

    @Value("${my.custom.value}")
    private String customValue;

    @Value("${my.timeout:5000}") // 기본값 지정
    private int timeout;
}

5. @ConfigurationProperties (권장)

타입 안전하고 IDE 자동완성이 지원됩니다.

# application.yml
app:
  database:
    host: localhost
    port: 5432
    name: mydb
@ConfigurationProperties(prefix = "app.database")
@Component
public class DatabaseProperties {
    private String host;
    private int port;
    private String name;
    // getter/setter 또는 Record 사용
}

6. 설정 우선순위

높을수록 먼저 적용됩니다.

순위 설정 위치
1 커맨드라인 인수 --key=value
2 OS 환경변수
3 application-{profile}.yml
4 application.yml
5 @PropertySource 어노테이션

Relaxed Binding - 네이밍 규칙이 달라도 인식되는 이유

Spring Boot는 다양한 형식의 키를 자동으로 동일한 값으로 매핑하는 Relaxed Binding 기능을 제공합니다.

같은 속성을 표현하는 다양한 형식

형식 예시 사용 위치
케밥케이스 spring.datasource.max-pool-size .yml, .properties 권장
카멜케이스 spring.datasource.maxPoolSize .yml, .properties
스네이크케이스 spring.datasource.max_pool_size .yml, .properties
대문자 스네이크 SPRING_DATASOURCE_MAX_POOL_SIZE OS 환경변수 권장

위 4가지 모두 같은 속성으로 인식됩니다.

Spring 내부 정규화 과정

입력값: SPRING_DATASOURCE_MAX_POOL_SIZE
  1단계: 소문자 변환  → spring_datasource_max_pool_size
  2단계: _ → .      → spring.datasource.max.pool.size

입력값: spring.datasource.maxPoolSize
  1단계: 카멜 분리   → spring.datasource.max.pool.size

입력값: spring.datasource.max-pool-size
  1단계: - 제거     → spring.datasource.max.pool.size

✅ 셋 다 동일한 canonical key로 처리됨

위치별 권장 형식

# application.yml → 케밥케이스
spring:
  datasource:
    max-pool-size: 10
# OS 환경변수 → 대문자 스네이크
export SPRING_DATASOURCE_MAX_POOL_SIZE=10
# 커맨드라인 → 케밥케이스
java -jar app.jar --spring.datasource.max-pool-size=10
// @Value → 케밥케이스
@Value("${spring.datasource.max-pool-size}")
private int maxPoolSize;

@Value vs @ConfigurationProperties 바인딩 차이

@ConfigurationProperties는 Relaxed Binding을 완전히 지원하지만, @Value는 정확한 키를 입력해야 합니다.

// ❌ @Value에서는 환경변수 형식 직접 사용 불가
@Value("${SPRING_DATASOURCE_MAX_POOL_SIZE}")

// ✅ @Value에서는 케밥케이스로
@Value("${spring.datasource.max-pool-size}")

// ✅ @ConfigurationProperties는 어떤 형식이든 OK
@ConfigurationProperties(prefix = "spring.datasource")

OS 환경변수에서 케밥케이스를 쓸 수 없는 이유

결론부터 말하면 대부분의 OS에서 불가능합니다.

# ❌ bash에서 - 는 변수명에 사용 불가 → 문법 오류
export SPRING_DATASOURCE_MAX-POOL-SIZE=10
# bash: export: `SPRING_DATASOURCE_MAX-POOL-SIZE=10': not a valid identifier

POSIX 명세상 환경변수명에 허용되는 문자가 정해져 있습니다.

  • 허용: 영문자(A-Z, a-z), 숫자(0-9), 언더스코어(_)
  • 금지: 하이픈(-), 점(.), 공백 등

이는 Spring의 문제가 아니라 OS/Shell 레벨에서 아예 설정이 불가능한 것입니다.

Docker / Kubernetes도 동일

# docker-compose.yml
environment:
  - SPRING_DATASOURCE_MAX_POOL_SIZE=10  # ✅
  - SPRING_DATASOURCE_MAX-POOL-SIZE=10  # ❌ 오류
# k8s deployment.yml
env:
  - name: SPRING_DATASOURCE_MAX_POOL_SIZE  # ✅
    value: "10"

위치별 형식 정리

위치 케밥케이스 대문자 스네이크
application.yml ✅ 권장 가능
OS 환경변수 ❌ OS 불가 ✅ 권장
Docker / k8s
커맨드라인 가능

보안 팁

민감한 값(password, secret-key 등)은 절대 Git에 올리지 말고 아래와 같이 관리합니다.

  • 로컬: .env 또는 application-local.yml.gitignore 처리
  • 운영: OS 환경변수 또는 AWS Parameter Store / Vault 연동