본문 바로가기
자바/스프링부트

Github Actions + AWS EC2 로 간단하게 스프링 부트 프로젝트 CI/CD 파이프라인 구축하기

by huffpuffkin 2025. 11. 25.

목차

    AWS EC2 구성

    프리티어 기준으로 구성했다. 

     

    • ami: ubuntu - Ubuntu Server 24.04LTS (HVM), SSD Volume Type
    • 인스턴스 유형: t2.micro
    • 키 페어: RSA(.pem) 사용
    • 스토리지: 30GiB gp3

    이 정도로 가볍게 구성하고 나머지는 선택되어 있는 그대로 진행했다.

     

     

     

     

     

     

     

     

     

    Github Actions

    구축하고자 하는 프로젝트의 레포지토리에서 Actions를 눌러 구성한다. 스프링부트 프로젝트이기 때문에 Java with Gradle로 선택한다. 

     

     

    Configure을 선택하고 나면 다음과 같이 기본코드가 생성된다.

     

    나는 CI, CD를 한번에 처리할 것이기 때문에 yml 이름을 cicd.yml로 변경하고 진행했다. 

     

     

    기본 코드를 커밋하면 프로젝트 루트 경로에 다음과 같은 패키지가 생성된다. 

     

    들어가보면 작성한 yml파일이 들어있다. 

     

     

     

    이제 yml파일을 프로젝트에 맞게 수정해주기만 하면 구축이된다. 

     

     

     

     

     

     

     

     

     

     

    yml 파일 구성

    빌드하고 정상적으로 빌드된 파일을 ec2에 전송해, 백그라운드에서 실행시키는 코드이다. 정상적으로 구동되고 있는지 ec2 내에서 확인하기 위해서는 다음과 같은 명령어를 사용하면 된다. 

    tail -f output.log

     

     

    # 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: CI/CD
    
    on:
      push:
        branches: [ "main" ]
      pull_request:
        branches: [ "main" ]
    
    jobs:
      # ci
      build:
    
        runs-on: ubuntu-latest
        permissions:
          contents: read
    
        steps:
        # repository checkout
        - uses: actions/checkout@v4
        # jdk 환경 설치
        - name: Set up JDK 17
          uses: actions/setup-java@v4
          with:
            java-version: '17'
            distribution: 'temurin'
        # gradle 환경 설치
        - name: Setup Gradle
          uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
    
        # 권한 부여
        - name: Grant execute permission for Gradle wrapper
          run: chmod +x ./gradlew
    
        # 빌드 
        - name: Build (skip tests) 
          run: ./gradlew clean bootJar -x test --stacktrace
          env: 
            AWS_DB_URL: ${{secrets.AWS_DB_URL}}
            AWS_DB_USER: ${{secrets.AWS_DB_USER}}
            AWS_DB_PASSWORD: ${{secrets.AWS_DB_PASSWORD}}  
            SECURITY_JWT_SECRET: ${{secrets.SECURITY_JWT_SECRET}}
            SECURITY_JWT_AT_EXPIRE: ${{secrets.SECURITY_JWT_AT_EXPIRE}}
            AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
            AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
        # 빌드된 파일 이름 변경
        - name: 빌드된 파일 이름 변경
          run: mv ./build/libs/*SNAPSHOT.jar ./agree.jar
        # 빌드된 파일 ec2 전송
        - name: ec2 전송
          uses: appleboy/scp-action@master
          with: 
            host: ${{secrets.SERVER_IP}}
            username: ${{secrets.SSH_USER}}
            key: ${{secrets.SSH_PRIVATE_KEY}}
            source: agree.jar
            target: /home/ubuntu
      # cd
      deploy: 
        needs: build
        runs-on: ubuntu-latest
    
        steps:
        - name: ssh로 ec2 접속
          uses: appleboy/ssh-action@master
          with: 
            host: ${{secrets.SERVER_IP}}
            username: ${{secrets.SSH_USER}}
            key: ${{secrets.SSH_PRIVATE_KEY}}
            script_stop: true
            script: |
              export AWS_DB_URL='${{secrets.AWS_DB_URL}}'
              export AWS_DB_USER='${{secrets.AWS_DB_USER}}'
              export AWS_DB_PASSWORD='${{secrets.AWS_DB_PASSWORD}}'
              export SECURITY_JWT_SECRET='${{secrets.SECURITY_JWT_SECRET}}'
              export SECURITY_JWT_AT_EXPIRE='${{secrets.SECURITY_JWT_AT_EXPIRE}}'
              export AWS_ACCESS_KEY_ID='${{secrets.AWS_ACCESS_KEY_ID}}'
              export AWS_SECRET_ACCESS_KEY='${{secrets.AWS_SECRET_ACCESS_KEY}}'
            
              fuser -k -n tcp 8080 || true
              nohup java -jar agree.jar > output.log 2>&1 &

     

     

    나는 아래 블로그를 많이 참고했다. 

    https://wildeveloperetrain.tistory.com/401

     

    Spring Boot 프로젝트 GitHub Actions CI/CD 구축하기

    GitHub Actions CI/CD 구축하기(Spring Boot 프로젝트) CI/CD는 단순히 번거로운 배포 과정을 자동으로 만들 뿐만 아니라, 수동으로 배포했을 때 발생할 수 있는 사용자의 실수를 줄일 수 있고, 자동화된

    wildeveloperetrain.tistory.com

     

     

    그중 다르게 구성한 것은 배포 시 환경 변수를 주입하는 부분이다. 

     

     

     

     

     

     

     

     

     

     

    환경 변수 세팅

    이전에 cicd를 진행할 때 가장 애먹었던 부분이 환경 변수 세팅이다. 이번에는 간단하게 진행하기 위해서 github에서 제공하는 기능을 적극적으로 활용하기로 했다. 

     

    Settings> Secrets and variables 메뉴에 접속한다. 

     

     

    그중 Actions 탭에 들어가면 Repository Secrets 메뉴가 보일텐데, 그곳에 yml에 작성한 환경변수들을 모두 추가해주면 된다. 

     

     

    나는 다음과 같이 설정해주었다. 

    • AWS_ACCESS_KEY_ID: AWS 공개 키
    • AWS_SECRET_ACCESS_KEY: AWS 비밀 키 
    • AWS_DB_PASSWORD: RDS에 구축한 DB 비밀번호
    • AWS_DB_URL: RDS에 구축한 DB URL
    • AWS_DB_USER: RDS에 구축한 DB 유저 이름
    • SECURITY_JWT_SECRET: JWT 시크릿 키
    • SECURITY_JWT_AT_EXPIRE: JWT 유효기간
    • SERVER_IP: EC2 퍼블릭 IPv4 주소
    • SSH_PRIVATE_KEY: pem키 (-----BEGIN RSA PRIVATE KEY----- 부터 -----END RSA PRIVATE KEY-----까지)
    • SSH_USER: ubuntu (ec2 생성 시 선택한 이미지에 따라 다름)

     

     

     

     

     

     

     

     

     

     

    정상 작동 테스트

    만약 정상적으로 구축이 되었다면, main 브랜치에 푸시될 때마다 다음과 같은 Action이 실행되고 모두 정상적으로 완료가 되면 다음과 같이 표시된다. 

     

     

    만약 빌드, 배포 과정 중 오류가 발생하면 다음과 같이 표시된다.