0biglife.

Github Actions로 사내 프로젝트 CI/CD 구축하기(1)

Productivity/CI/CD

· 2025-03-14

Github Actions로 사내 프로젝트 CI/CD 구축하기(1)

들어가며

빌드와 배포까지 수행하는 개발자라면 코드 구현하는 렌더링 작업과는 달리 빌드하는 시간이 길수록 답답하다고 느끼거나 속도 개선에 대한 욕구가 조금은 있었을테다. 빌드 자동화를 구현하는 것은 매번 미뤄지는 일이며, 실제로 조금의 시간만 들여보면 시간 대비 굉장히 가성비 있는 일임을 알 수 있다. 따라서, 이번 작은 사내 프론트엔드 프로젝트를 매번 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 DocGithub Actions Doc

git push할 때마다의 동작을 통해 테스트해주고, Job에 원하는 동작을 echo부터 시작해서 테스트해보자. 그 다음, Docker Auth나 필요한 Secret Key들은 Repository의 Setting으로 들어가보자. New repository secret을 통해 원하는 값을 넣어주면 끝이다. (여기서, 내가 업로드한 값은 다른 Admin 권한의 사용자라도 보지못한다는 점을 기억하자.)

SettingSetting

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.CI/CD Done.

값을 넣고 Run workflow 돌리면 끝 ! 이 전에 빌드한 히스토리와 얼마나 걸렸는지를 포함한 상세도 모두 조회 가능하다. (마음 편-안-) 물론, 빌드하다 실패할 경우도 실시간 모니터링 가능하다.

CI/CD HistoryCI/CD History

그치만, 놀라운 사실은 우리는 여태 CI만 한거지 CD는 하지 않았다. CI/CD가 붙어있지만 사실 이미지 빌드만 했다고 해서 끝나는 일은 아니다. 다음 게시글에서는 편하게 빌드된 이미지를 현재 EKS에 배포까지 자동화해보는 것을 yaml에 반영해본다.

끝 !

Index

들어가며Github ActionsWorkflowEventJobStepCI/CD 수동 실행Final Yaml