Github Actions로 사내 프로젝트 CI/CD 구축하기(1)
Productivity/CI/CD
· 2025-03-14

들어가며
빌드와 배포까지 수행하는 개발자라면 코드 구현하는 렌더링 작업과는 달리 빌드하는 시간이 길수록 답답하다고 느끼거나 속도 개선에 대한 욕구가 조금은 있었을테다. 빌드 자동화를 구현하는 것은 매번 미뤄지는 일이며, 실제로 조금의 시간만 들여보면 시간 대비 굉장히 가성비 있는 일임을 알 수 있다. 따라서, 이번 작은 사내 프론트엔드 프로젝트를 매번 VSCode Terminal 하나를 열어 빌드하는 일을 편리하게 만드는 데 목적이 있다.
Github Actions
Github Actions는 Github에서 제공하는 CI/CD 플랫폼이다. CI/CD(Continuous Integration/Continuous Deployment)는 지속적 통합과 지속적 배포를 의미하며, 개발자가 작성하는 코드 작업 외에 빌드와 배포와 같은 워크플로우를 자동화할 수 있게 도와주는 강력한 툴!이다.
Workflow
워크플로우는 Github Actions를 구축하기 위한 일종의 프로세스다. Github Actions의 자동화된 프로세스를 정의하는 YAML
파일로 구성되며, 이 파일은 프로젝트의 .github/workflows/
디렉토리에 위치하여 해당 프로젝트에 대한 특정 프로세스를 실행시킨다.
.github/workflows
디렉토리는 Github가 자동으로 인식하는 것을 시작으로 구현된다. 이 디렉토리 내부의.yml
또는.yaml
파일을 워크플로우 설정으로 인식하여 여러 워크플로우 파일을 동작시킬 수 있다.
1{root}/ 2├── .github/ # <-- 동일하게 생성 3│ └── workflows/ 4│ ├── ci.yml 5│ └── deploy.yml 6├── .husky/ 7├── .next/ 8├── .storybook/ 9├── src/ 10├── ... 11└── README.md
Event
워크플로우를 트리거하는 특정 규칙이다. push, pull_request, schedule ... 등이 있다. 이 중에서 필자는 Github 사이트에서 버튼을 동작시켜 원할 때마다 수동으로 이미지 빌드를 해주는 방식을 구현할 것이다. 즉, workflow_dispatch
를 쓰는 것.
push
: 코드 푸시 시 실행pull_request
: PR 생성/수정 시 실행workflow_dispatch
: 수동 실행schedule
: 정해진 시간에 실행
Job
워크플로우 안에서 실행되는 단위 작업이며, 각 잡은 여러 스탭(Step)으로 구성되어 병렬로 처리된다. (순서가 필요할 경우 needs
로 설정 가능하다.) 아래 예시에서는 우분투 환경에서 "Hello World" 출력을 실행한다.
1jobs: 2 build: # 작업 ID 3 runs-on: ubuntu-latest # 실행 환경# 또는 4 # runs-on: windows-latest 5 # runs-on: macos-latest 6 # runs-on: self-hosted 7 8 steps: # 실행할 단계들 9 - name: Step 1 10 run: echo "Hello World" # 예시 11--- 12# needs 활용 예시 13jobs: 14 test: 15 runs-on: ubuntu-latest 16 steps: 17 - run: npm test 18 19 deploy: 20 needs: [test] # test job이 성공해야 실행 21 runs-on: ubuntu-latest 22 steps: 23 - run: deploy-test 24 25--- 26# 조건부 실행 27jobs: 28 build: 29 if: github.event_name == 'push' 30 runs-on: ubuntu-latest 31 steps: 32 - run: npm build
Step
작업 내에서 순차적으로 실행되는 개별 테스크 작업이다. npm install
과 같은 명령어 또는 액션을 포함한다.
1steps: 2 - name: Install dependencies 3 run: npm install # npm install command 실행 4 5 - name: Run tests 6 run: npm test
CI/CD 수동 실행
기존의 이미지 빌드 방식은 azure cli
를 통해 매번 Azure Container Registry에 이미지명과 태그명을 입력하여 넣어주었다. 이 방식을 Git Repository의 Actions Tab에서 버튼 한 번으로 해결하려고 한다. 동작도 편할 뿐더러 빌드한 히스토리와 에러 동작까지 지원해주니 참고하자.
먼저 workflow_dispatch
로 수동 실행시키고 필요한 필드들을 공식 문서를 참고하여 yaml
을 구성하였다.
Github Actions Doc
git push할 때마다의 동작을 통해 테스트해주고, Job에 원하는 동작을 echo
부터 시작해서 테스트해보자. 그 다음, Docker Auth나 필요한 Secret Key들은 Repository의 Setting으로 들어가보자. New repository secret
을 통해 원하는 값을 넣어주면 끝이다. (여기서, 내가 업로드한 값은 다른 Admin 권한의 사용자라도 보지못한다는 점을 기억하자.)
Setting
Final Yaml
최종 yaml이다. 동작은 아주 기본적인 빌드 과정과 필요한 시크릿 값들만 참조되도록 넣었다.
1name: Manually Build and Push Docker Image 2on: 3 workflow_dispatch: 4 inputs: 5 TARGET_NAME: 6 type: choice 7 description: "Container Registry Target Repo Name (e.g. front-stag, front-prod)" 8 required: true 9 options: 10 - front-stag 11 - front-prod 12 13 CUSTOM_TAG: 14 type: string 15 description: "Optional: Custom image tag (overrides secrets.VERSION if provided)" 16 required: true 17 18permissions: 19 contents: read 20 21env: 22 REGISTRY_PATH: ${{ secrets.REGISTRY_PATH }} 23 24jobs: 25 build-and-push: 26 runs-on: ubuntu-latest 27 steps: 28 # 현재 Repository 코드를 워크플로우의 실행 환경으로 체크아웃(다운로드) 29 # 아래와 같은 액션들은 Github 제공 공식 액션들 30 - name: Checkout 31 uses: actions/checkout@v4 # v4는 액션의 버전 지정 32 # with: 33 # 예시 파라미터 34 # token: ${{ secrets.GITHUB_TOKEN }} # 인증 토큰 35 # ref: feature/new-feature # 체크아웃할 브랜치/태그 36 # fetch-depth: 2 # 히스토리 깊이 37 # path: my-project # 저장소 경로 38 # submodules: recursive # 서브모듈 설정 39 40 # 지정된 버전의 Node.js 설치 및 설정 41 - name: Setup Node.js 42 uses: actions/setup-node@v3 43 with: # 액션에 전달할 파라미터 정의(각 액션마다 필요 필드 다름, 문서 확인) 44 node-version: 45 "20.18" # Node.js 버전 지정하는 파라미터 46 # '20.19' # 정확한 버전 47 # '20.x' # 메이저 버전의 최신 48 # '>=20.0.0' # 버전 범위 49 # '20' # 메이저 버전 50 # 예시 파라미터 51 # node-version: [14.x, 16.x, 18.x, 20.x] 52 # check-latest: true # Node.js 체크 53 # architecture: 'x64' # 아키텍처 지정 54 55 # cache: 'npm' # 패키지 매니저 캐시 56 # cache-dependency-path: subdir/package-lock.json 57 58 - name: Install pnpm 59 uses: pnpm/action-setup@v2 60 with: 61 version: latest 62 63 - name: Install dependencies 64 run: pnpm install 65 66 - name: Build project 67 run: | 68 pnpm build all 69 pnpm web:build 70 71 - name: Set up QEMU 72 uses: docker/setup-qemu-action@v3 73 74 - name: Set up Docker Buildx 75 uses: docker/setup-buildx-action@v3 76 77 - name: Determine final tag 78 id: parse-tag 79 run: | 80 echo "final_tag=${{ inputs.CUSTOM_TAG }}" >> $GITHUB_OUTPUT 81 82 - name: Docker Login 83 uses: docker/login-action@v3 84 with: 85 registry: ${{ secrets.DOCKER_REGISTRY }} 86 username: ${{ secrets.DOCKER_USERNAME }} 87 password: ${{ secrets.DOCKER_PASSWORD }} 88 89 # 해당 베이스 폴더로 이동 -> Dockerfile로 이미지 빌드 -> 빌드 이미지를 레지스트리에 푸시 90 - name: Build and Push Docker Image 91 run: | 92 docker buildx build --push --platform=linux/amd64 -f Dockerfile -t ${{ env.REGISTRY_PATH }}/${{ github.event.inputs.TARGET_NAME }}:${{ steps.parse-tag.outputs.final_tag }} . 93 94 # GITHUB_STEP_SUMMARY : Github Actions의 특별한 환경 파일 (워크플로우 실행 결과의 요약을 생성하는 역할) 95 # 즉, 워크플로우 실행 후 Github UI에서 확인 가능 요약 정보 생성 96 - name: Generate Docker Build Summary 97 if: always() 98 run: | 99 echo "### Docker Build Summary" >> $GITHUB_STEP_SUMMARY 100 echo "- **Target Name:** ${{ github.event.inputs.TARGET_NAME }}" >> $GITHUB_STEP_SUMMARY 101 echo "- **Image Tag:** ${{ steps.parse-tag.outputs.final_tag }}" >> $GITHUB_STEP_SUMMARY 102 echo "- **Full Image Name:** ${{ env.REGISTRY_PATH }}/${{ github.event.inputs.TARGET_NAME }}:${{ steps.parse-tag.outputs.final_tag }}" >> $GITHUB_STEP_SUMMARY
CI/CD Done.
값을 넣고 Run workflow
돌리면 끝 ! 이 전에 빌드한 히스토리와 얼마나 걸렸는지를 포함한 상세도 모두 조회 가능하다. (마음 편-안-) 물론, 빌드하다 실패할 경우도 실시간 모니터링 가능하다.
CI/CD History
그치만, 놀라운 사실은 우리는 여태 CI만 한거지 CD는 하지 않았다. CI/CD가 붙어있지만 사실 이미지 빌드만 했다고 해서 끝나는 일은 아니다. 다음 게시글에서는 편하게 빌드된 이미지를 현재 EKS에 배포까지 자동화해보는 것을 yaml
에 반영해본다.
끝 !