목차
여러 개발자가 협업을 할 때 수작업으로 개발코드를 통합하고 테스트한다면 코드가 꼬이거나 버그가 발생할 수 있습니다. 최악의 경우 다시 개발해야 하는 힘든 상황이 올지도 모릅니다. CI/CD를 도입하면 이러한 문제를 예방할 수 있습니다. 이미 CI/CD는 개발에서 중요한 개념으로 자리 잡았으며, 많은 기업들은 CI/CD를 통해 코드 개발 및 배포 작업을 획기적으로 간소화하고 있습니다.
저는 CI/CD 도구 중 Github Actions을 이용해 프로젝트에 도입했습니다. Github Actions는 비교적 쉽고 빠르게 CI/CD를 구축할 수 있으며, public repository 한정으로 무료로 제공합니다.
CI/CD란?
CI/CD는 자동화 기능을 사용하여 코드 개발 및 제공을 획기적으로 간소화할 수 있는 2단계의 프로세스입니다.
CI (Continuous Integration)
‘지속적인 통합’을 의미합니다. 지속적인 통합은 개발을 진행하면서 코드의 통합을 지속적으로 진행해 코드의 품질을 유지시키는 것을 의미합니다. 소스 코드 통합 및 버전 관리 등의 개발자 작업을 보다 효율적으로 수행할 수 있도록 함으로써 소프트웨어를 보다 신속하게 운영환경에 배치할 수 있도록 해주는 사전 단계입니다.
⇒ 빌드와 테스트의 자동화
CD (Continuous Delivery & Continuous Deployment)
‘지속적인 배포’를 의미합니다. 지속적인 배포는 소프트웨어가 항상 신뢰 가능한 수준에서 배포될 수 있도록 하는 것을 의미합니다. 소프트웨어를 배포하기 위해서는 빌드와 테스트는 필수적이기 때문에, CD를 위해서는 CI가 선행되어야 하며, CI에서 유효성 검증이 끝난 코드들을 저장소에 자동으로 릴리스합니다.
⇒ 배포의 자동화
CI/CD 구축 과정
제가 진행한 프로젝트의 브런치는 feature, develop, release, master branch로 구성되어 있습니다.
feature branch
기능 개발용 브랜치입니다. ex) 로그인 기능 개발 feature/login
develop 브랜치에서 새로운 기능에 대해 freture 브랜치를 분기합니다. feature 브랜치에서 개발이 완료되면 develop 브랜치로 PR 합니다. develop 브랜치로 merge 후 feature 브랜치는 삭제합니다.
develop branch
개발을 위한 브랜치입니다.
release branch
출시 버전을 준비하는 브랜치입니다. Tag를 이용해 버전을 관리합니다. ex) vX.X.X
릴리즈를 위한 준비가 완료되면 master 브랜치에 병합합니다.
master branch
바로 배포해서 사용 가능한 최종 브랜치입니다.
프로젝트의 develop 브랜치에서 새로운 기능을 개발할 때 feature 브랜치를 분기하여 개발했습니다. 기능 개발 작업이 끝나면 develop 브랜치로 merge 하고 feautre 브랜치는 삭제합니다. develop 브랜치에서 배포를 위한 기능이 모이면 해당 시점을 기준으로 release 브랜치를 생성합니다. release 브랜치에서 배포를 위해 테스트, 버그 수정, QA를 진행하고 릴리즈 문서를 추가합니다. 배포 준비가 완료되면 master 브랜치로 최종 merge 합니다. 동기화를 위해 develop 브랜치에도 merge 합니다.
저는 feature 브랜치에서 기능 개발이 끝나 develop 브랜치로 PR이 들어올 경우 CI를 시키고, release 브랜치에 push나 PR이 들어올 경우 CD를 진행했습니다. 또한 공통으로 push나 PR 발생 시 슬랙으로 알림이 오도록 하였습니다.
CI 구성
CI 구성은 아래와 같습니다. 코드의 품질을 높이기 위해 ktlint, detekt, unit tests를 체크해 주었습니다. test report 도 추가했습니다.
name: Android CI on develop PR
on:
pull_request:
branches: [ develop ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'adopt'
cache: gradle
- name: Setup Android SDK
uses: android-actions/setup-android@v2
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Run ktlint
run: ./gradlew ktlintCheck
- name: Run detekt
run: ./gradlew detekt
- name: Run unit tests
run: ./gradlew testDebugUnitTest
- name: Create android test report
uses: asadmansr/android-test-report-action@v1.2.0
if: ${{ always() }}
- name: Build assemble release apk
run: ./gradlew assembleRelease
CD 구성
CD 구성은 아래와 같습니다. 앱 배포는 Firebase App Distribution 을 사용했습니다. JSON 형태의 서비스 자격 증명 개인 키 파일 serviceCredentialsFileContent를 사용하여 인증을 했습니다. groups은 미리 파이어베이스에서 설정해 놓은 테스터 그룹으로 지정하였습니다. 각 옵션에 대한 설명은 Firebase-Distribution-Github-Action에서 확인하실 수 있습니다.
name: Android CD on release push or PR
on:
push:
branches: [ release ]
pull_request:
branches: [ release ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'adopt'
cache: gradle
- name: Setup Android SDK
uses: android-actions/setup-android@v2
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build assemble release apk
run: ./gradlew assembleRelease
- name: Upload apk to Firebase App Distribution
uses: wzieba/Firebase-Distribution-Github-Action@v1
with:
appId: ${{ secrets.FIREBASE_APP_ID }}
serviceCredentialsFileContent: ${{ secrets.CREDENTIAL_FILE_CONTENT }}
groups: release-testers
file: app/build/outputs/apk/release/app-release-unsigned.apk
releaseNotesFile: documents/release-note/default-note.txt
사용한 releaseNotesFile 양식은 아래와 같습니다. documents/release-note 경로에 파일을 작성하였습니다.
Release: Android X.X.X
Release date: XXXX-XX-XX
#Bug Fixes
- 버그 수정사항을 적어주세요.
#Improvements
- 개선사항을 적어주세요.
#New Features
- 추가된 새로운 기능을 적어주세요.
추가) 알림 구성
Slack을 연동하였습니다.
- name: Action slack
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
author_name: Sloth Backend - dev
fields: repo,commit,message,author,eventName,ref,workflow
mention: here
if_mention: failure,cancelled
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
if: always()
마무리
Github Actions를 이용해서 쉽고 간단하게 CI/CD를 구축할 수 있었습니다.
다음번에는 master 브랜치를 Google Play Store에 자동 배포되도록 구현하여 좀 더 완벽한 CD를 구축해 보고 싶습니다.
![](https://t1.daumcdn.net/keditor/emoticon/niniz/large/002.gif)
'Main' 카테고리의 다른 글
[Android] 이미지 로드 최적화 (10) | 2023.01.06 |
---|---|
[Android] 다양한 폼 팩터를 위한 UI 개발 (4) | 2022.12.30 |
[Android] Room을 활용해 Android 오프라인 캐시 구현 (0) | 2022.12.06 |
[Android] Service를 활용한 Timer 개발 (0) | 2022.11.30 |
MVP 앱 개발 (4) | 2022.11.06 |
댓글