개발/Android

[Android] Github Actions로 CI 적용하기 - 간단 가이드

호두가코딩했어요 2025. 4. 2. 15:53

들어가며

여러 개발자와 협업을 할 때, CI(Continuous Integration)나 CD(Continuous Deployment)가 적용되어있다면 각자가 개발한 기능을 병합하기 수월해집니다.
CI/CD를 지원해주는 도구는 젠킨스(Jenkins), 서클CI(circle ci) 등 여러 가지가 있으며, 빠르고 간편하게 CI/CD를 적용하고 싶다면 GitHub에서 제공해주는 GitHub Actions를 사용할 수 있습니다. 제가 하고 있는 스타카토 프로젝트도 GitHub Actions를 활용해 CI/CD를 적용하고 있습니다.

 

꾸준히 프로젝트를 진행하며 CI/CD를 조금씩 개선해왔습니다. CI와 CD를 구축하며 알게된 내용을 정리해 간단한 가이드를 만들어보고자 합니다. 이번 포스팅은 GitHub Actions로 CI를 구성하는 방법을 스타카토 프로젝트 경험을 바탕으로 작성해보겠습니다.

해당 포스팅은 CI에 대한 개념이 잡혀있는 독자, 안드로이드 개발을 하고있는 독자, 프로젝트에 CI를 적용하고 싶은 독자를 대상으로 작성된 글입니다.
CI/CD에 대한 개념을 먼저 익히고 오는 것을 권장드립니다.

 

GitHub Actions 로 빠르게 CI 적용하기

GitHub Actions 란?

GitHub 원격 레포지토리 서버에서 CI/CD(Continuous Integration, Continuous Deployment)를 수행할 수 있도록 지원해주는 플랫폼입니다.
원격의 코드 저장소에서 발생하는 이벤트(e.g. 브랜치 병합, PR 생성, 이슈 생성 등)에 따라 자동으로 수행할 작업을 설계할 수 있습니다.

이러한 이벤트를 잘 활용하면 PR에 커밋이 push 될 때마다 워크플로를 실행시켜 빌드와 테스트를 자동화할 수 있고, 다른 원하는 동작도 자동으로 실행시킬 수 있습니다.

 

시작하기

간단 가이드인 만큼, CI를 적용하는 방법부터 빠르게 알아보겠습니다.

GitHub Actions로 CI/CD를 설정하는 방법은 2가지가 있습니다.

방법 1 - GitHub Actions 탬플릿 활용

GitHub 레포지토리의 상단 탭에서 Actions를 선택하면 아래와 같이 나타납니다.

Actions 탬플릿 검색 화면

 

이곳에서 원하는 키워드를 검색하여 원하는 워크플로를 빠르게 시작할 수 있습니다. 물론 기본적인 설정만 작성되어있고, 프로젝트 환경에 따라 커스텀하게 변경해주어야합니다.

참고로 이미지에 보이는 Simple workflow를 선택하면, 워크플로의 기본 요소들을 한 파일에 확인할 수 있습니다.

방법 2 - 직접 작성하기( .github/workflows/ )

워크플로를 구성하는 파일은 레포지토리의 .github/workflows/ 경로에 저장합니다.

따라서 로컬 레포지토리에서 위 디렉토리 경로에 워크플로 파일을 작성하여 CI/CD를 적용할 수 있습니다.

스타카토 프로젝트의 CI/CD 워크플로 파일

 

워크플로 파일 형식은 YML 파일이고, 문법이 정해져있습니다. 처음이라면 낯설고 어렵게 느껴지겠지만, 문법 자체는 굉장히 쉬워서 금방 익숙해질 수 있습니다.

또 자바 버전, 빌드 파일 설정 등 프로젝트 환경에 따라 커스텀하게 설정해주어야 하기 때문에, 저는 탬플릿을 사용하지 않고 직접 작성하는 편입니다. 만약 처음 도입하신다면, 시간은 조금 걸리더라도 직접 작성하는 방법을 알아두는 것이 좋습니다.

YML 파일의 문법이 궁금하시다면, Inpa Dev님의 포스팅에서 자세하고 친절히 설명되어있으니 링크를 참고해주시기 바랍니다.
 

📑 YAML 개념 & 문법 마스터 하기

YAML 이란? 우리가 타 시스템 간에 데이터를 주고 받을 필요가 있을때 데이터의 연동과 호환성을 위해 포맷에 대한 규칙이 필요하게 된다. 한번 쯤 들어보았고, 또한 이때까지 자주 사용해왔던 CSV

inpa.tistory.com

 

주요 개념

아래는 현재 스타카토의 안드로이드에 적용된 CI 워크플로의 일부입니다.

name: Android CI

on:
  pull_request:
    branches: [ "develop" ]

