git

git Action으로 Spring boot CI/CD 환경 구축 - gradle.yml 작성

해니01_15 2025. 5. 16. 12:37

 

[git Action 이름 설정 ]

name: Java CI/CD with Gradle and Docker //Action의 이름

 

 

[워크플로우 트리거 설정] 

backdev 브랜치에 푸시 할 때마다 발생 하게 할 것이라는 의미 

on:
  push:
    branches: ["backdev"]

아래는 다른 트리거들을 정리해 본 것으로 프로젝트 상황에 맞는 트리거로 적용 하면 된다. 

더보기

- push 

on:
  push:
    branches: ["main", "backdev"] //두개라면 쉼표로 이어서 작성.

 

- pull_request 

PR이 생성되거나 업데이트 될 때 실행 된다. 

on:
  pull_request:
    branches: ["main"]

 

- workflow_dispatch 

수동 실행용 트리거로 GitHub에서 직접 버튼을 눌러 실행 할 수 있다. 

on:
  workflow_dispatch:

혹은 아래처럼 입력값을 받아 작동 하게 할 수 도 있다. 

on:
  workflow_dispatch:
    inputs: //입력 할 값들 
      environment: //입력 필드의 이름 키 
        description: '배포 환경' //UI에 표시될 설명 
        required: true //반드시 입력해야 하느냐 아니냐 유무 
        default: 'production' // 디폴트값

 

- schedule 

정해진 시간마다 자동으로 실행하는 크론 기반 스케줄이다.

on:
  schedule:
    - cron: "0 1 * * *"

 

- 여러 트리거 조합

on:
  push:
    branches: ["main"]
  pull_request:
    branches: ["main"]
  workflow_dispatch:

 

[Job 정의]

어떤 일을 수행 할 것이라는 빌드 정의를 해주는 곳으로  spring-build 는 ubuntu 최신 환경에서 실행 하게 된다.  

jobs:
  spring-build:
    runs-on: ubuntu-latest

 

[코드 체크아웃]

repo 에 있는 파일들을 불러오고 커밋을 가져오는 역할 을 한다. 이건 github marketplace 에서 제공 되고 있다. 

      - name: 레파지토리 체크아웃 
        uses: actions/checkout@v4 #uses는 외부에서 제공되는 Action을 사용하도록 하는 지시어

 

[JDK 설정]

Temurin (OpenJDK의 배포판) 으로 설치해 Gradle 빌드를 위한 환경을 준비한다. 

      - name: JDK 17 세팅 
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

 

[Gradle 세팅]

gradle 세팅에 들어간다. Gradle 캐시 및 설정을 Github Action이 관리 하도록 외부 소스를 사용했다. 

      - name: Gradle 세팅 
        uses: gradle/actions/setup-gradle@v4

 

[application.properties 생성]

application.properties의 내용을 인코딩 하여 비밀키로 프로퍼티를 등록 해 놓았다. 

따라서 그걸 다시 디코딩 해서 실행 하겠다는 의미로 구성 했다. 

      - name: application.properties 생성 
     #uese 가 외부(마켓플레이스)의 것이라면 run은 직접 짠 코드로 실행 하는 것
        run: | 
          mkdir -p src/main/resources
          echo "${{ secrets.APPLICATION_PROPERTIES }}" | base64 --decode > src/main/resources/application.properties

 

[Gradle 빌드]

Gradle Wrapper 에 실행 권한을 부여 한 후 테스트를 건너 뛰고 프로젝트를 빌드한다. 

테스트를 건너 뛴 이유는 서버 세팅할때 이상하게 테스트만 하면 오류가 났기 때문에 일단 건너뛰었지만 

그래도 테스트를 넣어서 하는게 안정성 측면에서 좋다. 

      - name: gradlew 빌드 
        run: |
          cd ReadingLogBackend
          chmod +x gradlew
          ./gradlew build -x test

 

[DokerHub 로그인]

이제 DockerHub에 로그인을 해준다. 아이디와 비밀번호(토큰)은 시크릿에 저장 해 두었다. 

      - name: 도커허브 로그인 
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_ID }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

 

[Docker 이미지 빌드 및 푸시]

빌드 된 애플리케이션으로 Dokcer 이미지를 생성하고, Docker Hub에 푸시한다. 이렇게 저장 된 이미지를 GCP 서버에서 가져다가 실행 하게 된다. 

      - name: 도커이미지 빌드 
        run: |
          cd ReadingLogBackend
          docker build -t ${{ secrets.DOCKERHUB_ID }}/readinglog-app:latest .

      - name: 도커이미지 도커에 푸시
        run: |
          docker push ${{ secrets.DOCKERHUB_ID }}/readinglog-app:latest

 

