infra
Platform

모듈 맵

[Infra Ops] dev/stg/prod 환경변수와 설정 파일 분리 전략

0 / 52 완료

펼치기
0 / 52 완료0%

인프라 운영 & SRE · 33 / 52

[Infra Ops] dev/stg/prod 환경변수와 설정 파일 분리 전략

환경별 properties/yml/env 분리, 민감 정보 관리, endpoint 분리 전략까지 — 배포 사고를 막는 설정 관리 실무

🚨INCIDENT ALERT
HIGH

신규 서비스 배포를 앞두고 운영팀에서 연락이 왔습니다. "스테이징에서는 잘 됐는데 운영에서 오류가 납니다." 로그를 열어보니 운영 서버가 개발 DB에 연결 시도하고 있었습니다. 개발자가 application.yml 하나에 모든 환경 설정을 때려넣고, 프로파일 지정 없이 배포했던 것입니다.

이 모듈은 그런 사고를 막기 위한 것입니다. 환경별 설정 파일을 어떻게 분리하고, 민감한 정보를 어디에 두어야 하며, 운영 서버에서 설정을 어떻게 적용하는지를 다룹니다.

이번 챕터에서 배울 것
  • 1application-dev.yml / application-stg.yml / application-prod.yml 파일 분리 구조를 설명할 수 있다
  • 2OS 환경변수 > JVM 옵션 > properties 파일의 우선순위를 이해하고 활용할 수 있다
  • 3.env 파일, 환경변수, Vault의 용도 차이를 설명하고 .gitignore에 포함할 파일을 알 수 있다
  • 4Tomcat setenv.sh로 JVM 환경변수를 주입하는 방법을 실습할 수 있다
  • 5설정 변경 후 무중단 적용 여부를 판단하고 올바른 재기동 절차를 선택할 수 있다

환경 분리 — 왜 파일을 나눠야 하나

💡개념

환경별 설정 파일 분리

개발/스테이징/운영은 DB 주소, 로그 레벨, API 엔드포인트가 모두 다릅니다. 하나의 파일에 모든 환경 설정을 넣으면 배포 실수가 났을 때 어느 환경이 잘못 연결됐는지 추적하기 어렵고, 민감한 운영 정보가 개발 환경에 노출될 위험도 생깁니다.

환경별 설정 파일 분리 — 개발·스테이징·운영은 DB 주소·로그 레벨·API 엔드포인트가 다름. 공통 설정과 환경별 설정을 파일로 분리(application-env.yml·프로파일)하고 민감 값은 환경변수·시크릿으로 주입. 한 파일에 다 넣으면 배포 실수 추적이 어렵고 운영 정보가 개발에 노출될 위험확대

Spring Boot는 application-{profile}.yml 규칙으로 환경별 파일을 자동으로 읽습니다.

src/main/resources/ 구조입니다.

  • application.yml — 공통 설정 (프로파일 무관하게 항상 로드)
  • application-dev.yml — 개발 환경 전용
  • application-stg.yml — 스테이징 환경 전용
  • application-prod.yml — 운영 환경 전용
YAML
# application.yml (공통)
spring:
  application:
    name: my-service
  jpa:
    open-in-view: false

logging:
  pattern:
    console: "%d{HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
YAML
# application-dev.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb_dev
    username: dev_user
    password: dev_pass   # 개발 환경은 .env나 로컬 파일 허용
  jpa:
    show-sql: true        # 개발에서만 SQL 로그 출력

logging:
  level:
    root: DEBUG
YAML
# application-prod.yml
spring:
  datasource:
    url: jdbc:mysql://${DB_HOST}:3306/${DB_NAME}   # 환경변수로 주입
    username: ${DB_USER}
    password: ${DB_PASSWORD}
  jpa:
    show-sql: false       # 운영에서는 SQL 로그 off

logging:
  level:
    root: WARN

핵심 원칙: 운영 설정 파일(application-prod.yml)에는 실제 비밀값을 절대 하드코딩하지 않습니다. ${환경변수명} 플레이스홀더만 두고, 실제 값은 OS 환경변수나 Vault에서 주입합니다.