jobs:
  ci:
    name: Run Unit Tests
    runs-on: ubuntu-latest

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

      - name: Setup JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'
          cache: gradle

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew

      - name: Check Lint
        run: ./gradlew ktlintCheck

      - name: Run Test
        run: ./gradlew testDebugUnitTest --stacktrace

 

 

실제 워크플로에는 더 자세한 설정이 있지만, 간단 가이드인만큼 주요 요소만 남겨놓았습니다.

위에 작성된 워크플로를 바탕으로 GitHub Action에 사용되는 주요 개념들을 설명하겠습니다.

위의 코드를 기반으로 원하는 대로 커스텀하셔도 좋습니다.

현재 스타카토 프로젝트의 CI 워크플로에서 사용 중인 Actions 요소들을 위주로 소개합니다.
더 자세한 정보는 GitHub Actions 공식 문서를 참고해 주세요!

 

워크플로 (Workflow)

CI나 CD의 자동화 프로세스를 정의한 YAML(YML) 파일입니다. 위의 파일 전체를 일컫으며, 해당 .yml 파일이 하나의 워크플로입니다.
프로젝트 디렉토리 내 .github/workflows/ 에 저장되며, 특정 이벤트가 발생할 때 실행됩니다. GitHub의 원격 레포지토리가 이 YML 파일에 작성된 작업들을 이벤트에 따라 자동으로 수행합니다.

name: Android CI   # 워크플로 이름

워크플로 파일 최상단에 워크플로의 이름을 설정할 수 있습니다.

설정한 이름은 GitHub Actions에서 아래와 같이 제목처럼 나타납니다.

GitHub Actions 워크플로 확인

 

이벤트 (Event)

워크플로를 트리거하는 조건입니다.

push, pull_request, schedule(정기 실행) 등이 있으며, 아래와 같이 on: 키와 함께 사용합니다.

# 특정 브랜치에 대한 Pull Request에서 수행
on:
  pull_request:
    branches: [ "develop" ]

# 특정 브랜치에 Push 될 때 수행(병합도 포함)
on:
  push:
    branches: [ "main" ]

 

branches로 이벤트에 대한 대상 브랜치를 설정할 수 있습니다.

 

작업 (Job)

워크플로를 구성하는 작업의 단위입니다. '어떤 목적을 수행하겠다'는 큰 맥락 같은 것으로 이해하시면 좋습니다.
기본적으로 Job은 병렬적으로, 독립적으로 실행됩니다. needs: 를 설정하여 특정 작업을 순서대로 실행할 수 있습니다.

jobs:
  build:  # 빌드를 수행하는 job
	...

  test:  # 테스트를 수행하는 job, build와 병렬적, 독립적으로 실행
	...

  cd:  # CD를 수행하는 job
    needs: build  # build job이 실행된 이후에 실행
    ...

 

이해를 돕기 위해 위와 같이 예시 코드를 작성했지만, 모든 Job은 독립적인 환경에서 실행된다는 점을 명심해야 합니다.

때문에 build Job에서 설정하고 실행한 결과는 cd Job에 영향을 끼치지 않습니다.

 

러너 (Runner)

워크플로의 Job을 실제로 실행하는 환경입니다. Job은 사용자가 지정한 러너 환경에서 실행됩니다.
GitHub에서 제공하는 Hosted Runner(Ubuntu, Windows, macOS) 또는 사용자가 설정한 Self-hosted Runner를 사용할 수 있습니다.

jobs:
  ci:
    name: Run Unit Tests
    runs-on: ubuntu-latest  # Ubuntu 최신 버전에서 실행(권장 설정)

 

단계 (Step)

Job 내에서 순차적으로 실행되는 명령어 또는 액션입니다.
특정 스크립트를 실행하거나 원하는 액션 호출이 가능합니다.

아래와 같이 steps: 키에서 리스트(-)로 설정합니다.

액션의 경우 uses: 키워드를, 특정 스크립트(명령어)를 실행하고자 한다면 run: 키워드를 사용합니다.

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

      - name: Setup JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'
          cache: gradle

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew

      - name: Check Lint
        run: ./gradlew ktlintCheck

      - name: Run Test
        run: ./gradlew testDebugUnitTest --stacktrace

 

 

액션 (Action)

특정 작업을 수행하는 재사용 가능한 코드 조각입니다.
GitHub Marketplace에서 다양한 액션을 찾아 사용할 수 있습니다. 다른 사용자가 만든 커스텀 액션이 존재합니다.

아래 이미지처럼 GitHub 페이지에서 워크플로를 작성, 수정하는 경우 우측에서 액션을 검색할 수 있습니다.

워크플로 작성 페이지 우측에서 Action을 검색할 수 있습니다.

더 많은 액션을 검색하고 싶다면 GitHub Marketplace 사이트를 참고해주세요.
액션마다 사용법이 다르고 버전에 따라 달라질 수 있기 때문에, 액션의 공식 문서를 직접 참고하여 설정하시는 것을 권장드립니다.

 