[배포 job 설정]

도커 이미지까지 설정 되었다면, 이제 이걸 서버에 올리는 배포 작업을 거쳐야 한다. 

ubuntu최신 버전으로 실행하고 spring-build 가 있어야 실행 되는 작업으로 설정 해 주었다. 

  deploy:
    runs-on: ubuntu-latest
    needs: spring-build

 

[배포 전 체크아웃]

Spring-build 와 같이 배포 전 레포를 체크아웃 해준다. 

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

 

[환경변수 파일 생성 및 복사]

필요한 환경 변수 파일을 생성해 준다. 백단에서 코드를 짤 때 쓰일 API 키 값들을 넣는다. 

그렇게 만들어진 .env 파일을 GCP instance로 복사 해 준다. 복사하는 것 역시 외부소스를 사용하여 간편하게 진행 했다. 

GCP의 host와 이름, 개인키까지 넣어주고 port 설정과 env 파일을 넣어 줄 경로도 맞춰 주었다. 

      - name: .env 파일생성
        run: |
          echo "NAVER_CLIENT_ID=${{ secrets.NAVER_CLIENT_ID }}" >> .env
          echo "NAVER_CLIENT_SECRET=${{ secrets.NAVER_CLIENT_SECRET }}" >> .env
          echo "NAVER_REDIRECT_URI=${{ secrets.NAVER_REDIRECT_URI }}" >> .env
          echo "KAKAO_API_KEY=${{ secrets.KAKAO_API_KEY }}" >> .env
          echo "KAKAO_REDIRECT_URI=${{ secrets.KAKAO_REDIRECT_URI }}" >> .env
          echo "VITE_ALADIN_API=${{ secrets.VITE_ALADIN_API }}" >> .env
          
      - name: Copy .env to GCP instance
        uses: appleboy/scp-action@v0.1.7
        with:
          host: ${{ secrets.GCP_HOST }}
          username: ${{ secrets.GCP_USERNAME }}
          key: ${{ secrets.GCP_PRIVATEKEY }}
          port: 22
          source: ".env"
          target: "/home/readingLog"
          overwrite: true
          debug: true

 

[docker-compose.yml 복사]

나는 Spring, DB를 하나로 묶어 관리하기 때문에 docker-compose.yml 파일 역시 GCP로 복사 해 주었다. 

      - name: Copy docker-compose.yml to GCP instance
        uses: appleboy/scp-action@v0.1.7
        with:
          host: ${{ secrets.GCP_HOST }}
          username: ${{ secrets.GCP_USERNAME }}
          key: ${{ secrets.GCP_PRIVATEKEY }}
          port: 22
          source: "ReadingLogBackend/docker-compose.yml"
          target: "/home/readingLog"
          overwrite: true
          #파일이나 디렉터리를 복사할 때 디렉터리 계층을 몇 단계 "잘라낼지"를 지정하는 옵션
          strip_components: 1 
          debug: true

 

 

[GCP 배포]

드디어 마지막 단계 최종 적으로 도커를 실행하여 서버배포를 마무리 하는 일이다. 

이것도 마켓플레이스 오픈소스가 잘 되어있으니 그냥 이렇게 작성하면 끝! 

      - name: GCP에 배포
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.GCP_HOST }}
          username: ${{ secrets.GCP_USERNAME }}
          key: ${{ secrets.GCP_PRIVATEKEY }}
          port: 22
          script: |
            sudo docker login -u ${{ secrets.DOCKERHUB_ID }} -p ${{ secrets.DOCKERHUB_TOKEN }}
            sudo docker pull ${{ secrets.DOCKERHUB_ID }}/readinglog-app:latest
            cd /home/readingLog
            sudo docker-compose down || true
            sudo docker-compose up -d --remove-orphans
            sudo docker image prune -f

 

 

최종적으로 성공 하였지만 이 과정에서 총 17번의  fail을 겪었다. 일단 gradle.yml파일의 작성은 쉬운데 역시나 환경 설정이 문제 였던 것이다. 이미 GCP 서버에 배포를 해보고 실행 해 봤음에도 불구하고 오류가 나서 쵸큼 성질이 났지만, 이 오류를 해결하는 데 어떤 방법을 썼는지 정리 해 봐야겠다. 아무튼 깃 액션으로 스프링 -> GCP CI/CD 설정에 성공 하였다.