프로젝트/쇼핑몰 프로젝트

[쇼핑몰 프로젝트] Spring Boot 민감 정보 보호와 배포 자동화: GitHub Actions secrets & .env 활용

Joo.v7 2025. 7. 31. 23:20

0. 개요

쇼핑몰 프로젝트를 혼자 다시 구현하던 중, 민감 정보(DB 계정, 비밀번호 등)의 보호 방법에 대해 고민하게 되었다.
기존 팀 프로젝트에서는 NHN Cloud의 Key Manager 서비스를 활용했지만, 이번 개인 프로젝트에서는 이를 사용할 수 없어 GitHub Actions Secrets와 .env 파일을 활용한 새로운 방법을 적용하게 되었다.


1. env 파일을 활용하여 로컬에서 민감 정보 관리하기

Spring Boot 2.4 이상에서는 spring.config.import 기능을 사용하여 외부 설정 파일 (.env, .yml 등)을 로드하고, 이를 application.properties에서 사용할 수 있다.

 

(1) 프로젝트 루트 디렉토리에 env 파일 생성.

  • chokchok-api/.env
  • .env 파일은 key=value 형식으로 작성

 

(2) yml 파일에 import 설정 추가.

  • spring.config.import: optional:file:.env[.properties]

 

(3) 환경변수처럼 사용.

  • .env 파일에 정의된 값이 ${...} 형태로 Spring 설정에 주입됨

 

* yml 파일

더보기
# prod profile
server:
  port: 8200

spring:
  config:
    activate:
      on-profile: prod

    # env 파일 로드
    import: optional:file:.env[.properties]

  # MySQL
  datasource:
    url: jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_NAME}?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}

    # HikariCP 설정
    hikari:
      maximum-pool-size: 10
      minimum-idle: 5
      idle-timeout: 600000  # 10분
      max-lifetime: 1800000 # 30분
      connection-timeout: 30000 # 30초
      pool-name: HikariChokChokPool

  # Hibernate
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: validate
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL8Dialect

    # OSIV 비활성화
    open-in-view: false

2. GitHub Actions에서 Secrets로 환경변수 관리하기

앞에서 설정한 .env 파일은 로컬 개발 환경에서만 적용되는 파일이다.
하지만 GitHub Actions를 통한 CI/CD 자동 배포 환경에서는 이 .env 파일이 존재하지 않기 때문에, 동일한 환경변수를 제공해주는 다른 방법이 필요하다.

이를 위해 GitHub Actions에서는 Secrets 기능을 활용한다.
Secrets에 민감 정보를 등록해두고, workflow 파일에서 아래처럼 환경변수로 주입해주면 된다.

 

* GitHub Actions의 workflows 파일

더보기
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

name: Java CI with Maven

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:

    runs-on: ubuntu-latest

    # github Actions을 위해 DB 정보 - secrets를 환경변수로 주입
    env:
      DB_USERNAME: ${{ secrets.DB_USERNAME }}
      DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
      DB_HOST: ${{ secrets.DB_HOST }}
      DB_PORT: ${{ secrets.DB_PORT }}
      DB_NAME: ${{ secrets.DB_NAME }}

    steps:
      - uses: actions/checkout@v4
      - name: Set up JDK 21
        uses: actions/setup-java@v4
        with:
          java-version: '21'
          distribution: 'temurin'
          cache: maven
      - name: Build with Maven
        run: mvn -B package --file pom.xml -Dspring.profiles.active=prod

      # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive
      - name: Update dependency graph
        uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6

      # 파일 업로드
      - name: Upload file
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.SSH_IP }}
          username: ${{ secrets.SSH_ID }}
          key: ${{ secrets.SSH_KEY }}
          port: ${{ secrets.SSH_PORT }}
          source: "target/*.jar"
          target: "/home/chokchok/prod/"
          rm: false

      # 서버의 배포 스크립트 실행
      - name: Execute shell script
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SSH_IP }}
          username: ${{ secrets.SSH_ID }}
          key: ${{ secrets.SSH_KEY }}
          port: ${{ secrets.SSH_PORT }}
          script_stop: true
          script: "~/prod/scripts/api.sh"

3. 서버에서 .env 파일 적용하기

로컬과 CI 환경에서는 각각 .env 파일과 GitHub Secrets를 통해 환경변수를 주입했지만, 문제는 서버 환경에서 .env 파일을 어떻게 적용할까?

 

서버에서는 .env 파일을 .jar와 같은 위치에 두고, spring.config.import 설정을 통해 자동으로 환경변수가 주입되도록 한다.

 

yml 파일에서 spring.config.import: optional:file:.env[.properties] 설정을 했다. 따라서 서버에서 .jar 파일을 실행할 때 .jar 파일이 위치한 디렉토리를 기준으로 .env 파일을 로드한다. 즉, .env 파일을 .jar와 같은 디렉토리에 배치하면 된다.

서버 디렉토리 구조