➕ CI / CD 파이프라인 구축

김민지·2025년 4월 4일

서버 기초 강의

목록 보기
12/12

EC2(Amazon Linux)에서의 Java 버전 변경

  • CI/CD 파이프라인 구축 이전에, 현재 로컬에서 완성한 코드는 SpringBoot 3.xx 버전으로, 자바 17버전을 기준으로 실행되고 있으므로 최신 코드를 pull 받아오는 것에 앞서서 자바 버전 수정을 선행해줘야 함.


  • 아래의 명령어들을 차례로 수행하면 위의 스크린샷과 같은 결과가 나옴.
sudo yum install java-17-amazon-corretto -y
sudo alternatives --config java
java --version

CI / CD 파이프라인 관련 설명

왜 EC2에서 build를 하지 않고, GitHub Actions 같은 CI 서버에서 build를 하는걸까?

  1. EC2는 배포용 서버이지 빌드용 서버가 아님: EC2는 실제로 서비스가 실행되는 운영 환경이며, 운영 서버에서는 빌드 작업처럼 무거운 연산을 피하는 것이 안정성에 유리함.
    또한, 빌드 과정에서 리소스를 많이 쓰면 사용자 요청 처리에 지장이 갈 수도 있음

  2. CI 서버에서 빌드하면 결과물이 검증된 상태라는 장점이 있다. 즉, 빌드가 성공한 경우에만 EC2로 전송하므로 안정성이 높다.
    반대로, EC2에서 빌드 시 오류가 발생하면 서버가 중단 상태가 되어버릴 수 있음

  3. 버전 관리 + 오류 추적 가능: CI에서 빌드하고 배포하면: 누가 작성한 어떤 커밋 기준으로 빌드되었는지 등의 정보가 GitHub Actions 로그에 자동으로 남아서 이후 어떤 커밋의 코드가 오류의 원인인지도 명확히 확인할 수 있음

  4. 보안 측면에서도 EC2에는 최소한의 코드만 올리고 실행만 시키는 것이 소스코드 전체를 EC2에 복사하고 빌드하는 것보다 나음

  5. Free Tier EC2는 용량이 작은 것에 반해, CI 서버(GitHub Actions)는 무료로 빠른 VM에서 빌드해줌. 즉, EC2가 무거운 빌드 안 해도 되니까 성능의 부담이 없음

CI / CD 구축

  1. 사진과 같이 Github Actions에 들어가서 미리 만들어진 workflow들을 가져올 수 있다. 우리는 우측 상단의 Java with Gradle을 사용해보자.
  • 모든 수정사항을 추적하는 것이 아닌, 'minji03/library-app/**' 위치의 수정사항만 추적해야 하므로 아래와 같이 수정해주기
on:
  push:
    branches: [ "main" ]
    paths: 
      - 'minji03/library-app/**'
  pull_request:
    branches: [ "main" ]
  • 또한, build의 대상도 전체 레포지토리가 아니라 minji03 폴더의 library-app이므로 아래와 같이 수정해주기
    - name: Build with Gradle Wrapper
      run: 
        cd minji03/library-app
        ./gradlew build
  • 추가 수정사항을 반영한 전체 스크립트
# 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.
# This workflow will build a Java project with Gradle 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-gradle

name: Java CI with Gradle

on:
  push:
    branches: [ "main" ]
    paths: 
      - 'minji03/library-app/**'
  pull_request:
    branches: [ "main" ]

