[Spring] Spring Profile을 활용한 환경 구축

2026. 1. 18. 23:47·Framework & Library/Spring
뒤죽박죽이 되어버린 개발 환경을 정리하며

 

왜 이 글을 쓰게 되었나

지금 우리 서비스는 운영 환경에서 RDS, MongoDB Atlas, S3를 모두 사용하고 있다. 문제는 테스트 서버였다. 비용 문제로 EC2 한 대로 버티다 보니 docker-compose를 이용해 DB와 Redis 같은 것들을 함께 띄워야 했는데, 여기서부터 문제들이 하나둘씩 터지기 시작했다.

 

문제 1. 환경 설정이 뒤죽박죽

초기 .env 설정도 제대로 해두지 않은 상태에서 application-prod.yml에 모든 정보를 몰아넣은 구조였다. 이러다 보니 로컬에서 개발하다가 테스트 데이터를 넣는 과정이 귀찮고 시간이 걸리다 보니 그냥 운영 DB 붙어서 테스트를 하는 등 위험한 상황이 발생했다.

과거에 운영 데이터를 건드려서 한번 복구 하는 사고가 있던 만큼, 이런 구조는 언제든 또다시 문제를 일으킬 수 있어 개선할 필요성을 느끼게 되었다..

.

문제 2. Docker Compose의 애매한 용도

compose 파일은 분명 존재했지만, 사실상 테스트 서버용으로만 쓰이고 있었다. 테스트 환경은 사실상 비용적 문제로 한개의 인스턴스로만 구성되어있고 별도로 rds, cache, mongoDB가 따로 없기에 docker compose로 세팅해둬었기에

로컬 환경에서의 테스트 환경은 각 개발자마다 달라서 docker-compose 설정도 따로 필요한 상황이었다. 일관된 개발 환경이 없다는 것은 팀 협업에 있어서 큰 걸림돌이었다.


어떻게 해결할 것인가

1단계: Spring 설정 레이어링

Spring의 프로파일 기능을 활용해 "환경 프로파일 + 기능 프로파일" 구조를 도입하기로 했다.

환경 프로파일

  • local: 개발자 PC에서 실행하는 환경
  • staging: 테스트 서버(단일 인스턴스) 배포 환경 (기존 test 서버 역할)
  • prod: 실제 운영 배포 환경
  • test: JUnit/CI 테스트 전용 (실제 서버 환경이 아님)

기능 프로파일

  • observability: actuator, metrics, log 포맷 등 관측성 관련 설정
  • debug: 로깅 상세화, SQL 로그/추적 등 개발 편의 기능
  • swagger: API 문서 UI 등 개발/검증용 기능
  • mock: 외부 연동을 대체하는 mock endpoint 등

이렇게 나눈 프로파일들은 Spring의 프로파일 그룹 기능을 통해 조합할 수 있다. 예를 들어 SPRING_PROFILES_ACTIVE=staging만 지정해도 내부적으로 staging, observability가 함께 활성화되도록 구성하는 것이다.

 
 
yaml
spring:
  profiles:
    group:
      local: local,debug,swagger
      staging: staging,observability
      prod: prod,observability

 

2단계: Docker Compose Overlay 방식 도입

여러 환경에서 겹치는 설정이 많다는 점을 고려해 Overlay 방식으로 compose 파일을 구성하기로 했다.

파일 구성:

docker-compose.yml              # 공통 설정
docker-compose.local.yml        # 로컬 개발용 추가 설정
docker-compose.staging.yml      # 테스트 서버용 추가 설정

왜 Overlay를 사용하는가? 사실상 compose에서 겹치는 부분이 많이 존재하고, 거기에서 추가되는 것은 오버레이로 덮으면 되기 때문이다.

# 로컬 환경
docker compose -f compose.yml -f compose.local.yml up -d --build

# staging 환경
docker compose -f compose.yml -f compose.staging.yml up -d

로컬에서는 DB, MongoDB, Redis 등을 모두 컨테이너로 띄우고, staging에서는 운영과 가까운 환경을 재현할 수 있게 된다.

 

환경별 자원 사용 원칙

  • local: H2 또는 로컬 Docker 컨테이너 사용 (H2는 고려 중)
  • staging: EC2 한 대에서 애플리케이션과 DB 컨테이너를 함께 실행. 운영 자원 직접 연결 금지..!
  • prod: RDS, MongoDB Atlas, S3 같은 관리형 서비스 사용

 


 

고려했던 다른 방법들은?

A. 환경별 Compose 파일 완전 분리

각 환경마다 완전히 독립된 compose 파일을 만드는 방법이다. 직관적이긴 하지만 중복과 누락이 쉽게 발생하고 유지보수가 어렵다는 단점이 있었다. 현재 우리 팀의 규모와 구조에서는 부적합하다고 판단했다.

B. Spring 설정을 하나의 파일에서 조건문으로 처리

파일 수는 줄어들지만 가독성이 떨어지고 운영 설정이 섞일 확률이 증가한다. 운영 안정성 측면에서 좋지 않은 선택이라 채택하지 않았다.

