Spring Boot 보안 꿀팁: 환경 변수로 DB 비밀번호 안전하게 관리하는 법

Spring Boot 보안 꿀팁: 환경 변수로 DB 비밀번호 안전하게 관리하는 법 이미지 1

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

오픈소스 프로젝트나 개인 프로젝트를 깃허브(GitHub)에 올릴 때, 가장 흔하게 발생하는 사고가 무엇일까요? 바로 AWS 액세스 키나 DB 비밀번호가 포함된 설정 파일을 그대로 커밋(Commit)해 버리는 것입니다.

이렇게 노출된 키는 해커들의 먹잇감이 되어, 하룻밤 사이에 수천만 원의 클라우드 요금 폭탄을 맞을 수도 있습니다.

오늘은 이러한 비극을 막기 위해, 민감한 설정 정보를 코드에서 분리하고 환경 변수(Environment Variables)로 안전하게 관리하는 방법을 알아보겠습니다. Twelve-Factor App 방법론에서도 설정(Config)은 코드에서 엄격하게 분리할 것을 권장합니다.


1. Spring Boot의 설정 우선순위

Spring Boot는 매우 유연한 설정 주입 방식을 제공합니다. 같은 키 값(spring.datasource.password)이 여러 곳에 정의되어 있다면, 다음 우선순위에 따라 덮어씌워집니다.

  1. 커맨드 라인 인자 (최상위)
  2. JAVA_OPTS 등 시스템 프로퍼티
  3. OS 환경 변수
  4. application-{profile}.yml
  5. application.yml (최하위)

우리는 이 중에서 3번 OS 환경 변수를 적극 활용할 것입니다.


2. application.yml에서 환경 변수 참조하기

가장 깔끔한 방법은 YAML 파일에는 “참조”만 걸어두고, 실제 값은 운영체제가 주입하도록 하는 것입니다.

${변수명:기본값} 문법

${ENV_VAR} 형식을 사용하면 Spring Boot가 기동될 때 해당 환경 변수 값을 찾아 치환해 줍니다. 콜론(:) 뒤에 기본값을 적을 수도 있습니다.

spring:
  datasource:
    url: ${DB_URL:jdbc:mysql://localhost:3306/devdb} # 환경 변수 없으면 로컬 DB 사용
    username: ${DB_USER:devuser}
    password: ${DB_PASSWORD} # 기본값 없음. 환경 변수 필수!

security:
  jwt:
    secret-key: ${JWT_SECRET}
  oauth2:
    client:
      google:
        client-id: ${GOOGLE_CLIENT_ID}
        client-secret: ${GOOGLE_CLIENT_SECRET}

이렇게 작성하면, 이 application.yml 파일이 깃허브에 올라가도 실제 비밀번호는 노출되지 않습니다. DB_PASSWORD라는 변수명만 노출될 뿐이죠.


3. 로컬 개발 환경에서 환경 변수 설정하기

개발할 때마다 매번 환경 변수를 세팅하는 건 번거롭습니다. IDE(IntelliJ, Eclipse)의 기능을 활용하세요.

IntelliJ IDEA 기준

  1. Run/Debug Configurations 창을 엽니다.
  2. Environment variables 항목의 폴더 아이콘을 클릭합니다.
  3. Key-Value 쌍을 추가합니다.
    • DB_PASSWORD : 1234
    • JWT_SECRET : my-secret-key-1234

이제 실행 버튼을 누르면 IDE가 알아서 환경 변수를 주입해서 애플리케이션을 띄워줍니다.


4. 운영 서버(Linux/Docker)에서 설정하기

실제 배포 환경에서는 어떻게 할까요?

4.1. 리눅스 쉘 (Shell)

.bashrc.bash_profile에 등록하거나, 실행 직전에 export 합니다.

export DB_URL=jdbc:mysql://prod-db:3306/production
export DB_USER=admin
export DB_PASSWORD=very-complex-password

java -jar my-app.jar

4.2. Docker Compose

docker-compose.yml 파일에서 environment 섹션을 사용합니다.

version: '3.8'
services:
  myapp:
    image: my-spring-app
    ports:
      - "8080:8080"
    environment:
      - DB_URL=jdbc:mysql://mysql:3306/prod
      - DB_USER=admin
      # 호스트 OS의 환경 변수를 컨테이너로 전달 (비밀번호 노출 방지)
      - DB_PASSWORD=${HOST_DB_PASSWORD} 

5. 완화된 바인딩 (Relaxed Binding)

Spring Boot는 환경 변수의 이름 규칙을 유연하게 처리해 줍니다. 이를 Relaxed Binding이라고 합니다.

YAML에서 spring.datasource.url이라고 썼다면, 환경 변수로는 다음 모두가 허용됩니다.

  • SPRING_DATASOURCE_URL (대문자 + 언더바 권장)
  • spring.datasource.url
  • spring_datasource_url

리눅스 환경 변수 표준은 대문자 + 언더바이므로, 보통 SPRING_DATASOURCE_URL 형태로 작성하는 것이 관례입니다.


Spring Boot 보안 꿀팁: 환경 변수로 DB 비밀번호 안전하게 관리하는 법 이미지 2

결론

“Secret은 코드 저장소(Git)에 있어서는 안 됩니다.”

환경 변수를 활용한 설정 관리는 보안의 기본 중의 기본입니다.

  1. application.yml에는 ${VAR} 형태로 플레이스홀더만 남기세요.
  2. 로컬 개발은 IDE 설정으로, 운영 배포는 OS 환경 변수나 CI/CD 파이프라인의 Secret 변수로 주입하세요.
  3. 이렇게 하면 코드는 하나지만, 환경에 따라 완벽하게 다른 설정으로 안전하게 동작하는 애플리케이션을 만들 수 있습니다.

지금까지 7편에 걸쳐 Spring Boot의 설정(Configuration) 마스터 가이드를 진행했습니다.
application.yml 문법부터 프로파일, 로그, 그리고 보안 설정까지. 이 시리즈가 여러분의 탄탄한 백엔드 개발에 도움이 되었기를 바랍니다.

감사합니다!

관련 글 보기