jobs:
  build:

    runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
    - uses: actions/checkout@v4
    - name: Set up JDK 17
      uses: actions/setup-java@v4
      with:
        java-version: '17'
        distribution: 'temurin'

    # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
    # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
    - name: Setup Gradle
      uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0

    - name: Build with Gradle Wrapper
      working-directory: minji03/library-app
      run: ./gradlew build

    # NOTE: The Gradle Wrapper is the default and recommended way to run Gradle (https://docs.gradle.org/current/userguide/gradle_wrapper.html).
    # If your project does not have the Gradle Wrapper configured, you can use the following configuration to run Gradle with a specified version.
    #
    # - name: Setup Gradle
    #   uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
    #   with:
    #     gradle-version: '8.9'
    #
    # - name: Build with Gradle 8.9
    #   run: gradle build
    # ~ 여기까지는 기존 템플릿 내용이고, 아래부터는 새로이 추가된 내용
    - name: Ensure EC2 directory exists
      uses: appleboy/ssh-action@v0.1.10
      with:
        host: ${{ secrets.EC2_HOST }}
        username: ec2-user
        key: ${{ secrets.EC2_KEY }}
        script: mkdir -p /home/ec2-user/minji03/library-app/build/libs

    - name: Copy JAR to EC2
      uses: appleboy/scp-action@v0.1.3
      with:
        host: ${{ secrets.EC2_HOST }}
        username: ec2-user
        key: ${{ secrets.EC2_KEY }}
        source: "minji03/library-app/build/libs/*.jar"
        target: "/home/ec2-user/minji03/library-app/build/libs/"

    - name: Deploy on EC2
      uses: appleboy/ssh-action@v0.1.10
      with:
        host: ${{ secrets.EC2_HOST }}
        username: ec2-user
        key: ${{ secrets.EC2_KEY }}
        script: |
          echo ">>> Starting to deploy on EC2..."
          cd /home/ec2-user/minji03/library-app
          ./deploy.sh
          echo ">>> Deployment Successfully Completed"
    
    # Additional changes in order to copy built JAR file to EC2 and deploy it on EC2 (여기까지가 추가된 내용)

  dependency-submission:

    runs-on: ubuntu-latest
    permissions:
      contents: write

    steps:
    - uses: actions/checkout@v4
    - name: Set up JDK 17
      uses: actions/setup-java@v4
      with:
        java-version: '17'
        distribution: 'temurin'

    # Generates and submits a dependency graph, enabling Dependabot Alerts for all project dependencies.
    # See: https://github.com/gradle/actions/blob/main/dependency-submission/README.md
    - name: Generate and submit dependency graph
      uses: gradle/actions/dependency-submission@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
  1. GitHub Secrets 등록: 이제 위의 스크립트에서 변수 부분처럼 남겨둔 부분들을 추가해보자.
    GitHub 레포지토리SettingsSecrets and variablesActions로 접근해서 아래 두개의 변수를 Repository secrets로 등록하기.
  • EC2_HOST : EC2 퍼블릭 IP 주소
  • EC2_KEY : 앞서 프로젝트 root에 복붙해두었던 .pem 파일을 열어서 내용을 통째로 복붙 (맨 앞/뒤 공백, 줄바꿈 포함!)
  1. EC2에 deploy.sh 파일 만들기
    minji03/library-app 위치로 이동한 후 vim deploy.sh 로 파일 생성, 아래 내용 붙여넣기
#!/bin/bash

APP_NAME=minji03-library-app
JAR_PATH=$(ls /home/ec2-user/minji03/library-app/build/libs/*.jar | tail -n 1)

# 기존 프로세스 종료
PID=$(pgrep -f $JAR_PATH)
if [ -n "$PID" ]; then
  echo ">> Kill process: $PID"
  kill -15 $PID
  sleep 5
fi

# 새로 실행
echo ">> Run $APP_NAME"
nohup java -jar $JAR_PATH > nohup.out 2>&1 &
  • 실행 권한 부여: chmod +x deploy.sh
  1. 코드 변경 후 Push → 자동 배포 테스트
    minji03/library-app 내부에서 아무 파일이나 수정하고 커밋 → main 브랜치에 푸시!
git add .
git commit -m "CI/CD test: 배포 트리거 테스트"
git push origin main

Actions 탭Workflow 실행 확인

  1. EC2에서 실행 상태 확인
ps -ef | grep java           # 실행 중인 프로세스 확인
tail -f /home/ec2-user/minji03/library-app/nohup.out   # 로그 실시간 확인

0개의 댓글