CI/CD를 구축하기 위한 툴 중 하나로 GitHub Actions가 있습니다. 이 툴은 무료로 사용할 수 있으며, 별도의 빌드 서버를 구축할 필요가 없다는 장점 때문에 현업에서 널리 사용됩니다. 또한, GitHub 레포지토리와의 통합이 원활해 설정과 관리가 간편합니다.
이 외에도 많이 사용되는 CI/CD 툴로는 Jenkins(젠킨스)가 있으며, Jenkins는 오픈소스 툴로서 다양한 플러그인을 통해 유연하게 CI/CD 파이프라인을 구성할 수 있습니다.
CI/CD 흐름에서 GitHub Actions는 빌드, 테스트, 배포에 대한 로직을 실행할 수 있는 일종의 컴퓨터라고 생각하면 됩니다.
CI/CD의 구성 방식은 다양하지만, 일반적으로 아래와 같은 흐름을 따릅니다.

특정 기능을 개발 완료한 후, 코드를 커밋하면 빌드가 자동으로 진행됩니다. 빌드가 완료된 후에는 테스트 코드가 실행되며, 모든 테스트가 통과되면 최신 코드가 실제 서버에 배포됩니다. 이와 같은 CI/CD 파이프라인은 코드 배포를 자동화하여 개발 효율성을 크게 높여줍니다.
실습을 위한 AWS EC2를 하나 생성합니다. EC2 구성 시 유형을 프리티어인 t2.micro가 아닌 t3a.small을 선택합니다. 이는 프리티어 유형으로 스프링부트 프로젝트 배포 시 메모리 부족으로 인한 멈춤 현상이 발생할 수 있기 때문입니다.


실습을 위한 스프링 프로젝트를 생성 후 깃허브에 올리고, 프로젝트 내부에서 GitHub Actions 워크플로 작성을 위한 디렉터리를 추가해 줍니다. 그리고 아래와 같이 워크플로 파일 내용을 작성합니다.

# 워크플로 이름
name: Deploy To EC2
# main 브랜치에 push 될 때 워크플로 실행
on:
push:
branches:
- main
jobs:
# Job의 고유 ID 값
Deploy:
# ubuntu-latest 환경에서 job 실행
runs-on: ubuntu-latest
# step: 특정 작업을 수행하는 가장 작은 단위
steps:
- name: SSH(원격 접속)로 EC2에 접속
# EC2에서 자동 배포를 위해 appleboy/ssh-actions@v1.0.3 라이브러리 사용
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
secrets.EC2_HOST 는 EC2의 주소를 의미합니다.secrets.EC2_USERNAME 은 EC2의 접속 username을 의미합니다.secrets.EC2_PRIVATE_KEY 는 EC2의 Key 파일의 내부 텍스트를 의미합니다. EC2 생성 시 발급한 키 페어 .pem 파일의 내부 내용을 가져와 추가하면 됩니다.script_stop: true
script: |
cd /home/ubuntu/test-server
git pull origin main
./gradlew clean build
sudo fuser -k -n tcp 8080 || true
nohup java -jar build/libs/*SNAPSHOT.jar > ./output.log 2>&1 &
script_stop: true 는 아래 스크립트 중 실패하는 명령이 하나라도 있으면 실패로 처리한다는 의미입니다.cd /home/ubuntu/test-server 는 본인이 생성한 EC2의 경로입니다.git pull origin main 명령어로 최신 수정 사항을 가져와 병합합니다../gradlew clean build 명령어로 프로젝트를 다시 빌드합니다.sudo fuser -k -n tcp 8080 || true 에서 || true 를 붙인 이유는 8080 포트에서 종료할 프로세스가 없더라고 실패로 처리하지 않기 위함입니다.nohup java -jar build/libs/*SNAPSHOT.jar > ./output.log 2>&1 & 명령어는 jar 파일을 실행하고, 발생하는 로그들을 ./output.log 파일에 기록하는 명령어입니다.아래와 같이 깃허브에서 워크플로에 사용할 secrets를 설정합니다.


이후 코드를 수정하여 깃허브에 push 후 워크플로가 잘 작동하는지 서버에 접속하여 확인해보면, 자동 배포가 잘 되고 있음을 확인할 수 있습니다.



아래와 같이 워크플로 내용을 수정합니다.
env: APPLICATION_PROPERTIES: ${{ secrets.APPLICATION_PROPERTIES }} 는 GitHub Secrets에 저장된 application.yml 내용을 환경 변수로 설정한다는 의미입니다.envs: APPLICATION_PROPERTIES 는 위에서 정의한 환경 변수를 전달한다는 의미입니다.rm -rf src/main/resources/application.yml 는 기존의 application.yml 파일을 삭제한다는 의미입니다.echo "$APPLICATION_PROPERTIES" > src/main/resources/application.yml 는 echo로 출력된 APPLICATION_PROPERTIES의 값을 src/main/resources/application.yml 파일에 저장한다는 의미입니다. 즉, 새로운 application.yml 파일을 생성하여 그 안에 APPLICATION_PROPERTIES 값을 삽입하게 됩니다.
APPLICATION PROPERTIES에 프로젝트의 appliction.yml 파일 내용을 가져와 추가합니다. 이 과정은 노출하면 안 되는 값인 application.yml 파일의 내용을 GitHub Secrets로 추가하는 것입니다.

프로젝트를 새로 push한 후에 깃허브 리포지토리에서 확인해보면 설정에 따라 application.yml 파일이 없는 것을 확인할 수 있습니다.

하지만 EC2 내부에서 확인해보면 워크플로 파일 설정에 따라 application.yml 파일이 생성되어 존재하는 것과 그 내용까지 확인할 수 있습니다.

application.yml 파일 내용을 수정했거나 추가한 경우에는 깃허브 Secrets에서 직접 수정한 내용으로 재작성해 주어야 합니다. 이 과정은 자동으로 처리되지 않으므로 수동으로 처리합니다.



프로젝트에서 일부러 테스트를 실패하도록 코드를 작성 후 이를 깃허브에 올리게 되면 배포가 정상적으로 진행되는지 확인합니다.