액션을 사용할 때는 uses: 를 사용합니다.

      # 원격 레포지토리로 체크아웃하는 액션
      - name: Checkout Repository
        uses: actions/checkout@v4

      # JDK를 설정하는 액션
      - name: Setup JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'
          cache: gradle


위의 actions/checkout 은 저장소 코드를 체크아웃하는 작업을 수행합니다. 원격 레포지토리의 코드를 확인해야하는 작업일 때 필수적으로 사용합니다.

JDK 액션의 버전은 프로젝트의 JDK 버전에 맞게 설정해주어야 하므로, 현재 프로젝트의 JDK 버전과 Java 세팅 액션의 공식문서를 확인해주시기 바랍니다.

 

 

기본적인 동작 흐름

워크플로의 각 중요 요소들을 알아보았으니, 전체 흐름을 살펴보며 CI가 동작하는 과정을 살펴보겠습니다.

트리거 감지

develop 브랜치에 대한 Pull Request 이벤트가 발생하면 GitHub Actions가 이를 감지하여 워크플로를 시작합니다.

on:
  pull_request:
    branches: [ "develop" ]

 

워크플로 및 Job 실행

위 트리거에 따라 현재 YAML 파일에 정의된 워크플로가 실행됩니다.

워크플로의 각 Job을 실행하며, 현재 워크플로에서는 'ci' 라는 이름의 Job이 실행됩니다.

해당 Job이 Actions 페이지와 콘솔에서 나타나는 이름은 "Run Unit Tests"로 설정했고, ubuntu 최신 버전에서 실행됩니다.

jobs:
  ci:
    name: Run Unit Tests
    runs-on: ubuntu-latest

 

각 Step 순차 실행

각 Job은 지정된 러너 환경에서 실행되며, Job 내의 Step은 순차적으로 진행됩니다.

 

레포지토리 체크아웃

      # 레포지토리 체크아웃
      - name: Checkout Repository
      - uses: actions/checkout@v4

 

JDK 버전 설정

저희는 JDK 17 버전을 채택하고 있습니다.

      # JDK 버전 설정
      - name: Setup JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'  # 17 버전
          distribution: 'temurin'  # temurin
          cache: gradle  # gradle 캐싱 설정

 

Gradle 실행 권한 설정

gradlew 명령어를 이용해 빌드 또는 테스트를 실행할 수 있도록, gradlew의 접근 권한에 실행 권한을 추가합니다.

      - name: Grant Execute Permission for gradlew
        run: chmod +x gradlew    # gradlew 명령어에 대한 실행 권한 설정하기

 

Lint 확인

gradlew 명령어로 현재 프로젝트의 코틀린 린트를 확인합니다.

      - name: Check Lint
        run: ./gradlew ktlintCheck    # 코틀린 린트 확인

 

테스트 실행

gradlew 명령어로 현재 프로젝트의 단위 테스트를 실행합니다.

저는 디버그 모드에서의 테스트를 실행하며, --stacktrace 옵션으로 콘솔에 로그를 출력하도록 했습니다.

다른 조건, 방식의 테스트를 실행하고 싶다면 원하는 명령어를 설정하면 됩니다.

e.g. testReleaseUnitTest, --no-build-cache 등

      - name: Run Test
        run: ./gradlew testDebugUnitTest --stacktrace    # Debug 테스트 실행

 

실행 완료 및 결과 확인

모든 작업이 완료되면 결과는 GitHub의 Actions 탭에서 확인할 수 있습니다.

워크플로에 설정된 이벤트에 따라 실행된 결과가 저장됩니다.
워크플로가 실행된 Job을 볼 수 있습니다.
Job이 실행된 흐름과 콘솔 로그를 확인할 수 있습니다.

 

마치며

이번 포스팅에서는 GitHub Actions를 활용해 CI를 적용하는 방법을 빠르고 간단하게 알아보았습니다.

그러나 간단한 프로젝트라면 괜찮지만, 구글 맵 등의 다른 SDK를 사용하는 경우에는 몇 가지 설정이 더 필요합니다.

  • 프로젝트 빌드에 필요하지만 원격에 Push 되어서는 안되는 설정 파일(local.properties, google-services.json 등)

또 여러 편리한 기능을 제공해주는 Actions나, 워크플로의 효율을 증가시키기 위한 추가 설정도 가능합니다.

저 또한 처음에는 단순하게 설정했으나, 프로젝트에 기능이 조금씩 추가되고 불편한 점들이 하나 둘 보이면서 워크플로를 꾸준히 개선 중에 있습니다.

다음 포스팅은 제가 CI 워크플로를 개선한 경험을 바탕으로, GitHub Actions를 잘 활용하는 방법을 다뤄보겠습니다.

 

참고 자료

Inpa Dev 님의 기술 블로그 - YAML 개념 & 문법 마스터 하기