[Spring Boot] 개발/운영 환경 분리 전략: 실수로 운영 DB 날려먹지 않는 법

[Spring Boot] 개발/운영 환경 분리 전략: 실수로 운영 DB 날려먹지 않는 법 이미지 1

안녕하세요. IT 기술 블로거입니다.

지난 시간에 Spring Boot의 프로파일(Profile) 기능에 대해 알아보았습니다. 오늘은 이를 바탕으로 “실제 프로젝트에서 개발(Dev)과 운영(Prod) 환경을 어떻게 깔끔하게 분리할 것인가?”에 대한 실무 전략을 다뤄보려 합니다.

“그냥 파일 따로 만들면 되는 거 아냐?”라고 생각하실 수 있지만, 팀 규모가 커지고 보안 요구사항이 까다로워질수록 환경 분리는 복잡해집니다. 실수로 개발 DB 정보를 운영 서버에 올리는 대형 사고를 막기 위한, 가장 쉽고 안전한 패턴을 소개합니다.


1. 환경 분리가 필요한 이유

환경 분리는 단순히 “편리함”의 문제가 아니라 “안전”의 문제입니다.

  1. 데이터 오염 방지: 개발 중 생성한 테스트 데이터가 운영 DB에 섞이면 안 됩니다.
  2. 보안 사고 예방: 개발자의 실수로 운영 서버가 멈추거나, 운영 DB 비밀번호가 깃허브에 노출되는 것을 막아야 합니다.
  3. 리소스 최적화: 개발 서버는 비용 절감을 위해 낮은 사양을, 운영 서버는 성능을 위해 높은 사양을 사용하므로 튜닝 값이 달라야 합니다.

2. 파일 구조 전략 (The Multi-File Strategy)

가장 권장되는 방식은 “역할별 파일 분리 + 기본값 설정” 전략입니다.

폴더 구조 예시

src/main/resources/
├── application.yml       (공통 설정 + 기본 프로파일 지정)
├── application-local.yml (개인 로컬 PC용)
├── application-dev.yml   (공용 개발 서버용)
└── application-prod.yml  (실제 운영 서버용 - 민감 정보 제외)

1단계: application.yml (공통 설정)

모든 환경에서 변하지 않는 설정을 이곳에 둡니다. 그리고 개발자가 별도 설정 없이 실행했을 때 안전하게 돌아가도록 local을 기본값으로 둡니다.

spring:
  application:
    name: codecamp-service
  profiles:
    active: local # 기본값은 로컬! 실수로 배포해도 운영 DB 안 건드림
  jackson:
    serialization:
      indent-output: true

logging:
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n"

2단계: application-local.yml (로컬 환경)

개발 편의성을 극대화합니다. H2 인메모리 DB를 사용하거나, SQL 로그를 전부 출력합니다.

server:
  port: 8080

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    username: sa
    password: 
  jpa:
    show-sql: true # 쿼리가 눈에 보여야 개발이 편함
    hibernate:
      ddl-auto: create-drop # 껐다 켜면 초기화

3단계: application-prod.yml (운영 환경)

안정성과 보안을 최우선으로 합니다. 여기서 중요한 점은 비밀번호 등 민감 정보를 파일에 직접 적지 않는 것입니다.

server:
  port: 80

spring:
  datasource:
    # 환경 변수나 외부 주입을 받도록 설정 (다음 섹션 참고)
    url: ${PROD_DB_URL}
    username: ${PROD_DB_USER}
    password: ${PROD_DB_PASSWORD}
  jpa:
    show-sql: false # 성능 저하 방지
    hibernate:
      ddl-auto: validate # 스키마 변경 방지 (매우 중요!)

logging:
  level:
    root: INFO
  file:
    name: /var/logs/app.log

3. 빌드 타임 vs 런타임 분리

환경 분리의 핵심은 “코드는 하나(One Artifact), 설정은 실행 시점에(Configuration at Runtime)” 원칙입니다.

나쁜 예 (Anti-Pattern)

  • 소스 코드 내에 if (env == "prod") 로직을 넣는 것.
  • 빌드할 때 mvn build -P prod처럼 빌드 자체를 다르게 하는 것. (빌드된 JAR 파일이 환경마다 다르면 테스트 신뢰도가 떨어집니다.)

좋은 예 (Best Practice)

  • 빌드는 한 번만 수행하여 myapp.jar를 생성합니다. (이 JAR는 개발, 운영, QA 어디서든 동일해야 합니다.)
  • 실행할 때 환경을 결정합니다.
java -jar myapp.jar --spring.profiles.active=dev

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

4. 실무 Tip: include 기능을 활용한 모듈화

환경 설정이 너무 길어지면 include 기능을 사용해 기능별로 쪼갤 수 있습니다.

application-prod.yml

spring:
  profiles:
    include:
      - prod-db      # application-prod-db.yml 로드
      - prod-oauth   # application-prod-oauth.yml 로드
      - prod-logging # application-prod-logging.yml 로드

이렇게 하면 DB 설정 담당자, 보안 담당자가 각자의 파일을 관리할 수 있어 충돌을 줄일 수 있습니다.


[Spring Boot] 개발/운영 환경 분리 전략: 실수로 운영 DB 날려먹지 않는 법 이미지 2

결론

환경 분리는 “사고를 미연에 방지하는 안전장치”입니다.

  1. 기본값은 무조건 로컬(Local)로 설정하세요. (실수로 프로파일 없이 실행해도 안전하도록)
  2. 운영(Prod) 설정에는 절대 스키마 변경(ddl-auto: update/create)을 넣지 마세요.
  3. 하나의 JAR 파일로 모든 환경을 커버할 수 있도록 외부 설정 주입을 생활화하세요.

이 원칙들만 지킨다면, 여러분은 “금요일 오후의 배포”도 두렵지 않은 탄탄한 시스템을 갖추게 될 것입니다.

다음 글에서는 “Spring Boot 포트 번호 변경”에 대한 시시콜콜하지만 꼭 필요한 내용들을 정리해 보겠습니다. 포트 충돌 때문에 고생해보신 분들은 꼭 읽어주세요!

관련 글 보기