설정 우선순위 — 어디서 값이 오는가

💡개념

Spring Boot 설정 우선순위

같은 키가 여러 곳에 정의되어 있을 때 어떤 값이 적용되는지 알아야 설정 충돌을 추적할 수 있습니다. Spring Boot는 명확한 우선순위를 따릅니다.

설정 우선순위(위가 가장 강함):

  1. OS 환경변수 (SPRING_DATASOURCE_URL)
  2. JVM 시스템 옵션 (-Dspring.datasource.url=...)
  3. 프로파일 yml 파일 (application-prod.yml)
  4. application.yml (공통 파일)

OS 환경변수가 가장 강하다는 것이 핵심입니다. 파일에 값이 있더라도 환경변수를 설정하면 그 값이 우선 적용됩니다. 운영 서버에서 DB 비밀번호를 파일에 넣지 않고 환경변수로 주입하는 이유가 여기 있습니다.

설정 우선순위 4계층 — 같은 키가 OS 환경변수·JVM 시스템 옵션·프로파일 yml(application-prod.yml)·application.yml 네 곳에 있을 때, 위(환경변수)가 아래를 덮어써 최종 적용값이 된다. 파일에 값이 있어도 환경변수를 설정하면 그 값이 우선하므로 운영 서버는 DB 비밀번호를 파일이 아니라 환경변수로 주입한다. "설정을 바꿨는데 반영이 안 된다"는 대개 더 강한 계층(환경변수·JVM 옵션)에 옛 값이 남아 파일 값을 덮고 있는 경우로, env·cat /proc/PID/environ으로 실제 주입값을 확인해 원인을 좁힌다. 비밀값은 강한 계층(환경변수·Vault)에, 공통 기본값만 application.yml에 두면 파일이 git에 노출돼도 안전하다확대

로컬 터미널
# 운영 서버에서 환경변수 확인
env | grep -E "SPRING|DB|APP|JAVA"

# 실행 중인 JVM 프로세스의 환경변수 확인 (PID는 ps aux로 찾기)
cat /proc/$(pgrep -f myapp.jar)/environ | tr '\0' '\n' | grep -E "DB|SPRING"
💡개념

설정값 하나가 최종 적용되기까지 — 로드부터 병합까지 5단계

application-prod.yml에 DB 주소를 분명히 새 값으로 고쳤는데 앱은 옛 주소에 붙습니다. 파일도 맞고 문법 오류도 없습니다. 이런 일이 나는 건, 앱이 값을 한 곳에서 읽는 게 아니라 여러 계층을 순서대로 읽어 덮어쓰며 하나의 최종값으로 병합하기 때문입니다. 어느 계층이 마지막에 값을 얹었는지 모르면 "고쳤는데 왜 그대로지"를 영원히 못 풉니다. 설정값 하나가 기동 시점에 어떻게 실려 최종 적용값이 되는지를 단계로 봅니다.

TEXT
[앱 기동]  같은 키(예: spring.datasource.url)를 아래 순서로 읽어 뒤가 앞을 덮는다
   │
   ① 기본값            코드에 박힌 기본값(@Value 기본·프레임워크 디폴트)
   │                    → 아무 설정도 없을 때 쓰이는 최후의 바닥값
   │
   ② 설정 파일          application.yml (프로파일 무관 공통값)
   │
   ③ 프로파일 파일      application-{active}.yml (dev/stg/prod 중 활성 프로파일)
   │                    → SPRING_PROFILES_ACTIVE 가 어느 파일을 열지 결정
   │
   ④ 환경변수           OS 환경변수(SPRING_DATASOURCE_URL 등)가 파일 값을 덮음
   │
   ⑤ 커맨드라인/시크릿   --spring.datasource.url=... 실행인자·시크릿 주입 (가장 강함)
   ▼
[최종 병합값]  각 키마다 '가장 마지막에 얹힌 값'이 실제로 적용된다

각 단계가 무엇을 얹고, 그 계층이 범인일 때의 증상:

단계무엇을 얹는가이 계층이 범인이면 증상
① 기본값코드·프레임워크 내장 디폴트위 어느 계층도 값을 안 주면 의도치 않게 로컬(localhost) 기본값으로 뜬다
② application.yml환경 무관 공통값공통 파일에 개발 DB 주소가 남아 있으면 프로파일 미지정 시 그 값으로 붙음
③ 프로파일 파일활성 프로파일 전용값SPRING_PROFILES_ACTIVE 누락 → prod 파일이 안 열려 공통값·개발값이 적용
④ 환경변수서버별 실제 주입값파일을 고쳐도 옛 값이 든 환경변수가 남아 파일을 덮음(우선순위 역전) · 반대로 누락되면 ${} 미치환
⑤ 커맨드라인/시크릿최종 오버라이드·비밀값시크릿 미주입이면 비밀번호 자리가 비어 인증 실패 · -D 옛 값이 남으면 모든 걸 덮어 이김

최종 적용값은 "가장 마지막에 얹은 계층"이 이깁니다. "고쳤는데 반영이 안 된다"는 대개 ④·⑤의 더 강한 계층에 옛 값이 남아 파일을 덮는 우선순위 역전이고, "설정이 통째로 개발값"이면 ③의 프로파일 미지정입니다. 그래서 진단은 파일부터 보지 말고 강한 계층부터 역순으로 봅니다 — env | grep SPRING, cat /proc/PID/environ, ps aux-D 옵션, 그리고 앱에 있으면 actuator/env어느 소스가 그 키를 최종 채택했는지를 바로 확인합니다.

민감 정보 관리 — .env, 환경변수, Vault

💡개념

비밀값을 어디에 두어야 하나

DB 비밀번호, API 키, JWT 시크릿 같은 민감 정보는 코드와 분리해야 합니다. 규모와 보안 요구에 따라 세 가지 방법 중 하나를 선택합니다.

방법적합한 상황주의사항
.env 파일개발 로컬 / 소규모 스테이징git에 절대 커밋 금지, .gitignore 필수
OS 환경변수단일 서버 운영 환경setenv.sh 또는 systemd 서비스 파일에 주입
HashiCorp Vault멀티 서버/클라우드/보안 규정 있는 운영별도 Vault 서버 구성 필요, 접근 권한 관리
로컬 터미널
# .env 파일 예시 (로컬 개발용)
DB_HOST=localhost
DB_NAME=mydb_dev
DB_USER=dev_user
DB_PASSWORD=dev_secret_password
APP_SECRET_KEY=localdev_secret_key_only

.gitignore 에 반드시 포함할 파일들:

로컬 터미널
# .gitignore
.env
.env.*
!.env.example          # 예시 파일(실제 값 없음)은 허용
application-prod.yml   # 운영 설정에 비밀이 있을 경우
*.properties.bak
/config/secrets/
로컬 터미널
# .env.example (저장소에 포함하는 템플릿)
DB_HOST=localhost
DB_NAME=
DB_USER=
DB_PASSWORD=               # 팀원이 이 파일을 복사해 .env 를 만든다
APP_SECRET_KEY=

환경별 설정 분리 — 12 Factor App 원칙확대

Tomcat 환경변수 주입 — setenv.sh

💡개념

setenv.sh 로 JVM 환경변수 설정

Tomcat은 기동 시 $CATALINA_HOME/bin/setenv.sh 파일이 있으면 자동으로 실행합니다. 이 파일에 환경변수와 JVM 옵션을 설정하면 Tomcat 프로세스 전체에 적용됩니다. 파일이 없으면 직접 만들면 됩니다.

로컬 터미널
# /opt/tomcat/bin/setenv.sh
export JAVA_OPTS="
  -server
  -Xms512m
  -Xmx2048m
  -Dspring.profiles.active=prod
  -Dspring.config.location=/etc/myapp/application-prod.yml
"

# 민감 정보는 OS 환경변수에서 읽어서 JVM에 전달
export JAVA_OPTS="$JAVA_OPTS
  -DDB_HOST=${DB_HOST}
  -DDB_PASSWORD=${DB_PASSWORD}
