이번 글에서는 Spring Boot 멀티 모듈 기반 프로젝트에서 프로필(Profile)을 활용해 환경별 설정(local/dev/prod)을 분리하는 방법을 정리합니다.
프로필 분리는 실무 백엔드 프로젝트에서 거의 필수이며, 운영 환경과 개발 환경의 설정이 섞이지 않도록 하는 매우 중요한 개념입니다.
📌 Spring Boot(Kotlin) 기본 셋팅 — 전체 시리즈
- 왜 멀티 모듈 구조인가? (아키텍처 철학 & 전체 설계 편)
- API Response 포맷 설계
- 글로벌 예외 처리(GlobalExceptionHandler)
- Swagger(OpenAPI) 설정
- Security(JWT) 기본 골격
- JWT TokenProvider
- Redis 설정
- Validation 설정
- Logging + MDC(traceId) 설정
- application.yml 프로필 분리 (local/dev/prod) ← 지금 글
- 멀티모듈 + JPA 기본 구조 정리
- 완성된 프로젝트 템플릿 git 공유
✔ 왜 프로필(Profile) 분리가 필요한가?
백엔드 애플리케이션은 환경마다 서로 다른 설정값을 필요로 합니다.
예를 들어,
- 로컬 개발 환경(local) → 로컬 DB, 로컬 Redis
- 개발 서버(dev) → 개발용 DB, 개발용 JWT 키
- 운영 서버(prod) → 운영 DB, 운영 보안 설정
이를 하나의 application.yml에 모두 넣어버리면 다음과 같은 문제가 발생합니다:
- 운영용 비밀번호/보안키가 로컬 코드에 섞여 보안 위험 발생
- 로컬에서 테스트하는데 dev 또는 prod 설정 적용 → 장애 발생 가능
- 환경별 설정 차이를 관리하기 어려움
따라서 Spring Boot에서는 프로필(profile)을 사용해 설정 파일을 분리하는 것을 강력히 추천하며, 실무에서는 거의 필수적으로 local/dev/prod 3단계를 구분합니다.
✔ application.yml 기본 구조
기본 application.yml은 “공통 설정”과 “기본 활성 프로필” 정도만 포함합니다.
application.yml
server:
port: 8080
spring:
profiles:
active: local # 기본은 local 환경
logging:
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [traceId=%X{traceId}] [eventId=%X{eventId}] [userId=%X{userId}] [ip=%X{clientIp}] %-5level %logger{36} - %msg%n"
여기서는 console 로그 패턴과 기본 프로필(local)만 지정하고 있습니다.
이 로그 패턴은 이전 글에서 정리한 Logging + MDC(traceId) 설정에 맞춰 구성되어 있으며,traceId, eventId, userId, clientIp 등이 모두 로그에 자동 포함됩니다.
아래는 해당 패턴을 적용했을 때 실제로 출력되는 로그 예시입니다:
2025-02-01 23:10:22 [traceId=ca21ef01] [eventId=ABCD1234] [userId=42] [ip=123.45.67.89] ERROR c.e.a.UserService - [Unexpected Error]
method=com.example.UserService.createUser(L52)
rootCause=java.lang.IllegalStateException: something went wrong
이처럼 traceId와 eventId, userId가 함께 출력되기 때문에 특정 사용자의 요청 흐름을 추적하거나
오류 발생 시 동일한 eventId로 전체 로그를 빠르게 검색하는 것이 훨씬 쉬워집니다.
✔ application-dev.yml — 개발 서버 설정
application-dev.yml
spring:
config:
activate:
on-profile: dev
datasource:
url: ${DEV_DB_URL}
username: ${DEV_DB_USERNAME}
password: ${DEV_DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: none
properties:
hibernate:
format_sql: false
open-in-view: false
jwt:
secret: ${DEV_JWT_SECRET}
redis:
host: ${REDIS_HOST}
port: ${REDIS_PORT}
개발 서버(dev)는 대부분 AWS / GCP / 내부 개발 서버 등에 배포되는 단계입니다.
DB 정보·Redis·JWT 키 등도 개발용 environment variable로 분리되어 있습니다.
✔ application-local.yml — 로컬 개발 환경 설정
application-local.yml
spring:
config:
activate:
on-profile: local
datasource:
url: ${LOCAL_DB_URL:}
username: ${LOCAL_DB_USERNAME:}
password: ${LOCAL_DB_PASSWORD:}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: none
properties:
hibernate:
format_sql: true
open-in-view: false
# Base64 encoded dummy key (real secrets should be overridden in dev/prod)
jwt:
secret: dGVtcG9yYXJ5LXNlY3JldC1rZXktZm9yLWxvY2FsLWRldg==
redis:
host: localhost
port: 6379
로컬에서는 편의를 위해:
- format_sql = true → SQL 로그 보기 쉽게
- dummy JWT key → 실 서버 키 노출 방지
- 로컬 Redis/DB 사용
✔ application-prod.yml — 운영 서버 설정
application-prod.yml
spring:
config:
activate:
on-profile: prod
datasource:
url: ${PROD_DB_URL}
username: ${PROD_DB_USERNAME}
password: ${PROD_DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: none
properties:
hibernate:
format_sql: false
open-in-view: false
jwt:
secret: ${PROD_JWT_SECRET}
redis:
host: ${REDIS_HOST}
port: ${REDIS_PORT}
운영(prod)에서는 다음 기준으로 설정합니다:
- 운영 DB 정보는 절대 코드에 포함하지 않고 모두 환경 변수로 분리
- SQL 로그 출력 비활성화(format_sql=false)
- JWT 키도 운영용 환경 변수 기반
- Redis, 외부 API 키 등 모두 environment variable 로 관리
✔ 프로필 분리 흐름 요약
Spring Boot는 다음 순서로 설정을 읽습니다:
application.yml → 활성 프로필 확인 →
application-{profile}.yml → 해당 설정 override
예를 들어 prod 환경에서는 다음처럼 실행:
java -jar app.jar --spring.profiles.active=prod
→ application.yml에서 기본 구조 로드 → application-prod.yml로 설정 override
✔ 왜 이렇게 분리하는 것이 좋은가?
1) 보안 강화
- 운영 DB ID/PW, JWT Secret 키가 코드에 절대 포함되지 않음
- 환경 변수로만 관리하므로 안전함
2) 환경별 설정 충돌 방지
- local에서 테스트하는데 prod 설정이 적용되는 사고 방지
- 개발서버(dev) 테스트 중 운영 DB에 영향을 주는 위험 제거
3) 배포 자동화 용이
- CI/CD 파이프라인에서 프로필만 바꿔 배포 가능
- 한 프로젝트로 로컬/개발/운영 3가지 환경 모두 대응 가능
4) 유지보수 용이
- 각 환경의 설정이 명확하게 분리되어 변경 시 실수 줄어듦
- 팀원 간 협업에도 유리
✔ 마무리
application.yml 프로필 분리는 작은 프로젝트에서도 반드시 필요한 구조이며,
운영 환경이 생기는 순간부터 안정성·보안·유지보수 측면에서 큰 차이를 만들어 줍니다.
다음 글에서는 멀티모듈 + JPA 기본 구조를 정리합니다!
https://jaemoi8.tistory.com/48
Spring Boot(Kotlin) 기본 셋팅 — 11편. 멀티모듈 + JPA 기본 구조 정리
이번 글에서는 Spring Boot 멀티 모듈 프로젝트에서 JPA를 어떤 구조로 배치해야 하는지와초기 셋팅에서 알아두면 좋은 핵심 개념을 정리합니다.특히 본 시리즈는 “기본 서버 셋팅 템플릿”을 만
jaemoi8.tistory.com
'개발' 카테고리의 다른 글
| Spring Boot(Kotlin) — 12편. 완성된 프로젝트 템플릿 공유 (0) | 2025.11.27 |
|---|---|
| Spring Boot(Kotlin) 기본 셋팅 — 11편. 멀티모듈 + JPA 기본 구조 정리 (0) | 2025.11.27 |
| Spring Boot(Kotlin) — 9편. Logging + MDC(traceId) 설정 (0) | 2025.11.27 |
| Spring Boot(Kotlin) — 8편. 멀티 모듈 환경에서 Spring Validation을 어떻게 적용할 것인가 (0) | 2025.11.27 |
| Spring Boot(Kotlin) — 7편. 왜 Redis인가? Spring Boot 애플리케이션에서 Redis를 사용하는 이유와 설정 (0) | 2025.11.25 |