diff --git a/android/app/version.properties b/android/app/version.properties index 875f85b..fafb77c 100644 --- a/android/app/version.properties +++ b/android/app/version.properties @@ -1,3 +1,3 @@ -buildNumber=7 -versionCode=7 -versionName=1.1.1.3 +buildNumber=8 +versionCode=8 +versionName=1.1.8 diff --git a/android/app_version.json b/android/app_version.json index e2e868b..ddfd747 100644 --- a/android/app_version.json +++ b/android/app_version.json @@ -1,6 +1,6 @@ { - "versionCode": 7, - "versionName": "1.1.1.3", - "buildNumber": 7, + "versionCode": 8, + "versionName": "1.1.8", + "buildNumber": 8, "notes": "사용자가 수정한 버전 정보입니다. 이 파일을 편집하여 앱 버전 정보를 변경할 수 있습니다." } diff --git a/android/version.properties b/android/version.properties index 875f85b..fafb77c 100644 --- a/android/version.properties +++ b/android/version.properties @@ -1,3 +1,3 @@ -buildNumber=7 -versionCode=7 -versionName=1.1.1.3 +buildNumber=8 +versionCode=8 +versionName=1.1.8 diff --git a/docs/02_기술_문서/ci-cd-pipeline.md b/docs/02_기술_문서/ci-cd-pipeline.md new file mode 100644 index 0000000..f3780af --- /dev/null +++ b/docs/02_기술_문서/ci-cd-pipeline.md @@ -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를 통한 직접 설치는 개발자만 가능합니다.