"
로컬 터미널
# setenv.sh 적용 확인 — Tomcat 재기동 후
ps aux | grep java | grep spring.profiles.active

# 또는 실행 중인 프로세스 JVM 옵션 확인
jps -v | grep Catalina

setenv.sh 권한 설정:

로컬 터미널
chmod 750 /opt/tomcat/bin/setenv.sh
chown tomcat:tomcat /opt/tomcat/bin/setenv.sh

실습

1현재 적용된 환경변수 확인

실행 중인 환경에서 어떤 설정 관련 환경변수가 있는지 확인합니다. 운영 서버라면 DB 연결 정보, 프로파일 설정 등이 나와야 합니다. 아무것도 나오지 않는다면 환경변수 주입이 누락된 상태입니다.

로컬 터미널
# 실행 중인 Java 프로세스의 환경변수 직접 확인
# 먼저 PID 찾기
ps aux | grep java | grep -v grep | awk '{print $2}'

# PID 로 환경변수 읽기 (예: PID=12345)
cat /proc/12345/environ | tr '\0' '\n' | grep -E "DB|SPRING|APP"
OUTPUT
SPRING_PROFILES_ACTIVE=prod
DB_HOST=db-prod.internal
DB_NAME=mydb_prod
DB_USER=app_user
env | grep -E 'JAVA|SPRING|DB|APP'
🔍실행 후 확인할 것
  • ps aux | grep java에서 -Dspring.profiles.active 값을 먼저 확인 — prod가 없으면 기본 application.yml만 로드되어 개발 DB에 연결될 수 있음. 값이 없으면 setenv.sh 설정 누락
  • git ls-files .env 결과가 한 줄이라도 있으면 민감 정보가 저장소에 커밋된 것 — 즉시 git rm --cached .env 실행 후 .gitignore에 추가. 이미 커밋됐으면 히스토리 전체 정리 필요
  • -Dspring.profiles.active=prod이고 DB_HOST가 운영 주소인데 연결 오류가 나면 — 환경변수 이름이 맞는데 값만 틀린 경우. printenv | grep DB로 실제 주입된 값을 반드시 재확인
2setenv.sh 설정 확인 및 프로파일 지정

Tomcat을 사용하는 서버라면 setenv.sh에서 어떤 프로파일이 지정됐는지 확인합니다. spring.profiles.active가 없거나 dev로 돼 있으면 운영에서 개발 설정이 적용됩니다.

로컬 터미널
# setenv.sh 가 없으면 확인
ls -la /opt/tomcat/bin/setenv.sh

# JVM 옵션에서 프로파일 확인
grep -E "profiles|JAVA_OPTS" /opt/tomcat/bin/setenv.sh

# 실행 중인 프로세스에서 직접 확인
ps aux | grep "[Dd]spring.profiles.active"
OUTPUT
export JAVA_OPTS="-server -Xms512m -Xmx2048m -Dspring.profiles.active=prod"
cat /opt/tomcat/bin/setenv.sh
🔍실행 후 확인할 것
  • setenv.sh에서 -Dspring.profiles.active=prod 줄을 먼저 찾는다 — 없으면 프로파일 미지정 상태. JAVA_OPTS와 CATALINA_OPTS 두 변수 모두 확인해야 함(한쪽에만 있는 경우 많음)
  • JAVA_OPTS에 DB 비밀번호가 직접 문자열로 있으면 — ps aux 출력에 그대로 노출됨. 다른 계정 사용자도 비밀번호를 볼 수 있어 보안 위반. 환경변수 참조(${DB_PASSWORD}) 방식으로 즉시 교체 필요
  • setenv.sh 파일 권한이 644이면 다른 계정도 읽기 가능 — 비밀번호 등 민감 정보가 있는 경우 750(tomcat 그룹만 실행)이나 700(소유자만)으로 변경 필요. ls -la로 최종 확인

트러블슈팅

