들어가며
GitHub Actions는 GitHub에서 제공하는 내장형 CI(Continuous Integration, 연속 통합)/CD(Continuous Delivery, 지속적인 배포) 플랫폼이다. GitHub Actions는 2018년 8월[1]에 베타 버전이 출시된 이후로 많은 개발자들이 CI/CD 구성을 효율적으로 할 수 있게 하였고, 가장 중요한 코드에만 집중할 수 있도록 지원하고 있다. 본 리포트에서는 GitHub Actions에 대한 소개와 구성 요소에 대해 알아보고, GitHub 가이드 문서와 기존 Action을 활용하여 개발한 Custom Action에 대해 자세히 설명하고자 한다.
먼저 개발한 Custom Action 기능에 대해 간략히 말하자면, GitHub repository에 pull request 이벤트가 발생하면 ESLint를 기반으로 코드 품질을 점검하고 Google Gemini AI를 활용하여 코드 리뷰를 제공하는 기능을 제공한다. Custom Action의 소스 코드[2]를 보면서 Action의 요구 조건, 전체 동작 흐름, 사용 방법, 개발 과정, 시행착오에 대해 자세히 설명하고자 한다. 본 리포트를 통해 GitHub Actions를 처음 접하는 개발자뿐만 아니라 Custom Action을 직접 만들고 싶어하는 개발자에게 도움이 되기를 바란다.
GitHub Actions 소개
먼저 GitHub Actions는 개발자들이 기존 CI/CD 도구인 Jenkins, Travis CI와 같은 외부 도구를 구축하고 빌드, 테스트, 배포 파이프라인을 구성하고 연동하는 과정에서 발생하는 많은 불편한 점들을 해결하기 위해 나오게 되었다. GitHub Actions는 GitHub 환경 안에서 CI/CD 파이프라인을 간단하게 구축할 수 있을 뿐만 아니라 repository에 어떤 이벤트가 발생할 때 특정 작업을 실행하거나 주기적인 작업을 반복해서 실행할 수 있도록 한다. 따라서 GitHub Actions는 다음과 같은 상황에서 유용하게 사용할 수 있다.
- Repository 코드 변경 시 테스트, 빌드, 배포 등을 자동으로 수행할 때
- Repository 특정 브랜치의 모든 push 커밋에서 GitHub Actions Workflow로 새 컨테이너 이미지를 빌드하고 Amazon ECR(Elastic Container Registry)에 저장하고, Amazon ECS(Elastic Container Service)에 배포 자동화를 구성할 때
- 특정 시각 마다 일간 및 주간 통계 데이터를 수집해야 할 때
- Repository에 새 이슈를 만들 때마다 적절한 레이블을 자동으로 추가해야 할 때
GitHub Actions 구성 요소
GitHub Actions[3]에서 Workflow는 자동화된 프로세스이며, 아래 [그림1]에서 보듯 Event에 의해 예약되거나 트리거될 때 하나 이상의 Job이 순차적으로 또는 병렬적으로 실행 한다. 각 Job은 VM 또는 Docker와 같은 컨테이너, self-hosted Runner 안에서 실행되며, 개발자가 정의한 스크립트를 실행하거나 Action을 실행하는 하나 이상의 Step이 있다. Custom Action을 개발하기 앞서 Actions를 이루는 구성 요소 Workflow, Event, Job, Runner, Step에 대해 자세히 알아보고자 한다.
Workflow
Workflow는 자동화 프로세스를 정의한 YAML 파일이며, repository의 `.github/workflows` 디렉토리 아래에 위치한다. GitHub Actions는 YAML 파일에 정의된 Workflow를 보고 Job을 실행한다. 또한, GitHub에서 다양한 언어와 도구에 대한 Workflow template을 제공하고 있어서, 이를 참고하여 원하는 조건에 맞는 Workflow를 빠르게 만들 수 있다.
Event
Event는 Workflow를 언제 실행(트리거)할지를 결정한다. 예를 들어, 누군가가 특정 branch에 커밋을 push하거나 pull request 생성 및 변경한다면, Workflow가 시작된다. Repository의 특정 활동 뿐만 아니라 주기적으로 수행해야 하는 Job은 schedule에 따라 Workflow를 실행시킬 수 있다. Workflow를 트리거하는 이벤트에 대해 알고 싶다면 GitHub 문서[11]를 참고하면 된다.
Runner
Runner는 Workflow를 어디에서 실행할지를 결정한다. GitHub-hosted Runner와 Self-hosted Runner로 나눠지며, GitHub-hosted Runner 표준 스펙은 다음 [표 1]과 같이 다양한 운영체제를 제공하고 있다.[13] 또한, 같이 public repository에 대해 무료로 제공하고 있으며 private repository는 제한된 범위 내에서 제공하고 있다.
Job
Job은 동일한 Runner에서 실행되는 여러 Step의 조합이며, Workflow가 무엇을 실행할지를 결정한다. 각 Step은 단순한 명령(command)이나 사용자가 작성한 스크립트, 또는 Action이 올 수 있다. 같은 Runner에서 실행되므로 step 간에 데이터를 공유할 수 있다. 예를 들어 어플리케이션을 빌드하는 step 뒤에 빌드된 어플리케이션을 테스트하는 step이 올 수 있다. Job 사이에는 의존 관계를 가질 수도 있고, 독립적으로 Job을 병렬로 실행할 수 있다.
Action
Action은 자주 반복되는 작업을 수행하는 GitHub Actions 플랫폼용 사용자 지정 Step이다. Action을 사용하면 Workflow 파일에 작성하는 반복적인 코드 양을 줄일 수 있다. 이러한 Action은 GitHub Marketplace에서 가져와서 사용하거나 직접 개발자가 작성하여 사용할 수 있다.
Custom Action 만들어보기
GitHub 커뮤니티에 공유된 Action과 GitHub 가이드 문서[4]를 바탕으로 GitHub Custom Action[5]을 만드는 일은 그리 어렵지 않다. 본 리포트에서는 평소 작성자가 관심있었던 ESLint와 자동 리뷰 Action을 만들어보고자 한다. Action의 이름은 `eslint-gemini-action`이고, 오픈 소스로 공개하여 GitHub[2]에서 확인할 수 있다. `eslint-gemini-action`은 pull request(이하 PR)가 생성되거나 변경될 때 ESLint를 실행하여 코드 품질을 점검하고, 검출된 오류에 대해 Google Gemini AI[6]로부터 코드 개선 제안을 받아 해당 PR 코드 라인에 자동으로 인라인 코멘트를 추가하는 자동화 리뷰 도구이다. 이 도구는 코드 품질 향상과 리뷰를 효율적으로 하는데 도움을 준다. 아래 [그림 2]는 GitHub PR 화면에서 `eslint-gemini-action` 실행 결과 ESLint `prefer-const` 규칙을 위반한 오류를 보여주고 AI 제안 코드와 간략한 설명을 오류 발생 지점에 인라인 코멘트로 보여주고 있다.
`eslint-gemini-action` 은 프로토타입 도구이므로 테스트를 편하게 하기 위해서 하나의 GitHub repository 안에 테스트용 소스 코드와 Custom Action을 같이 작성하였다. 만약 Custom Action을 GitHub Marketplace에 배포하거나 여러 프로젝트에서 쉽게 재사용하기 위해서는 별도의 repository에서 Custom Action을 정의하고 버전을 명시해서 배포해야 사용할 수 있다.
전체 동작 흐름
- PR이 생성되거나 수정되면 `eslint-gemini-action`이 트리거 된다.
- PR에서 변경된 .js 또는 .ts 파일 목록을 GitHub API를 통해 조회한다.
- 변경된 파일에 대해 ESLint를 실행하여 코드 분석을 수행한다.
- ESLint 오류가 존재할 경우, 각 오류 메시지와 관련된 코드 스니펫을 Gemini API로 전송한다.
- Gemini API로부터 수정된 코드 및 설명을 JSON 형태로 응답을 받는다.
- 해당 오류가 발생한 코드 라인에 GitHub API를 통해 PR 인라인 코멘트를 생성한다.
- 분석 결과 오류가 없을 경우, GitHub CheckRun을 생성하여 GitHub PR 화면의 Checks 탭에 “이슈 없음” 상태를 표시한다.
디렉토리 구조 및 파일 설명
.github/workflows/ : Workflow를 정의한 파일이 포함된 디렉토리
action/ : GitHub Custom Action의 실행 로직이 포함된 핵심 디렉토리
시행착오 및 해결 과정
- ESLint 플러그인을 찾을 수 없음
- ESLint 실행 경로와 node_modules 설치 경로가 일치하지 않아 ESLint 플러그인을 찾지 못했다. Repository의 `action/` 디렉토리 내부에서 ESLint를 실행하고, node_modules 또한 해당 위치에 설치하도록 수정하였다.
- ESLint 설정 파일을 인식하지 못함
- .eslintrc.json 위치가 ESLint 실행 위치와 달라 문제가 발생하였다. ESLint 실행 커맨드에서 -c 옵션을 사용해 config 파일 경로를 명시하여 해결하였다.
- Gemini API 응답 파싱 실패
- 응답이 JSON이 아닌 마크다운 형태로 반환되면서 백틱(`)이 포함되어 파싱 실패하였다. 프롬프트 문구를 수정하여 JSON 포맷으로 반환될 수 있도록 수정하였다.
- GitHub API 403 에러
- GitHub 토큰 권한 부족 GitHub API 403 에러가 발생하였다. Workflow 파일에 permissions 섹션을 명시하여 수정하였다.
한계점 및 개선점
- ESLint 8.56.0 버전과 ESLint 플러그인이 고정되어 있어서, 프로젝트마다 다른 ESLint 버전과 설정을 유연하게 처리하지 못하고 수동 업데이트가 필요하다.
- PR에 커밋이 여러 번 푸시될 경우, 같은 ESLint 오류에 중복된 코멘트가 생성된다. 만약 동일한 메시지가 있다면 코멘트를 생성하지 않도록 개선한다.
- Gemini API 응답 형식이 종종 잘못된 JSON 구조를 포함하여 파싱 에러가 발생한다. 또한, Gemini가 생성한 코드 개선 제안이 적절하지 않은 경우가 발생할 수 있다.
- ESLint가 한 번에 모든 파일을 처리하고, 각 오류 메시지에 대해 Gemini API, GitHub API 요청을 하고 있다. 만약 파일 수가 많거나 메시지가 많은 경우 실행 시간이 급격히 증가하여 성능 개선이 필요하다.
마치며
GitHub Actions는 다른 CI/CD 도구와 달리 소스 코드가 GitHub와 완전히 통합되어 있어, 설정과 운영이 비교적 쉽고, 코드 리뷰와 협업 흐름이 자연스럽게 연결된다. 또한, workflow를 유연하게 정의할 수 있고, 다양한 플랫폼과 언어를 지원하고 있어 팀의 복잡한 CI/CD 요구 사항이 있더라도 비교적 쉽게 설정할 수 있다. 이미 GitHub Marketplace와 오픈소스 커뮤니티에서 수많은 Action이 있지만, 팀에 꼭 맞는 Action이 없다면 직접 Custom Action을 만들어 사용할 수 있다. 이렇게 만든 Action은 팀의 생산성을 높일 수 있을 뿐만 아니라 개발자가 즐겁게 코드를 작성할 수 있는 환경을 만들 수 있을 것이라 기대한다.
# References
[1] https://en.wikipedia.org/wiki/Timeline_of_GitHub
[2] https://github.com/jihye1/eslint-gemini-action
[3] https://docs.github.com/en/actions
[4] https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-javascript-action
[5] https://docs.github.com/en/actions/sharing-automations/creating-actions/about-custom-actions
[6] https://ai.google.dev/gemini-api/docs
[7] https://docs.github.com/ko/rest/pulls/pulls#get-a-pull-request
[8] https://docs.github.com/en/rest/pulls/comments
[9] https://github.com/actions/toolkit/tree/main/packages/core
[10] https://github.com/actions/starter-workflows/blob/main/code-scanning/eslint.yml
[11] https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows
[12] https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners
[13] https://docs.github.com/en/actions/writing-workflows/choosing-where-your-workflow-runs/choosing-the-runner-for-a-job
[14] https://docs.github.com/en/actions/writing-workflows/using-workflow-templates

원지혜 프로
소프트웨어사업부 솔루션사업팀
프로그래밍 언어를 전공하고 개발 플랫폼 분야에서 경력을 쌓아왔습니다. 현재 DeepScan 서비스를 개발하고 있습니다.
-
다음 글다음 글이 없습니다.
Register for Download Contents
- 이메일 주소를 제출해 주시면 콘텐츠를 다운로드 받을 수 있으며, 자동으로 뉴스레터 신청 서비스에 가입됩니다.
- 뉴스레터 서비스 가입 거부 시 콘텐츠 다운로드 서비스가 제한될 수 있습니다.
- 파일 다운로드가 되지 않을 경우 s-core_mktg@samsung.com으로 문의해주십시오.