요약
GitHub Actions로 Spring Boot CI/CD 구축 2026
2026년 최신 기술 트렌드에 맞춰 GitHub Actions를 활용한 Spring Boot 프로젝트의 CI/CD 파이프라인 구축 및 배포 자동화 가이드입니다.
핵심 키워드: CI/CD, GitHub Actions, Spring Boot
이 글의 순서
1. CI/CD, 왜 2026년에 더 중요할까요?
2. GitHub Actions 기반 CI/CD 파이프라인 핵심 분석
3. 마주할 수 있는 기술적 도전과 해결책
4. 실전 가이드: Spring Boot CI/CD 워크플로우 구축
5. 배포 자동화, 그 이상의 가치와 미래
도입
CI/CD, 왜 2026년에 더 중요할까요?
안녕하세요, 권퓨터입니다! 2026년, 소프트웨어 개발 환경은 그 어느 때보다 빠르게 변화하고 있습니다. 마이크로서비스 아키텍처, 클라우드 네이티브 애플리케이션, 그리고 데브옵스(DevOps) 문화가 보편화되면서, 개발부터 배포까지의 과정을 얼마나 효율적으로 관리하느냐가 프로젝트의 성패를 좌우하는 핵심 요소가 되었죠. 특히 백엔드 개발에서 Spring Boot는 여전히 강력한 생태계를 자랑하며 많은 기업에서 사용되고 있습니다. 이러한 Spring Boot 프로젝트를 빠르고 안정적으로 배포하기 위한 필수 전략이 바로 CI/CD(Continuous Integration/Continuous Delivery)입니다.
과거에는 개발자가 코드를 작성하고, 빌드하고, 테스트한 다음, 수동으로 서버에 배포하는 과정이 일반적이었습니다. 이 과정은 시간이 많이 소요될 뿐만 아니라, 사람의 실수로 인한 오류 발생 가능성이 매우 높았습니다. 코드 충돌, 환경 설정 오류, 누락된 빌드 스텝 등으로 인해 배포 실패는 다반사였죠. 특히 복잡도가 높은 대규모 프로젝트에서는 이러한 수동 배포의 비효율성이 더욱 두드러집니다.
CI/CD는 이러한 문제를 해결하기 위한 자동화된 접근 방식입니다. 개발자가 코드를 변경할 때마다 자동으로 빌드, 테스트, 그리고 배포 단계를 거치게 하여, 소프트웨어의 품질을 높이고 시장 출시 시간을 단축시키는 것을 목표로 합니다. 특히 GitHub Actions는 GitHub 저장소와 긴밀하게 통합되어 있어, 별도의 CI/CD 서버를 구축할 필요 없이 YAML 파일 몇 줄로 강력한 자동화 파이프라인을 구축할 수 있다는 큰 장점이 있습니다.
이번 포스팅에서는 Spring Boot 백엔드 프로젝트를 대상으로, GitHub Actions를 활용하여 CI/CD 파이프라인을 구축하고 배포를 자동화하는 방법을 상세하게 알아보겠습니다. 개발 환경 설정부터 워크플로우 작성, 그리고 실제 서버에 배포하는 과정까지, 단계별로 따라오시면 누구나 자신만의 배포 자동화 시스템을 구축할 수 있을 거예요. 그럼, 함께 배포 자동화의 세계로 떠나볼까요?
핵심 분석
GitHub Actions 기반 CI/CD 파이프라인 핵심 분석
CI/CD 기본 개념 다시 보기
GitHub Actions를 활용하기 전에 CI/CD가 정확히 무엇인지 짚고 넘어가는 것이 중요합니다. CI/CD는 크게 두 가지 개념으로 나뉩니다.
CI (Continuous Integration, 지속적인 통합)
목표 — 개발자가 작성한 코드를 중앙 저장소에 자주 병합하고, 병합 시마다 자동으로 빌드 및 테스트를 수행하여 코드 충돌이나 버그를 조기에 발견합니다.
핵심 활동 — 코드 커밋, 자동 빌드, 단위 및 통합 테스트 실행, 코드 품질 검사.
CD (Continuous Delivery/Deployment, 지속적인 제공/배포)
Continuous Delivery (지속적인 제공) — 빌드되고 테스트된 소프트웨어를 언제든지 배포할 수 있는 상태로 유지합니다. 실제 운영 환경 배포는 수동으로 결정합니다.
Continuous Deployment (지속적인 배포) — 테스트를 통과한 모든 변경 사항을 자동으로 운영 환경에 배포합니다. 사람의 개입 없이 완전 자동화됩니다.
이번 포스팅에서는 CI와 Continuous Deployment를 함께 다루며, 코드 변경이 발생하면 자동으로 빌드, 테스트, 그리고 최종 서버 배포까지 이루어지는 완전 자동화 파이프라인을 목표로 합니다.
GitHub Actions 소개 및 주요 구성 요소
GitHub Actions는 GitHub에서 제공하는 CI/CD 서비스로, 저장소 내에서 소프트웨어 개발 워크플로우를 자동화할 수 있도록 해줍니다. .github/workflows 디렉토리 안에 YAML 파일을 생성하여 워크플로우를 정의하며, 코드 푸시, 풀 리퀘스트 생성 등 다양한 GitHub 이벤트에 반응하여 실행될 수 있습니다.
주요 구성 요소는 다음과 같습니다:
GitHub Actions 핵심 구성 요소
워크플로우 (Workflow) — 하나 이상의 작업을 포함하는 자동화된 프로세스입니다. YAML 파일로 정의되며, 특정 이벤트(예: push, pull_request)에 의해 트리거됩니다.
이벤트 (Event) — 워크플로우를 트리거하는 특정 활동입니다. (예: 코드 푸시, 풀 리퀘스트 오픈, 스케줄링 등)
작업 (Job) — 워크플로우 내에서 실행되는 일련의 단계(steps)입니다. 각 작업은 별도의 가상 환경(runner)에서 실행될 수 있으며, 독립적으로 또는 다른 작업에 의존하여 실행됩니다.
단계 (Step) — 작업 내에서 실행되는 개별 명령 또는 액션입니다. (예: 코드 체크아웃, 의존성 설치, 스크립트 실행)
액션 (Action) — 특정 작업을 수행하기 위한 재사용 가능한 코드 블록입니다. GitHub Marketplace에서 다양한 액션을 찾아 사용할 수 있으며, 직접 만들 수도 있습니다. (예: actions/checkout@v4, actions/setup-java@v4)
러너 (Runner) — 워크플로우를 실행하는 서버 환경입니다. GitHub 호스팅 러너(Ubuntu, Windows, macOS)를 사용할 수도 있고, 자체 호스팅 러너를 구성할 수도 있습니다.