원인: Spring Boot 프로파일이 지정되지 않으면 기본 application.yml만 로드됩니다. 개발 DB 주소가 기본 파일에 있거나, setenv.sh에 -Dspring.profiles.active 설정이 누락된 경우입니다.

로컬 터미널
# 1. 실행 중인 프로세스의 프로파일 확인
ps aux | grep java | grep profiles.active
# 아무것도 안 나오면 프로파일 미지정 상태

# 2. 어떤 설정 파일이 로드됐는지 애플리케이션 로그에서 확인
grep -E "profiles|config.*loaded|active profile" /opt/tomcat/logs/catalina.out | head -20

# 3. setenv.sh 수정 — 프로파일 지정 추가
vi /opt/tomcat/bin/setenv.sh
# 아래 줄 추가
# export JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active=prod"

# 4. Tomcat 재기동
systemctl restart tomcat

# 5. 재기동 후 확인
grep "The following profiles are active" /opt/tomcat/logs/catalina.out | tail -3

예방: 배포 체크리스트에 "setenv.sh 프로파일 확인" 항목을 추가하고, 배포 스크립트에서 기동 후 로그로 프로파일을 검증합니다.

원인: Java 애플리케이션은 JVM 기동 시점에 설정을 읽어 메모리에 올립니다. 파일을 수정해도 실행 중인 JVM에는 변경이 반영되지 않습니다.

로컬 또는 서버
# 설정 파일 수정 후 현재 적용된 값 확인 (Spring Actuator가 있는 경우)
curl http://localhost:8080/actuator/env | python3 -m json.tool | grep -A3 "datasource.url"

# 파일이 수정됐지만 프로세스는 구 값을 갖고 있음을 확인
# /proc/PID/environ 은 기동 시점 환경변수를 반영 → 변경 없음

# 일부 앱은 HUP 시그널로 재로드 지원 (NGINX 등) — Java 앱은 일반적으로 미지원
# kill -HUP $(pgrep -f myapp.jar)   ← 대부분의 Spring 앱에서 동작 안 함

# 올바른 방법: 점검 후 재기동
systemctl stop myapp
# 또는 Tomcat이라면
systemctl stop tomcat

# 설정 변경 확인
grep "datasource.url" /etc/myapp/application-prod.yml

# 재기동
systemctl start myapp
systemctl status myapp

무중단이 필요한 경우: 로드밸런서에서 해당 인스턴스를 제외(Drain) → 재기동 → 헬스체크 통과 후 복귀 순서로 처리합니다.

설정 파일 백업 전략

💡개념

설정 파일 변경 이력 관리

운영 서버의 설정 파일은 변경 전 반드시 백업합니다. 잘못 수정했을 때 빠르게 복구하기 위해서입니다.

로컬 터미널
# 수정 전 백업 (날짜 포함)
cp /etc/myapp/application-prod.yml \
   /etc/myapp/application-prod.yml.$(date +%Y%m%d_%H%M%S).bak

