버전 정보 파일 및 CI/CD 문서 업데이트

This commit is contained in:
hansoo
2025-04-05 15:52:06 +09:00
parent d1e45edcdb
commit e5caa27e91
4 changed files with 570 additions and 9 deletions

View File

@@ -0,0 +1,561 @@
# Zellyy Finance CI/CD 파이프라인 가이드
이 문서는 Zellyy Finance 앱의 CI/CD(지속적 통합/지속적 배포) 파이프라인 구축 및 사용 방법에 대해 설명합니다.
## 목차
1. [개요](#개요)
2. [CI/CD 파이프라인 구성](#cicd-파이프라인-구성)
3. [GitHub Actions 설정](#github-actions-설정)
4. [버전 관리 자동화](#버전-관리-자동화)
5. [테스트 빌드 배포 및 설치](#테스트-빌드-배포-및-설치)
6. [앱스토어 자동 배포](#앱스토어-자동-배포)
7. [비용 분석](#비용-분석)
8. [문제 해결 및 FAQ](#문제-해결-및-faq)
## 개요
CI/CD 파이프라인은 코드 변경사항을 자동으로 빌드, 테스트 및 배포하는 자동화된 프로세스입니다. Zellyy Finance 앱에서는 GitHub Actions를 사용하여 이 프로세스를 구현합니다.
### 주요 이점
- **개발 효율성 향상**: 반복적인 빌드 및 배포 작업 자동화
- **일관된 빌드 품질**: 동일한 환경에서 항상 일관된 방식으로 빌드
- **버전 관리 자동화**: 버전 코드 및 빌드 번호 자동 증가
- **배포 프로세스 간소화**: 앱스토어 제출 과정 자동화
- **팀 협업 개선**: 빌드 상태 및 결과 공유 용이
## CI/CD 파이프라인 구성
Zellyy Finance의 CI/CD 파이프라인은 다음과 같은 단계로 구성됩니다:
1. **코드 검증**: 린트 검사 및 단위 테스트 실행
2. **웹 앱 빌드**: React 앱 빌드
3. **네이티브 앱 빌드**: Capacitor를 통한 Android/iOS 앱 빌드
4. **테스트 배포**: Firebase App Distribution을 통한 테스터 배포
5. **앱스토어 배포**: Google Play Store 및 Apple App Store 배포
### 워크플로우 다이어그램
```
코드 푸시/PR → 코드 검증 → 웹 앱 빌드 → 네이티브 앱 빌드 → 테스트 배포 → 앱스토어 배포
```
## GitHub Actions 설정
### 워크플로우 파일 생성
`.github/workflows/ci-cd.yml` 파일을 생성하여 CI/CD 파이프라인을 구성합니다.
```yaml
name: Zellyy Finance CI/CD
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
workflow_dispatch:
inputs:
buildType:
description: '빌드 타입 (debug, release-apk, release-aab, ios-release)'
required: true
default: 'debug'
versionCode:
description: '버전 코드 (자동 증가는 1, 수동 지정은 원하는 숫자 입력)'
required: false
versionName:
description: '버전 이름 (예: 1.0.0)'
required: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 노드 설정
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: 종속성 설치
run: npm ci
- name: 린트 검사
run: npm run lint
- name: 버전 정보 설정
id: version
run: |
# 현재 버전 코드 가져오기
CURRENT_VERSION_CODE=$(grep -o 'versionCode [0-9]*' android/app/build.gradle | awk '{print $2}')
if [ -z "$CURRENT_VERSION_CODE" ]; then
CURRENT_VERSION_CODE=1
fi
# 현재 버전 이름 가져오기
CURRENT_VERSION_NAME=$(grep -o 'versionName "[^"]*"' android/app/build.gradle | sed 's/versionName "//' | sed 's/"//')
if [ -z "$CURRENT_VERSION_NAME" ]; then
CURRENT_VERSION_NAME="1.0.0"
fi
# 입력된 버전 정보 또는 기본값 사용
if [ "${{ github.event.inputs.versionCode }}" = "1" ] || [ -z "${{ github.event.inputs.versionCode }}" ]; then
NEW_VERSION_CODE=$((CURRENT_VERSION_CODE + 1))
else
NEW_VERSION_CODE=${{ github.event.inputs.versionCode }}
fi
VERSION_NAME="${{ github.event.inputs.versionName }}"
if [ -z "$VERSION_NAME" ]; then
VERSION_NAME=$CURRENT_VERSION_NAME
fi
BUILD_NUMBER=$NEW_VERSION_CODE
# 버전 정보 파일 업데이트
echo "buildNumber=$BUILD_NUMBER" > android/version.properties
echo "versionCode=$NEW_VERSION_CODE" >> android/version.properties
echo "versionName=$VERSION_NAME" >> android/version.properties
cp android/version.properties android/app/version.properties
# app_version.json 파일 업데이트
cat > android/app_version.json << EOF
{
"versionCode": $NEW_VERSION_CODE,
"versionName": "$VERSION_NAME",
"buildNumber": $BUILD_NUMBER,
"notes": "자동 빌드에 의해 생성된 버전 정보입니다."
}
EOF
echo "VERSION_CODE=$NEW_VERSION_CODE" >> $GITHUB_OUTPUT
echo "VERSION_NAME=$VERSION_NAME" >> $GITHUB_OUTPUT
echo "BUILD_NUMBER=$BUILD_NUMBER" >> $GITHUB_OUTPUT
- name: 웹 앱 빌드
run: npm run build
- name: Capacitor 동기화
run: npx cap sync android
- name: JDK 설정
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
cache: 'gradle'
- name: 안드로이드 앱 빌드
working-directory: android
run: |
if [ "${{ github.event.inputs.buildType }}" = "release-aab" ]; then
./gradlew clean bundleRelease
elif [ "${{ github.event.inputs.buildType }}" = "release-apk" ]; then
./gradlew clean assembleRelease
else
./gradlew clean assembleDebug
fi
- name: Firebase App Distribution 배포
if: github.event.inputs.buildType == 'debug'
uses: wzieba/Firebase-Distribution-Github-Action@v1
with:
appId: ${{ secrets.FIREBASE_APP_ID }}
serviceCredentialsFileContent: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }}
groups: testers
file: android/app/build/outputs/apk/debug/app-debug.apk
releaseNotes: |
버전: ${{ steps.version.outputs.VERSION_NAME }} (${{ steps.version.outputs.BUILD_NUMBER }})
빌드 날짜: $(date +'%Y-%m-%d %H:%M:%S')
커밋: ${{ github.sha }}
- name: Google Play 배포
if: github.event.inputs.buildType == 'release-aab'
uses: r0adkll/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{ secrets.PLAY_STORE_SERVICE_ACCOUNT_JSON }}
packageName: com.zellyy.finance
releaseFiles: android/app/build/outputs/bundle/release/app-release.aab
track: internal
status: completed
releaseName: ${{ steps.version.outputs.VERSION_NAME }}
releaseNotes: |
ko-KR: 버전 ${{ steps.version.outputs.VERSION_NAME }} 업데이트
- 버그 수정 및 성능 개선
- name: 빌드 결과물 저장
uses: actions/upload-artifact@v3
with:
name: app-${{ steps.version.outputs.VERSION_NAME }}-${{ steps.version.outputs.BUILD_NUMBER }}
path: |
android/app/build/outputs/apk/debug/*.apk
android/app/build/outputs/apk/release/*.apk
android/app/build/outputs/bundle/release/*.aab
- name: 슬랙 알림
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
fields: repo,message,commit,author,action,eventName,ref,workflow,job,took
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
if: always()
```
### GitHub Secrets 설정
GitHub 저장소의 Settings > Secrets and variables > Actions에서 다음 시크릿을 설정해야 합니다:
- `FIREBASE_APP_ID`: Firebase 프로젝트의 앱 ID
- `FIREBASE_SERVICE_ACCOUNT`: Firebase 서비스 계정 JSON 파일 내용
- `PLAY_STORE_SERVICE_ACCOUNT_JSON`: Google Play 서비스 계정 JSON 파일 내용
- `SLACK_WEBHOOK_URL`: 슬랙 알림을 위한 웹훅 URL
## 버전 관리 자동화
### 버전 관리 스크립트
`scripts/version-manager.sh` 파일을 생성하여 버전 관리를 자동화합니다.
```bash
#!/bin/bash
# version-manager.sh
# 현재 버전 정보 가져오기
get_current_version() {
if [ -f "android/app_version.json" ]; then
VERSION_CODE=$(grep -o '"versionCode": [0-9]*' android/app_version.json | awk '{print $2}')
VERSION_NAME=$(grep -o '"versionName": "[^"]*"' android/app_version.json | sed 's/"versionName": "//' | sed 's/"//')
BUILD_NUMBER=$(grep -o '"buildNumber": [0-9]*' android/app_version.json | awk '{print $2}')
# 값이 비어있는지 확인
if [ -z "$VERSION_CODE" ]; then VERSION_CODE=1; fi
if [ -z "$VERSION_NAME" ]; then VERSION_NAME="1.0.0"; fi
if [ -z "$BUILD_NUMBER" ]; then BUILD_NUMBER=1; fi
else
VERSION_CODE=1
VERSION_NAME="1.0.0"
BUILD_NUMBER=1
fi
echo "현재 버전 정보:"
echo "버전 코드: $VERSION_CODE"
echo "버전 이름: $VERSION_NAME"
echo "빌드 넘버: $BUILD_NUMBER"
}
# 버전 정보 업데이트
update_version_files() {
# version.properties 파일 업데이트
echo "buildNumber=$BUILD_NUMBER" > android/version.properties
echo "versionCode=$VERSION_CODE" >> android/version.properties
echo "versionName=$VERSION_NAME" >> android/version.properties
# app 디렉토리에도 동일한 파일 복사
cp android/version.properties android/app/version.properties
# app_version.json 파일 업데이트
cat > android/app_version.json << EOF
{
"versionCode": $VERSION_CODE,
"versionName": "$VERSION_NAME",
"buildNumber": $BUILD_NUMBER,
"notes": "자동 업데이트된 버전 정보입니다."
}
EOF
echo "버전 정보가 모든 파일에 저장되었습니다."
}
# 메인 함수
main() {
get_current_version
# 빌드 타입에 따라 버전 증가
case "$1" in
"debug")
BUILD_NUMBER=$((BUILD_NUMBER + 1))
;;
"release")
VERSION_CODE=$((VERSION_CODE + 1))
BUILD_NUMBER=$VERSION_CODE
;;
*)
echo "사용법: $0 [debug|release]"
exit 1
;;
esac
update_version_files
echo "업데이트된 버전 정보:"
echo "버전 코드: $VERSION_CODE"
echo "버전 이름: $VERSION_NAME"
echo "빌드 넘버: $BUILD_NUMBER"
}
main "$@"
```
### 버전 관리 규칙
Zellyy Finance 앱의 버전 관리는 다음 규칙을 따릅니다:
- **versionCode**: 앱스토어에 제출할 때마다 증가하는 정수 값
- **versionName**: 사용자에게 표시되는 버전 (예: "1.0.0")
- **buildNumber**: 내부 빌드 추적을 위한 번호
## 테스트 빌드 배포 및 설치
테스트 빌드가 완료된 후 개발자와 테스터가 앱을 설치하고 테스트할 수 있는 방법을 설명합니다.
### Firebase App Distribution을 통한 배포
Firebase App Distribution은 테스트 버전 앱을 테스터에게 쉽게 배포할 수 있는 서비스입니다.
#### 설정 방법
1. **Firebase 프로젝트 설정**:
- [Firebase 콘솔](https://console.firebase.google.com/)에서 프로젝트 생성
- App Distribution 서비스 활성화
- 테스터 그룹 생성 및 테스터 이메일 추가
2. **GitHub Actions 설정**:
- `FIREBASE_APP_ID``FIREBASE_SERVICE_ACCOUNT` 시크릿 설정
- 워크플로우 파일에 Firebase 배포 단계 추가
#### 테스터 초대 및 앱 설치 방법
##### 안드로이드 테스터
1. **테스터 초대**:
- Firebase 콘솔에서 테스터 이메일 추가
- 테스터에게 초대 이메일 발송
2. **앱 설치 방법**:
- 테스터는 초대 이메일의 링크를 클릭
- Firebase App Tester 앱 설치 (처음 사용 시)
- 테스트 앱 다운로드 및 설치
- 설치 시 "알 수 없는 출처" 앱 설치 허용 필요
```bash
# 안드로이드 테스터를 위한 안내 메시지 예시
안드로이드 테스트 앱 설치 방법:
1. 초대 이메일의 링크를 클릭하세요
2. Firebase App Tester 앱을 설치하세요 (처음 사용 시)
3. 테스트 앱을 다운로드하고 설치하세요
4. 설정 > 보안 > 알 수 없는 출처에서 설치 허용을 활성화하세요
```
##### iOS 테스터
1. **TestFlight 설정**:
- Apple Developer 계정에서 앱 등록
- 내부 테스터 그룹 생성
2. **테스터 초대**:
- App Store Connect에서 테스터 이메일 추가
- 테스터에게 초대 이메일 발송
3. **앱 설치 방법**:
- 테스터는 초대 이메일의 링크를 클릭
- TestFlight 앱 설치 (App Store에서 다운로드)
- TestFlight를 통해 테스트 앱 설치
```bash
# iOS 테스터를 위한 안내 메시지 예시
iOS 테스트 앱 설치 방법:
1. 초대 이메일의 링크를 클릭하세요
2. App Store에서 TestFlight 앱을 설치하세요
3. TestFlight 앱을 열고 테스트 앱을 설치하세요
```
### GitHub Actions Artifacts를 통한 직접 다운로드
Firebase App Distribution 외에도 GitHub Actions의 Artifacts 기능을 사용하여 빌드 결과물을 직접 다운로드할 수 있습니다.
1. **빌드 결과물 확인**:
- GitHub 저장소의 Actions 탭으로 이동
- 해당 워크플로우 실행 결과 페이지 열기
- Artifacts 섹션에서 APK 또는 IPA 파일 다운로드
2. **안드로이드 APK 설치**:
- 다운로드한 APK 파일을 안드로이드 기기로 전송
- 파일 관리자에서 APK 파일 실행
- 알 수 없는 출처 앱 설치 허용
3. **iOS IPA 설치** (개발자만 가능):
- Apple Developer 계정이 있는 개발자만 가능
- Xcode 또는 Apple Configurator를 사용하여 설치
### QR 코드를 통한 간편 설치
테스터의 편의를 위해 QR 코드를 생성하여 배포할 수도 있습니다:
```yaml
- name: QR 코드 생성
if: github.event.inputs.buildType == 'debug'
run: |
# Firebase 배포 URL에 대한 QR 코드 생성
FIREBASE_URL="https://appdistribution.firebase.dev/i/..."
curl -s "https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=$FIREBASE_URL" > qrcode.png
echo "QR 코드가 생성되었습니다. 테스터는 이 코드를 스캔하여 앱을 설치할 수 있습니다."
- name: QR 코드 저장
if: github.event.inputs.buildType == 'debug'
uses: actions/upload-artifact@v3
with:
name: install-qrcode
path: qrcode.png
```
## 앱스토어 자동 배포
### Google Play Store 배포
Google Play Store에 자동으로 앱을 배포하려면 다음 단계가 필요합니다:
1. **Google Play Console 설정**:
- API 액세스 활성화
- 서비스 계정 생성 및 권한 부여
- JSON 키 다운로드
2. **GitHub Actions 설정**:
- `PLAY_STORE_SERVICE_ACCOUNT_JSON` 시크릿 설정
- 워크플로우 파일에 배포 단계 추가
### Apple App Store 배포
Apple App Store에 자동으로 앱을 배포하려면 Fastlane을 사용합니다:
1. **Fastlane 설정**:
- iOS 디렉토리에 Fastfile 생성
```ruby
default_platform(:ios)
platform :ios do
desc "배포용 iOS 앱 빌드 및 TestFlight 업로드"
lane :release do
setup_ci
# 인증서 및 프로비저닝 프로파일 동기화
match(
type: "appstore",
readonly: true
)
# 버전 업데이트
increment_build_number(
build_number: ENV["BUILD_NUMBER"]
)
# 앱 빌드
build_app(
scheme: "App",
workspace: "App.xcworkspace",
export_method: "app-store"
)
# TestFlight 업로드
upload_to_testflight(
skip_waiting_for_build_processing: true
)
end
end
```
2. **GitHub Actions 설정**:
- App Store Connect API 키 생성 및 GitHub Secrets에 저장
- 워크플로우 파일에 iOS 빌드 및 배포 단계 추가
## 비용 분석
### GitHub Actions 비용
GitHub Actions는 다음과 같은 무료 할당량을 제공합니다:
- **퍼블릭 저장소**: 무제한 무료 사용 가능
- **프라이빗 저장소**:
- GitHub Free: 매월 2,000분의 무료 빌드 시간
- GitHub Pro: 매월 3,000분의 무료 빌드 시간
- GitHub Team: 매월 계정당 3,000분의 무료 빌드 시간
- GitHub Enterprise: 매월 계정당 50,000분의 무료 빌드 시간
### Zellyy Finance 앱의 예상 비용
- **빌드 시간 예상**: 한 번의 워크플로우당 약 7-20분
- **월간 빌드 횟수 시나리오**:
- 하루 1회 빌드: 월 30회 × 15분 = 450분
- 하루 3회 빌드: 월 90회 × 15분 = 1,350분
- 하루 5회 빌드: 월 150회 × 15분 = 2,250분
- **비용 계산**:
- GitHub Free 계정 사용 시: 월 2,000분 무료 (하루 4회 빌드까지 무료)
- 초과 사용 시: 분당 $0.008 (Linux 머신 기준)
### 비용 최적화 전략
1. **캐싱 활용**:
```yaml
- uses: actions/cache@v3
with:
path: |
~/.npm
node_modules
android/.gradle
key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }}
```
2. **빌드 트리거 최적화**:
```yaml
on:
push:
branches: [ main, develop ]
paths-ignore:
- '**.md'
- 'docs/**'
```
3. **조건부 작업 설정**:
```yaml
- name: Google Play 배포
if: github.ref == 'refs/heads/main' && github.event.inputs.buildType == 'release-aab'
# ...
```
## 문제 해결 및 FAQ
### 자주 발생하는 문제
1. **빌드 실패**:
- 종속성 문제: `npm ci` 대신 `npm install`을 사용해 보세요.
- 캐시 문제: 캐시를 삭제하고 다시 시도하세요.
2. **버전 관리 문제**:
- 버전 파일이 비어 있는 경우: 스크립트가 기본값을 설정하도록 합니다.
- 버전 코드 충돌: 수동으로 버전 코드를 설정하여 해결합니다.
3. **배포 실패**:
- 인증 문제: 서비스 계정 권한을 확인하세요.
- 앱 서명 문제: 키스토어 설정을 확인하세요.
### FAQ
**Q: 워크플로우를 수동으로 실행하려면 어떻게 해야 하나요?**
A: GitHub 저장소의 Actions 탭에서 "Zellyy Finance CI/CD" 워크플로우를 선택하고 "Run workflow" 버튼을 클릭합니다.
**Q: 특정 커밋에서 빌드를 실행하려면 어떻게 해야 하나요?**
A: 해당 커밋으로 체크아웃한 후 수동으로 워크플로우를 실행하거나, GitHub API를 사용하여 특정 커밋에서 워크플로우를 트리거할 수 있습니다.
**Q: 빌드 결과물은 어디에서 찾을 수 있나요?**
A: 워크플로우 실행 페이지의 "Artifacts" 섹션에서 다운로드할 수 있습니다.
**Q: 테스터가 테스트 앱을 설치하는 가장 쉬운 방법은 무엇인가요?**
A: Firebase App Distribution을 사용하는 것이 가장 쉽습니다. 테스터는 이메일로 초대를 받고 링크를 통해 앱을 설치할 수 있습니다. QR 코드를 제공하면 더욱 편리하게 설치할 수 있습니다.
**Q: iOS 테스트 앱 설치 시 개발자 계정이 필요한가요?**
A: TestFlight를 통한 배포의 경우 테스터는 개발자 계정이 필요하지 않습니다. 하지만 개발자는 Apple Developer 계정이 필요합니다. GitHub Actions Artifacts를 통한 직접 설치는 개발자만 가능합니다.