기술과 산업/언어 및 프레임워크

Spring Boot 시리즈 15편 – 운영 환경 배포 전략: Docker, 무중단 배포, CI/CD 실전 가이드

B컷개발자 2025. 4. 27. 13:32
728x90
Spring Boot 운영 환경 배포 전략을 소개합니다. Docker를 활용한 컨테이너화, 무중단 배포 기법, Spring Boot + CI/CD 구축 흐름까지 실전 사례를 중심으로 정리했습니다.

 


 

Spring Boot 시리즈 15편 – 운영 환경 배포 전략: Docker, 무중단 배포, CI/CD 실전 가이드

 

개발이 끝나고 테스트를 통과했다고 해서 서비스가 성공하는 것은 아닙니다.

운영 환경에서 안정적이고 빠르게, 그리고 다운타임 없이 배포할 수 있어야 비로소 완성입니다.

 

이번 글에서는 Spring Boot 애플리케이션을 Docker로 패키징하고,

무중단 배포를 설계하고, GitHub Actions 또는 GitLab CI로 자동화하는 전략을 단계별로 설명합니다.

 


 

📌 1. 운영 환경 배포의 핵심 목표

목표설명

자동화 수작업 없이 빌드 → 테스트 → 배포 전체 자동화
신뢰성 배포 후 장애나 롤백 없이 정상 운영
속도 소규모 수정이라도 빠르게 적용 가능
무중단 사용자 요청 중단 없이 서비스 지속 제공

 

 


 

✅ 2. Spring Boot를 Docker로 패키징하기

 

 

1️⃣ Dockerfile 작성

# 1. Build Stage
FROM gradle:8.2.1-jdk17 AS build
WORKDIR /app
COPY . .
RUN gradle bootJar

# 2. Runtime Stage
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY --from=build /app/build/libs/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

 

 


 

2️⃣ 빌드 및 실행 명령어

docker build -t myapp:latest .
docker run -d -p 8080:8080 --name myapp-container myapp:latest

 

  • 멀티 스테이지 빌드를 사용해 빌드 이미지 크기를 최소화
  • 운영 환경에는 오직 실행 파일(app.jar)만 포함

 


 

🔄 3. 무중단 배포(Zero Downtime Deployment) 설계

 

 

1️⃣ Blue-Green 배포 기본 흐름

[Blue 서버] 현재 운영중
        ↓
[Green 서버] 새 버전 배포 완료
        ↓
로드밸런서 트래픽 전환
        ↓
Blue 서버 종료

 

  • 항상 2개의 서버를 준비하고 새 버전에 문제가 없으면 트래픽을 전환
  • 문제 발생 시 즉시 이전 버전(Blue)으로 복구 가능

 


 

2️⃣ Rolling Update (Docker Compose 예시)

services:
  app:
    image: myapp:latest
    ports:
      - "8080:8080"
    deploy:
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure

 

  • 한 번에 1개 컨테이너만 업데이트 → 안정성 ↑
  • 실패 시 자동 롤백 설정 가능

 


 

⚙️ 4. CI/CD 자동화 흐름 구축

 

 

1️⃣ GitHub Actions 예시 (

.github/workflows/deploy.yml

)

name: CI/CD Pipeline

on:
  push:
    branches:
      - main

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: 소스코드 체크아웃
        uses: actions/checkout@v3

      - name: JDK 설정
        uses: actions/setup-java@v3
        with:
          java-version: '17'

      - name: Gradle 빌드
        run: ./gradlew bootJar

      - name: Docker 이미지 빌드
        run: docker build -t myapp:latest .

      - name: DockerHub 로그인
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Docker 이미지 푸시
        run: docker push myapp:latest

      - name: 서버 SSH 배포
        uses: appleboy/ssh-action@v0.1.6
        with:
          host: ${{ secrets.SERVER_IP }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SERVER_SSH_KEY }}
          script: |
            docker pull myapp:latest
            docker stop myapp-container || true
            docker rm myapp-container || true
            docker run -d -p 8080:8080 --name myapp-container myapp:latest

 

 


 

🧠 실무 적용 팁

항목전략

외부 환경 변수 관리 Dockerfile이나 서버에 환경 변수 별도 주입
무중단 점검 URL 배포 완료 후 /health 엔드포인트 체크 후 트래픽 전환
롤백 전략 Docker 이미지 태그 관리 (v1, v2)로 롤백 가능성 준비
Slack 알림 연동 배포 성공/실패 결과를 Slack으로 전송
DB 마이그레이션 Flyway, Liquibase 도구를 통한 자동 스키마 관리

 

 


 

✅ 마무리 요약

항목정리

컨테이너화 Docker 기반 배포, 멀티 스테이지 최적화
무중단 전략 Blue-Green 또는 Rolling Update 적용
CI/CD 구성 GitHub Actions → Build → Test → Docker Build → Deploy
운영 체크 Health Check, 자동 복구 설정
확장 방향 Kubernetes, ArgoCD를 통한 완전 자동화도 가능

 

 


 

📌 다음 편 예고

 

Spring Boot 시리즈 16편: 고급 캐시 전략 – 멀티 레벨 캐시(L1+L2)와 데이터 일관성 관리

 

728x90