# 백업 목록 확인
ls -lt /etc/myapp/*.bak | head -5

# 이전 버전으로 복구
cp /etc/myapp/application-prod.yml.20260530_143022.bak \
   /etc/myapp/application-prod.yml

# 설정 변경 이력은 git으로도 관리 (비밀값 제외한 템플릿)
# 민감 정보가 없는 application-prod.yml.template 을 저장소에 유지

심화 — 주입은 했는데: 시크릿과 우선순위의 뒷면

💡개념

심화: 환경변수 주입의 한계와 그다음 — 시크릿 매니저

비밀값을 이미지·파일에서 빼 환경변수로 옮기면 큰 진전이지만, "환경변수면 안전하다"에서 멈추면 여전히 새는 구멍이 남습니다. 환경변수가 실제로 어디까지 보이는지 알아야 다음 단계를 판단할 수 있습니다.

  • 커맨드라인보다 환경변수가 낫습니다: 비밀값을 -DDB_PASSWORD=...처럼 JVM 커맨드라인에 두면 ps aux·/proc/PID/cmdline으로 같은 서버의 다른 사용자에게도 그대로 보입니다. 같은 값이라도 환경변수로 주면 커맨드라인 노출은 사라집니다.
  • 환경변수도 완전히 숨지는 않습니다: 환경변수는 그 프로세스가 실행한 자식 프로세스에 상속되고, root·소유자는 /proc/PID/environ으로 읽을 수 있으며, 힙 덤프·에러 스택트레이스·잘못 열린 actuator/env 엔드포인트로 새어 나갈 수 있습니다.
  • 다음 단계는 시크릿 매니저: 규정이 엄격하거나 서버가 많아지면 HashiCorp Vault·클라우드 Secrets Manager로 넘어갑니다. 값을 디스크에 두지 않고 기동 시 받아오며, 짧은 수명(lease)·자동 회전·접근 감사를 제공합니다. DB 자격증명을 요청 시마다 동적으로 발급해, 유출돼도 곧 만료되게 할 수도 있습니다.
  • 한계/원칙: 도구가 무엇이든 원칙은 같습니다 — 비밀은 코드·이미지와 분리, 최소 권한, 그리고 정기 회전. 한 번 유출된 비밀은 코드에서 지워도 이미 복제됐다고 보고 회전(교체)해야 진짜로 닫힙니다.

그래서 "비밀을 환경변수로 뺐다"는 끝이 아니라 시작이고, 다음 질문은 "이 값을 어떻게 짧게 살게 하고, 언제 회전할까"입니다.

상황: 설정 파일을 새 주소로 바꾸고 재기동까지 했는데, 앱 로그의 실제 연결 대상은 옛 주소입니다. 파일을 다시 열어봐도 새 값이 맞고, yml 문법 오류도 없습니다.

원인: Spring Boot는 같은 키를 여러 소스에서 읽되 정해진 우선순위로 합칩니다. OS 환경변수와 -D JVM 옵션은 프로파일 yml·application.yml보다 강합니다. 어딘가(대개 setenv.shJAVA_OPTS나 배포 스크립트가 심어둔 SPRING_DATASOURCE_URL 환경변수)에 옛 값이 남아, 파일을 아무리 고쳐도 그 강한 계층이 파일 값을 덮고 있는 것입니다.

진단: env | grep -E "SPRING|DB"cat /proc/PID/environ | tr '\0' '\n' | grep SPRING으로 실제 주입된 환경변수를 보고, setenv.shJAVA_OPTS·CATALINA_OPTS에서 -Dspring.datasource.url 같은 옵션이 남아 있는지 확인합니다. 앱에 actuator/env가 있으면 그 키를 어느 소스가 최종 채택했는지를 바로 볼 수 있습니다.

해결: 옛 값을 쥐고 있는 강한 계층을 지우거나 새 값으로 갱신합니다(환경변수 unset·setenv.sh 수정). 그다음 재기동하면 파일 값이 살아납니다. 재발 방지로 "환경별 차이는 한 계층에서만 관리"라는 규칙을 정해, 같은 키를 파일과 환경변수 양쪽에 흩뿌리지 않습니다.

💼
실무 맥락
현업 패턴

실제 업무에서 이 지식이 쓰이는 상황:

인프라 엔지니어가 환경 설정 관리에서 가장 자주 마주치는 상황 세 가지입니다.

1. 신규 서버 환경 구성 시: 운영 서버를 새로 세팅할 때 개발자가 만든 application.yml 그대로 올리면 안 됩니다. setenv.sh에 SPRING_PROFILES_ACTIVE=prod를 설정하고, DB 접속 정보는 OS 환경변수로 주입하는 것이 기본 체크리스트입니다.

2. 설정 변경 요청 처리:

로컬 터미널
# 인프라 엔지니어의 설정 변경 표준 절차
# 1. 현재 설정 백업
cp /opt/tomcat/bin/setenv.sh /opt/tomcat/bin/setenv.sh.$(date +%Y%m%d).bak

# 2. 변경
vi /opt/tomcat/bin/setenv.sh

# 3. 적용을 위한 재기동 (무중단 필요 시 LB에서 먼저 제외)
systemctl restart tomcat

# 4. 적용 확인
sleep 10
curl -s http://localhost:8080/actuator/health | python3 -m json.tool
grep "profiles are active" /opt/tomcat/logs/catalina.out | tail -3

3. 보안 감사 대응: Git 저장소에 비밀번호가 커밋됐는지 점검 요청이 오면 아래를 씁니다.

로컬 터미널
# 저장소에 .env 파일이 들어간 적 있는지 확인
git log --all --full-history -- .env
git log --all --full-history -- "**/*.properties"