C. API 테스트 시 운영 자원 계속 공유

귀찮음은 덜하고 배포 환경과 데이터 환경이 동일하다는 장점이 있지만, 데이터, 보안, 장애, 품질 측면에서 모든 리스크가 크다는 치명적인 단점이 있다. 원칙적으로 금지하되, 불가피한 경우 별도 계정이나 스키마 등 강한 분리가 필요하다.

 


변경할 시 장단점

좋은 점

  • 로컬/스테이징에서 운영 자원을 건드리는 일이 구조적으로 차단
  • 테스트 서버가 EC2 한 대라도 compose로 전체 검증이 가능
  • 디버그, 스웨거 같은 기능을 환경별로 쉽게 제어
  • 나중에 CI를 붙일 때 충돌이 발생하지 않음

신경 쓸 점

  • 팀원들에게 새로운 구조를 설명하고 공유해야 한다
  • 테스트 서버 사양이 부족할 수 있다 (나중에 로깅 스택도 띄워야 함 흑흑)
  • 과거 502 에러 때처럼 또 걱정된다...

최종 파일 구조

 
src/main/resources/
├── application.yml
├── application-local.yml
├── application-staging.yml
├── application-prod.yml
├── application-test.yml
├── application-observability.yml
└── application-swagger.yml

src/main/resources/logback/
├── logback-spring.xml
├── logback-local.xml
├── logback-staging.xml
└── logback-prod.xml

프로젝트 루트/
├── docker-compose.yml
├── docker-compose.local.yml
├── docker-compose.staging.yml
├── .env.local
└── .env.staging

적용 순서

1. 파일 구조 잡기

기존 설정을 분리해서 환경별 yml 파일을 만든다.

2. 프로파일 그룹 설정

 
 
yaml
spring:
  profiles:
    group:
      local: local,debug,swagger
      staging: staging,observability
      prod: prod,observability

3. 테스트 서버 전환

  • 기존 test 프로파일 → staging으로 변경
  • compose.staging.yml 기반으로 배포

4. 안전장치

  • prod에서 환경변수를 넣지 않으면 앱이 시작되지 않게 설정
  • staging에서 prod 엔드포인트 접근 차단 (보안그룹, DB 권한)

 

롤백 계획

문제가 생기면 SPRING_PROFILES_ACTIVE 환경변수와 compose 파일을 기존 방식으로 되돌리면 된다. 배포 파이프라인에서 기존 설정을 유지한 채로 신규 구성을 병행할 수 있게 해둘 예정이다.


아직 결정하지 못한 것들

  • Grafana/Loki 모니터링 스택을 staging에 상시로 띄울지, 필요할 때만 띄울지
  • Logback 수집도 local, test, prod에 따라 달라지는데 어떻게 분류해둘지

 

참고 자료

Docker-Compose 개발 환경 설정 일대기(local, dev, prod)

'Framework & Library > Spring' 카테고리의 다른 글

[Spring] Spring Security 겉핥기  (0) 2025.12.06
[Spring] 리액티브에서의 Scheduler와 Context 그리고 Testing  (0) 2025.10.20
[Spring] Backpressure와 Sinks 이해하기  (0) 2025.10.20
[Spring] 리액티브 시스템? 리액티브 프로그래밍?  (0) 2025.10.17
[Spring] 리액티브 프로그래밍을 들어가며  (0) 2025.10.12
'Framework & Library/Spring' 카테고리의 다른 글
  • [Spring] Spring Security 겉핥기
  • [Spring] 리액티브에서의 Scheduler와 Context 그리고 Testing
  • [Spring] Backpressure와 Sinks 이해하기
  • [Spring] 리액티브 시스템? 리액티브 프로그래밍?
ryuwon
ryuwon
여러 개발 정보 끄적이고 있습니닷..
  • ryuwon
    이름 없는 블로그
    ryuwon
  • 글쓰기 관리
  • 전체
    오늘
    어제
    • 분류 전체보기 (34)
      • Series (0)
      • Programming (1)
        • Java (1)
        • C (0)
        • Swift (0)
      • Framework & Library (8)
        • Spring (6)
        • Spring Boot (2)
      • Data & ORM (0)
        • RDBMS (0)
        • NoSQL (0)
        • ORM (0)
      • Infra & DevOps (1)
        • Cloud (0)
        • DevOps (1)
        • Infra (0)
      • Knowledge (4)
        • 자료구조 (1)
        • 알고리즘 (3)
        • 운영체제 (2)
        • 네트워크 (1)
        • 아키텍쳐 및 디자인 패턴 (0)
        • 개발지식 (3)
      • Testing (0)
      • Security & System (0)
      • Project (5)
      • Writing (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    네트워크
    찐빵
    OCI
    K3S
    Spring Profile
    프로젝트
  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.5
ryuwon
[Spring] Spring Profile을 활용한 환경 구축
상단으로

티스토리툴바