핵심 포인트
GitHub Actions는 YAML 기반의 선언적인 방식으로 CI/CD 워크플로우를 정의하며, 다양한 이벤트에 반응하여 빌드, 테스트, 배포 등 개발 과정을 자동화합니다. 특히 GitHub 저장소와의 긴밀한 연동이 큰 장점입니다.
Spring Boot 프로젝트 준비: Dockerfile 작성
Spring Boot 애플리케이션을 CI/CD 파이프라인에 통합할 때, Docker를 활용하는 것이 일반적이고 효율적입니다. Docker를 사용하면 애플리케이션과 모든 종속성을 컨테이너 이미지로 패키징하여, 어떤 환경에서든 동일하게 실행될 수 있도록 보장할 수 있습니다. 이를 위해 먼저 프로젝트 루트에 Dockerfile을 작성해야 합니다.
다음은 일반적인 Spring Boot 애플리케이션용 Dockerfile 예시입니다. 멀티스테이지 빌드를 사용하여 최종 이미지 크기를 최적화합니다.
코드 설명
이 Dockerfile은 두 단계로 Spring Boot 애플리케이션을 빌드하고 패키징합니다. 첫 번째 단계(builder)에서 애플리케이션을 빌드하고 JAR 파일을 생성하며, 두 번째 단계(runner)에서 OpenJDK 기반의 경량 런타임 이미지를 사용하여 최종 실행 가능한 이미지를 만듭니다. 이를 통해 최종 Docker 이미지의 크기를 크게 줄일 수 있습니다.
# Stage 1: Build the Spring Boot application
FROM openjdk:17-jdk-slim as builder
WORKDIR /app
# Copy the Gradle wrapper files
COPY gradlew .
COPY gradle gradle
# Copy the build.gradle and settings.gradle files
COPY build.gradle .
COPY settings.gradle .
# Copy the source code
COPY src src
# Make gradlew executable
RUN chmod +x gradlew
# Build the application
# Use --no-daemon to prevent Gradle daemon issues in CI environments
# Use -x test to skip tests during build if they will be run separately in CI
RUN ./gradlew bootJar --no-daemon
# Stage 2: Create the final production image
FROM openjdk:17-jre-slim
WORKDIR /app
# Copy the built JAR file from the builder stage
COPY --from=builder /app/build/libs/*.jar app.jar
# Expose the port on which the Spring Boot application runs
EXPOSE 8080
# Run the Spring Boot application
ENTRYPOINT ["java", "-jar", "app.jar"]
참고: 만약 Maven을 사용한다면 ./gradlew bootJar 대신 mvn clean package -DskipTests와 같은 명령어를 사용하고, 필요한 Maven 관련 파일을 복사해야 합니다.
CI/CD 파이프라인 설계: 단계별 구성
일반적인 Spring Boot 프로젝트의 GitHub Actions CI/CD 파이프라인은 다음과 같은 단계로 구성될 수 있습니다.
CI/CD 파이프라인 주요 단계
1. 코드 체크아웃 — GitHub 저장소의 최신 코드를 워크플로우 러너로 가져옵니다.
2. Java 환경 설정 — Spring Boot 빌드에 필요한 Java Development Kit(JDK)을 설정합니다.
3. 종속성 캐싱 — Gradle/Maven 종속성을 캐싱하여 빌드 시간을 단축합니다.
4. 애플리케이션 빌드 — Spring Boot 프로젝트를 빌드하여 JAR 파일을 생성합니다. 이때 테스트도 함께 실행하는 것이 좋습니다.
5. Docker 이미지 빌드 — 앞에서 작성한 Dockerfile을 사용하여 애플리케이션의 Docker 이미지를 빌드합니다.
6. Docker 이미지 푸시 — 빌드된 Docker 이미지를 Docker Hub나 GitHub Container Registry와 같은 컨테이너 레지스트리에 푸시합니다.
7. 서버 배포 — 원격 서버에 SSH로 접속하여 최신 Docker 이미지를 풀(pull)받아 실행하거나, JAR 파일을 직접 실행하는 방식으로 배포를 수행합니다.


비교 분석: 주요 CI/CD 도구 (Jenkins, GitLab CI, GitHub Actions)
GitHub Actions 외에도 다양한 CI/CD 도구들이 존재합니다. 각각의 장단점을 간단히 비교하여, 왜 GitHub Actions가 Spring Boot 프로젝트에 특히 적합한지 이해해봅시다.
GitHub Actions의 장점
✓ GitHub 통합: 코드와 CI/CD 워크플로우를 한곳에서 관리하여 개발 흐름이 자연스럽습니다.
✓ 쉬운 설정: YAML 기반으로 간결하게 워크플로우를 정의할 수 있습니다.
✓ 풍부한 액션 마켓플레이스: 다양한 재사용 가능한 액션으로 복잡한 작업도 쉽게 구현 가능합니다.
✓ 무료 사용량 제공: 소규모 프로젝트나 오픈소스 프로젝트에는 충분한 무료 사용량을 제공합니다.
GitHub Actions의 단점
✗ 복잡한 워크플로우 관리: 대규모/복잡한 파이프라인의 경우 YAML 파일이 길어져 가독성이 떨어질 수 있습니다.
✗ 온프레미스 제약: GitHub 호스팅 러너 외에 자체 러너를 설정해야 할 수 있습니다.
Jenkins의 장점
✓ 높은 유연성: 거의 모든 CI/CD 시나리오에 적용 가능하며, 수많은 플러그인을 제공합니다.
✓ 온프레미스 지원: 자체 서버에 구축하여 보안 및 제어력을 높일 수 있습니다.
✓ 오랜 역사와 커뮤니티: 방대한 자료와 활발한 커뮤니티 지원을 받을 수 있습니다.
Jenkins의 단점
✗ 복잡한 설정 및 유지보수: 초기 설정과 운영에 많은 시간과 노력이 필요합니다.
✗ 인프라 비용: 자체 서버를 운영해야 하므로 인프라 비용이 발생합니다.
GitLab CI의 장점
✓ GitLab 통합: 저장소 관리, 이슈 트래킹 등 GitLab의 모든 기능과 통합되어 있습니다.
✓ 단일 플랫폼: 개발 라이프사이클 전체를 GitLab 단일 플랫폼에서 관리할 수 있습니다.
✓ Docker 지원: Docker를 기본적으로 지원하여 컨테이너 기반 CI/CD에 강합니다.
GitLab CI의 단점
✗ GitLab 종속성: GitLab을 사용하지 않는 프로젝트에서는 활용하기 어렵습니다.
✗ 학습 곡선: GitLab CI의 개념과 Runner 설정 등에 대한 학습이 필요합니다.
결론적으로, GitHub에서 Spring Boot 프로젝트를 관리하고 있다면 GitHub Actions는 가장 자연스럽고 효율적인 CI/CD 선택지입니다. 별도의 인프라 구축 없이 빠르고 간편하게 자동화 파이프라인을 구축할 수 있다는 점에서 특히 매력적입니다.
핵심 포인트
GitHub Actions는 GitHub 저장소와의 완벽한 통합, 쉬운 설정, 풍부한 액션 마켓플레이스 덕분에 Spring Boot 프로젝트의 CI/CD 구축에 매우 적합한 도구입니다.
문제 해결
마주할 수 있는 기술적 도전과 해결책
CI/CD 파이프라인을 구축하는 과정에서 몇 가지 기술적인 도전과 마주할 수 있습니다. 이러한 문제들을 미리 파악하고 적절한 해결책을 적용하는 것이 안정적인 배포 자동화를 위해 중요합니다.
환경 변수 관리: GitHub Secrets 활용
데이터베이스 비밀번호, API 키, SSH 키 등 민감한 정보는 절대로 워크플로우 파일(YAML)에 직접 노출해서는 안 됩니다. GitHub Actions는 이를 위해 Secrets 기능을 제공합니다.
문제 01
민감한 정보를 워크플로우에 안전하게 전달해야 합니다.
데이터베이스 URL, 사용자 이름, 비밀번호, Docker Registry 토큰, SSH 프라이빗 키 등은 공개되어서는 안 되는 중요한 정보입니다. 이를 YAML 파일에 직접 작성하면 보안 취약점이 발생합니다.
해결 — GitHub Secrets에 저장하고 워크플로우에서 참조
GitHub 저장소 설정에서 Secrets 탭으로 이동하여 필요한 환경 변수를 추가합니다. 워크플로우에서는 ${{ secrets.SECRET_NAME }} 형식으로 참조할 수 있습니다. 이 값들은 러너 환경에 안전하게 주입되며, 로그에도 노출되지 않습니다.
# 워크플로우 YAML 파일 내에서 Secrets 사용 예시
- name: Deploy to Server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
# 배포 스크립트 실행
echo "Deployment started on ${{ secrets.SERVER_HOST }}"
빌드 시간 최적화: 캐싱 전략
Spring Boot 프로젝트는 Gradle이나 Maven을 사용하여 의존성을 관리합니다. 매번 빌드를 실행할 때마다 모든 의존성을 다시 다운로드하면 빌드 시간이 길어지고, GitHub Actions의 무료 사용량도 빠르게 소진될 수 있습니다. actions/cache 액션을 사용하여 빌드 종속성을 캐싱하면 이러한 문제를 해결할 수 있습니다.
Gradle 의존성 캐싱 사례
Gradle 캐시 디렉토리(~/.gradle/caches)를 캐싱하여, 다음 빌드 시 빠르게 의존성을 로드합니다.
이 GitHub Actions 스텝은 Gradle의 종속성 캐시를 관리합니다. cache-hit 변수를 통해 캐시 적중 여부를 확인하고, 캐시가 없는 경우에만 Gradle 종속성을 다운로드하도록 하여 빌드 시간을 단축시킵니다.
- name: Cache Gradle dependencies
uses: actions/cache@v4
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Check Cache Hit
id: cache-check
run: echo "cache-hit=${{ steps.cache-gradle.outputs.cache-hit }}" >> $GITHUB_OUTPUT
위 코드에서 key는 캐시를 식별하는 고유한 값으로, hashFiles를 사용하여 .gradle 파일이나 gradle-wrapper.properties 파일이 변경될 때만 새로운 캐시를 생성하도록 합니다. 이렇게 하면 변경이 없을 때는 기존 캐시를 재사용하여 빌드 속도를 크게 향상시킬 수 있습니다.

핵심 포인트
GitHub Secrets로 민감한 정보를 안전하게 관리하고, actions/cache 액션을 활용하여 빌드 시간을 단축하는 것은 CI/CD 파이프라인의 보안과 효율성을 동시에 높이는 핵심 전략입니다.
실전 가이드
실전 가이드: Spring Boot CI/CD 워크플로우 구축
이제 실제로 GitHub Actions 워크플로우를 작성하여 Spring Boot 프로젝트의 CI/CD 파이프라인을 구축해봅시다. 이 가이드에서는 Gradle 빌드 도구를 사용하며, Docker 이미지를 빌드하여 Docker Hub에 푸시한 후, 원격 서버에 SSH로 접속하여 배포하는 시나리오를 따릅니다.
워크플로우 파일 생성
먼저, GitHub 저장소의 루트 디렉토리에 .github/workflows/ 디렉토리를 생성합니다. 그리고 그 안에 main-ci-cd.yml과 같은 이름의 YAML 파일을 생성합니다. 이 파일이 우리의 CI/CD 워크플로우를 정의하게 됩니다.
Spring Boot CI/CD 워크플로우 예시
다음은 Spring Boot 애플리케이션을 빌드, Docker 이미지화, Docker Hub 푸시, 그리고 원격 서버 배포까지 수행하는 전체 워크플로우 예시입니다. 각 단계별로 자세히 살펴보겠습니다.
코드 설명
이 YAML 파일은 GitHub Actions 워크플로우를 정의합니다. main 브랜치에 푸시가 발생할 때마다 실행되며, Java 환경 설정, Gradle 캐싱, Spring Boot 빌드 및 테스트, Docker 이미지 빌드 및 Docker Hub 푸시, 그리고 최종적으로 원격 서버에 SSH를 통해 배포하는 과정을 자동화합니다. 민감한 정보는 GitHub Secrets를 통해 안전하게 관리됩니다.
name: Spring Boot CI/CD Pipeline
on:
push:
branches:
- main # main 브랜치에 푸시될 때 워크플로우 실행
pull_request:
branches:
- main # main 브랜치로 풀 리퀘스트가 생성될 때 워크플로우 실행 (CI만)
env:
JAVA_VERSION: '17'
GRADLE_VERSION: '8.x'
DOCKER_IMAGE_NAME: ${{ github.repository }} # GitHub 저장소 이름을 Docker 이미지 이름으로 사용
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }} # Docker Hub 사용자 이름 (Secrets)
jobs:
build-and-deploy:
runs-on: ubuntu-latest # Ubuntu 환경에서 실행
steps:
- name: Checkout Code
uses: actions/checkout@v4 # 저장소 코드 체크아웃
- name: Set up JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v4
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: 'temurin'
cache: 'gradle' # Gradle 캐시 설정
- name: Cache Gradle dependencies
uses: actions/cache@v4
id: cache-gradle # 캐시 스텝에 ID 부여
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Grant execute permission for gradlew
run: chmod +x gradlew # gradlew 실행 권한 부여
- name: Build and Test Spring Boot Application
run: ./gradlew clean build # Spring Boot 빌드 및 테스트 실행
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ env.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }} # Docker Hub 토큰 (Secrets)
- name: Build and Push Docker Image
run: |
docker build -t ${{ env.DOCKER_HUB_USERNAME }}/${{ env.DOCKER_IMAGE_NAME }}:latest .
docker push ${{ env.DOCKER_HUB_USERNAME }}/${{ env.DOCKER_IMAGE_NAME }}:latest
working-directory: ./ # Dockerfile이 있는 디렉토리 지정 (보통 프로젝트 루트)
- name: Deploy to Remote Server via SSH
uses: appleboy/ssh-action@master # SSH 접속 및 명령 실행 액션
with:
host: ${{ secrets.SERVER_HOST }} # 원격 서버 IP (Secrets)
username: ${{ secrets.SERVER_USERNAME }} # 원격 서버 사용자 이름 (Secrets)
key: ${{ secrets.SSH_PRIVATE_KEY }} # SSH 프라이빗 키 (Secrets)
script: |
# 원격 서버에서 실행될 스크립트
# 1. 기존 실행 중인 Docker 컨테이너 중지 및 삭제
echo "Stopping existing Docker container..."
docker stop ${{ env.DOCKER_IMAGE_NAME }} || true
docker rm ${{ env.DOCKER_IMAGE_NAME }} || true
# 2. 최신 Docker 이미지 풀
echo "Pulling latest Docker image from Docker Hub..."
docker pull ${{ env.DOCKER_HUB_USERNAME }}/${{ env.DOCKER_IMAGE_NAME }}:latest
# 3. 새로운 Docker 컨테이너 실행
echo "Running new Docker container..."
docker run -d --name ${{ env.DOCKER_IMAGE_NAME }} -p 8080:8080 \
-e SPRING_PROFILES_ACTIVE=prod \
-e DB_URL=${{ secrets.PROD_DB_URL }} \
-e DB_USERNAME=${{ secrets.PROD_DB_USERNAME }} \
-e DB_PASSWORD=${{ secrets.PROD_DB_PASSWORD }} \
${{ env.DOCKER_HUB_USERNAME }}/${{ env.DOCKER_IMAGE_NAME }}:latest
echo "Deployment to remote server completed successfully!"
핵심 포인트: 위 워크플로우는 코드가 main 브랜치에 푸시될 때마다 자동으로 빌드, 테스트, Docker 이미지 생성 및 푸시, 그리고 원격 서버 배포까지 일련의 과정을 수행합니다. 모든 민감 정보는 GitHub Secrets를 통해 관리되므로 보안에 강합니다.
배포 스크립트 예시 (SSH 없이 JAR 파일 직접 배포 시)
만약 Docker를 사용하지 않고 JAR 파일을 직접 서버에 배포하고 싶다면, SSH 액션 내에서 다음과 같은 배포 스크립트를 사용할 수 있습니다. 이 스크립트는 기존 애플리케이션을 중지하고, 새로운 JAR 파일을 복사한 후, 다시 실행하는 과정을 포함합니다.
코드 설명
이 셸 스크립트는 원격 서버에서 Spring Boot JAR 파일을 배포하는 과정을 자동화합니다. 기존 프로세스를 종료하고, GitHub Actions에서 전송된 새로운 JAR 파일을 복사한 후, nohup과 백그라운드 실행을 사용하여 애플리케이션을 다시 시작합니다. PROD_DB_URL과 같은 환경 변수는 서버 환경에 맞게 설정해야 합니다.
#!/bin/bash
# Define application variables
APP_NAME="my-springboot-app"
JAR_PATH="/home/ubuntu/${APP_NAME}/${APP_NAME}.jar"
LOG_PATH="/home/ubuntu/${APP_NAME}/application.log"
# Stop existing application
echo "Stopping existing application ($APP_NAME)..."
CURRENT_PID=$(pgrep -f ${APP_NAME}.jar)
if [ -z "$CURRENT_PID" ]; then
echo "No existing application found."
else
kill -15 $CURRENT_PID
echo "Application stopped (PID: $CURRENT_PID)."
sleep 5 # Give time for graceful shutdown
fi
# Create application directory if it doesn't exist
mkdir -p /home/ubuntu/${APP_NAME}
# Copy the new JAR file (assuming it's transferred via SCP or another method)
# For GitHub Actions, you'd typically use `scp-action` before this script
echo "Copying new JAR file to $JAR_PATH..."
# Example: If using `scp-action` to transfer the JAR:
# cp /tmp/${APP_NAME}.jar $JAR_PATH
# For this example, let's assume the JAR is already in /tmp/ from a previous step
# You would need to adapt this based on how your JAR reaches the server.
# For `appleboy/ssh-action`, you'd usually have the JAR in the GitHub Actions workspace
# and then copy it to the server.
# A common pattern is to `scp` the JAR in a separate `appleboy/scp-action` step.
# For direct execution within `appleboy/ssh-action` script parameter,
# you'd need the JAR to be already on the server or use a more complex setup.
# Let's simplify and assume the JAR is on the runner and copied to the server via SSH.
# A better approach for JAR deployment with `appleboy/ssh-action` is to use `scp-action` first:
# - name: Transfer JAR to Server
# uses: appleboy/scp-action@master
# with:
# host: ${{ secrets.SERVER_HOST }}
# username: ${{ secrets.SERVER_USERNAME }}
# key: ${{ secrets.SSH_PRIVATE_KEY }}
# source: 'build/libs/*.jar' # Path to your JAR in GitHub Actions runner
# target: '/home/ubuntu/${APP_NAME}/'
# Then, in the `ssh-action` script:
echo "Starting new application ($APP_NAME)..."
nohup java -jar \
-Dspring.profiles.active=prod \
-DDB_URL=${PROD_DB_URL} \
-DDB_USERNAME=${PROD_DB_USERNAME} \
-DDB_PASSWORD=${PROD_DB_PASSWORD} \
$JAR_PATH > $LOG_PATH 2>&1 &
echo "Application started. Check logs at $LOG_PATH"
주의: 위의 스크립트 예시는 SSH 액션 내에서 실행될 때의 일반적인 흐름을 보여줍니다. 실제 JAR 파일 전송은 appleboy/scp-action과 같은 별도의 액션을 통해 먼저 수행하는 것이 일반적입니다. 이후 appleboy/ssh-action으로 서버에 접속하여 해당 스크립트를 실행하면 됩니다.
GitHub Secrets 설정 방법
앞서 언급했듯이 민감한 정보는 GitHub Secrets에 저장해야 합니다. 설정 방법은 다음과 같습니다.
1
저장소 설정으로 이동
GitHub 저장소 페이지에서 Settings 탭을 클릭합니다.
2
Secrets 메뉴 선택
왼쪽 사이드바에서 Secrets and variables > Actions를 선택합니다.
3
새로운 시크릿 추가
New repository secret 버튼을 클릭하고, Name과 Value를 입력한 후 Add secret을 클릭합니다. 예를 들어, DOCKER_HUB_USERNAME, DOCKER_HUB_TOKEN, SERVER_HOST, SERVER_USERNAME, SSH_PRIVATE_KEY 등을 추가할 수 있습니다.
주의사항
SSH Private Key를 Secrets에 추가할 때는 개행 문자(newline characters)를 포함하여 정확하게 복사-붙여넣기 해야 합니다. 또한, SSH 키는 강력한 비밀번호로 보호하고, 해당 키가 접근할 수 있는 서버의 권한을 최소화하는 것이 보안상 매우 중요합니다.
마무리
배포 자동화, 그 이상의 가치와 미래
지금까지 GitHub Actions를 활용하여 Spring Boot 프로젝트의 CI/CD 파이프라인을 구축하는 방법을 자세히 살펴보았습니다. 2026년의 개발 환경에서 배포 자동화는 선택이 아닌 필수적인 요소가 되었으며, GitHub Actions는 이러한 요구사항을 충족시키기에 매우 강력하고 편리한 도구입니다.
이번 가이드를 통해 여러분은 다음을 달성할 수 있습니다:
CI/CD 구축의 주요 이점
✓ 개발 생산성 향상: 수동 작업 최소화로 개발자들이 코드 작성에 집중할 수 있습니다.
✓ 소프트웨어 품질 향상: 자동화된 테스트와 빌드 검증으로 버그를 조기에 발견하고 수정합니다.
✓ 빠른 시장 출시 (Time-to-Market): 새로운 기능이나 버그 수정이 즉시 배포될 수 있도록 합니다.
✓ 안정적인 배포: 일관된 자동화 프로세스로 배포 오류를 줄이고 안정성을 높입니다.
✓ 팀 협업 강화: 모든 팀원이 동일한 배포 프로세스를 공유하고 신뢰할 수 있습니다.
이것은 CI/CD 여정의 시작일 뿐입니다. 더 나아가 다음과 같은 부분들을 고려하여 파이프라인을 더욱 고도화할 수 있습니다:
향후 파이프라인 고도화 방안
Rollback (롤백) 전략: 배포 실패 시 이전 버전으로 빠르게 되돌릴 수 있는 자동화된 롤백 기능을 추가합니다.
모니터링 및 알림: 배포 성공/실패 여부를 Slack, 이메일 등으로 알림을 받을 수 있도록 통합합니다.
스테이징/운영 환경 분리: 개발, 스테이징, 운영 등 여러 환경에 대한 배포 파이프라인을 분리하여 관리합니다.
고급 배포 전략: 블루/그린 배포, 카나리 배포와 같은 무중단 배포 전략을 도입하여 서비스 안정성을 극대화합니다.
코드 품질 도구 통합: SonarQube와 같은 코드 품질 분석 도구를 CI 파이프라인에 통합하여 코드 품질을 지속적으로 관리합니다.
핵심 포인트
CI/CD는 단순히 배포를 자동화하는 것을 넘어, 개발팀의 생산성, 소프트웨어 품질, 그리고 시장 대응 속도를 혁신적으로 개선하는 데 기여합니다. 지속적인 개선과 고도화를 통해 더욱 강력한 개발 프로세스를 구축할 수 있습니다.
자주 묻는 질문 (FAQ)
Q. GitHub Actions는 Spring Boot 프로젝트에만 사용할 수 있나요?
아닙니다. GitHub Actions는 다양한 프로그래밍 언어와 프레임워크를 지원합니다. Python, Node.js, .NET 등 어떤 프로젝트라도 GitHub 저장소에 있다면 CI/CD 파이프라인을 구축할 수 있습니다.
Q. GitHub Actions 무료 사용량은 충분한가요?
공개 저장소(Public repository)는 무료로 무제한 사용 가능하며, 비공개 저장소(Private repository)의 경우 계정 유형에 따라 매월 일정 시간(예: Free 계정은 2,000분)이 무료로 제공됩니다. 소규모 팀이나 개인 프로젝트에는 일반적으로 충분한 양입니다.
Q. Docker Hub 대신 다른 컨테이너 레지스트리를 사용할 수 있나요?
네, 물론입니다. GitHub Container Registry (GHCR), AWS ECR, Google Container Registry (GCR) 등 다양한 컨테이너 레지스트리를 사용할 수 있습니다. 해당 레지스트리의 인증 방식에 맞춰 워크플로우를 수정하면 됩니다.
Q. 배포 중 서비스 중단은 어떻게 최소화할 수 있나요?
무중단 배포를 위해서는 블루/그린 배포(Blue/Green Deployment)나 카나리 배포(Canary Deployment)와 같은 고급 전략을 사용해야 합니다. 이는 로드밸런서와 여러 대의 서버를 활용하여 새 버전을 점진적으로 적용하는 방식입니다.
Q. GitHub Actions에서 SSH 접속 시 Host key verification failed 오류가 발생해요.
이 오류는 SSH 클라이언트가 서버의 호스트 키를 알지 못하거나, 키가 변경되었을 때 발생합니다. appleboy/ssh-action의 script 옵션에 StrictHostKeyChecking no