설정 관리를 잘 하는 팀은 배포 사고의 절반을 예방합니다.


명령어·단축키 빠른 참조

이 모듈에서 다룬 환경변수·프로파일 확인과 설정 감사 명령을 실전 옵션과 함께 모았습니다.

명령어/단축키용도자주 쓰는 예
env | grep주입된 설정 환경변수 확인env | grep -E "SPRING|DB"
printenv특정 환경변수 값 재확인printenv | grep DB
cat /proc/<PID>/environ실행 중 프로세스의 실제 환경변수cat /proc/<PID>/environ | tr '\0' '\n'
pgrep -f <앱>앱 PID 찾기pgrep -f myapp.jar
ps aux | grep profiles.active활성 프로파일 확인-Dspring.profiles.active=prod 있는지
jps -vJVM 기동 옵션 전체 확인jps -v | grep Catalina
curl actuator/env최종 채택된 설정값 소스 확인curl localhost:8080/actuator/env
git ls-files .env비밀 파일 커밋 여부 점검한 줄이라도 나오면 즉시 조치
git rm --cached .env추적 제거(파일은 유지)이후 .gitignore에 추가
git log --all --full-history비밀 파일 커밋 이력 감사git log --all --full-history -- .env
chmod 750 setenv.shsetenv.sh 권한 잠금644면 다른 계정이 비밀 열람
systemctl restart tomcat설정 반영 재기동무중단은 LB Drain 후 재기동

관련 모듈로 더 깊이:

다음 모듈에서는 이런 설정 변경 이력을 체계적으로 관리하는 Git 형상관리 실무를 다룹니다.

지식 확인

퀴즈 — 8문제

Q1

dev/stg/prod 설정을 분리하는 방법 중 가장 안전한 방식은?

Q2

.env 파일을 git에 올리면 안 되는 가장 큰 이유는?

Q3

Spring Boot에서 운영 환경 프로파일을 지정하는 방법으로 올바른 것은?

Q4

운영 서버에서 설정 파일을 변경한 후 반영하는 올바른 절차는?

Q5

운영에서 application.yml에 적힌 DB 호스트를, 코드를 바꾸지 않고 그 서버에서만 다른 값으로 덮어쓰고 싶다. Spring Boot 설정 우선순위를 이용한 방법은?

Q6

DB 비밀번호 같은 민감값을 이미지 빌드 시 application.yml에 박아 넣고 배포하면 안 되는 이유와 올바른 방법은?

Q7

[심화] 비밀값을 이미지·파일에 박지 않고 OS 환경변수로 주입하기로 했다. 그런데 환경변수 주입도 완벽하지 않다. 다음 중 환경변수 방식의 한계로 옳은 것은?

Q8

[심화] application-prod.yml의 DB 호스트를 새 주소로 고치고 애플리케이션을 재기동했는데도, 앱은 여전히 옛 DB에 붙는다. 파일은 분명히 새 값이고 문법 오류도 없다. 가장 유력한 원인은?

0 / 8 답변

🧪 실습으로 확인하기

환경 설정 드리프트 — "스테이징은 되는데 운영만 안 됨"

중급

같은 코드가 환경마다 다르게 동작한다. 원인은 코드가 아니라 환경별 설정 차이(누락된 환경변수, 다른 시크릿, 잘못된 엔드포인트)다. 환경 간 설정을 안전하게 비교(시크릿 값은 가리고 키만)하고, 차이를 특정하고, 12-factor 원칙대로 설정을 코드에서 분리해 드리프트를 구조적으로 막는다.

40📋 3단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요