일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- delegate
- PG결제
- reactivex
- Swift
- 성능 개선
- Xcode
- 무선빌드
- fastlane
- flutter web
- Android
- BloC
- error
- Equatable
- shorebird
- copy on write
- Codepush
- SHIMMER
- Codemagic
- 갤럭시폴드
- MVVM
- DevTools
- FocusNode
- TextInputFormatter
- abstact
- appstore
- IOS
- reject
- struct
- GetX
- FLUTTER
- Today
- Total
뚝딱뚝딱 모바일
[Flutter] Code Push를 해보라고요? (2) - 맨땅에 헤딩하는 법 본문
아래 글에서 이어집니다.
Codemagic의 악몽
기존 Codemagic 빌드가 있기에 간단하게 붙이면 되겠다~ 생각하고 호기롭게 Codemagic 연계 문서를 클릭하였습니다.
어? 이게 뭐지? 이런 건 처음 보는데? 싶은 yaml 파일이 쫜! 하고 앞에 있었습니다.
그렇습니다. Codemagic은 GUI 형식의 Workflow Editor와 yaml 파일, 두 가지 방식의 빌드 flow를 지원하고 있었고, Shorebird를 적용하기 위해서는 yaml 파일을 새로 만들어야 했습니다!
슬퍼할 시간도 없이 바로 Docs를 정독하기 시작하였습니다.
자료가 없다 보니 그냥 공식 Docs 위주로 닥치는 대로 봤던 것 같습니다. 그중에서 가장 도움이 되었다고 생각하는 문서들입니다. 쭉 읽어보시면 좋을 것 같습니다.
Codemagic 세팅
shorebird 로그인 후 나온 토큰을 Codemagic에 넣어주어야 사용이 가능해집니다.
Codemagic 프로젝트를 yaml 파일로 변경 후 좌측 탭의 Environment variables에 진입해 줍니다.
SHOREBIRD_TOKEN 키값으로 토큰을 넣어주고 group명은 shorebird로 적어줍니다. Secure 항목도 체크해주어야 합니다.
스토어 관련 환경변수 세팅
이번엔 각 스토어에 자동 배포를 위한 환경변수를 세팅해 보겠습니다.
위 첨부한 링크들을 보시면 더욱 도움 되실 겁니다.
Codemagic 좌측 탭의 Teams -> codemagic.yaml settings -> Code signing identites에 각각의 인증서를 포함하여 주면 됩니다. 각각 이름은 codemagic.yaml에 사용할 것이기에 명확한 이름으로 지어주시면 좋습니다.
- iOS : p12파일 및 provisioning profiles
- AOS : key store
구글은 API 권한이 필요하므로, 구글 API 권한 json을 발급받아 SHOREBIRD_TOKEN을 넣어둔 Environment variables에 넣어주시면 됩니다. 여기 키값도 codemagic.yaml에서 사용할 것입니다.
애플도 연결해 줍시다. Codemagic 좌측 탭의 Teams -> General settings -> Integrations의 Developer Portal을 클릭하여 key를 추가해 주시면 됩니다. 물론 여기 키값도 codemagic.yaml에서 사용할 것입니다.
codemagic.yaml 원문
매우 매우 많은 시행착오와 오류를 겪고...
성공적인 codemagic.yaml 파일을 작성할 수 있었습니다.
아래 설명과 함께 한 번씩 보시면 좋을 것 같습니다!
definitions:
# Reusable definitions go in this section
scripts:
- &shorebird_install
name: Install Shorebird CLI
script: |
# Install the Shorebird CLI
curl --proto '=https' --tlsv1.2 https://raw.githubusercontent.com/shorebirdtech/install/main/install.sh -sSf | bash
# Set Shorebird PATH
echo PATH="/Users/builder/.shorebird/bin:$PATH" >> $CM_ENV
- &setup_local_properties
name: Set up local.properties
script: echo "flutter.sdk=$HOME/programs/flutter" > "$CM_BUILD_DIR/android/local.properties"
- &use_provisioning_profiles
name: Use provisioning profiles
script: xcode-project use-profiles
- &flutter_setting
name: Flutter setting
script: |
flutter pub get
dart run build_runner build
- &release_android
name: Release Android
script: shorebird release android --flutter-version=3.22.2 --target lib/main_prod.dart
- &release_ios
name: Release iOS
script: shorebird release ios --flutter-version=3.22.2 --target lib/main_prod.dart -- --export-options-plist=/Users/builder/export_options.plist
# patch should behind get version
- &patch_android
name: Patch Android
script: |
VERSION=$(grep '^version:' pubspec.yaml | sed 's/version: //')
echo "Version: $VERSION"
shorebird patch android --target lib/main_prod.dart --release-version=$VERSION
- &patch_ios
name: Patch iOS
script: |
VERSION=$(grep '^version:' pubspec.yaml | sed 's/version: //')
echo "Version: $VERSION"
shorebird patch ios --target lib/main_prod.dart --release-version=$VERSION -- --export-options-plist=/Users/builder/export_options.plist
- &sentry_debug_file_upload
name: Sentry Debug File Upload
script: flutter packages pub run sentry_dart_plugin
workflows:
app-deploy-workflow:
name: Deploy
instance_type: mac_mini_m1
environment:
ios_signing:
provisioning_profiles:
- ios-profile
certificates:
- ios-certificate
android_signing:
- android-keystore
groups:
- shorebird
- google_credentials
flutter: 3.22.2
xcode: 15.4
integrations:
app_store_connect: app-store-connect
scripts:
- *setup_local_properties
- *shorebird_install
- *flutter_setting
- *release_android
- *use_provisioning_profiles
- *release_ios
- *sentry_debug_file_upload
artifacts:
- build/**/outputs/**/*.aab
- build/**/outputs/apk/**/*.apk
- build/ios/ipa/*.ipa
publishing:
app_store_connect:
auth: integration
google_play:
track: production
credentials: $GCLOUD_SERVICE_ACCOUNT_CREDENTIALS
slack:
channel: 'your_channel'
notify_on_build_start: true # To receive a notification when a build starts
notify:
success: true # To not receive a notification when a build succeeds
failure: true # To not receive a notification when a build fails
patch-workflow:
name: Hotfix Patch
instance_type: mac_mini_m1
environment:
android_signing:
- android-keystore
ios_signing:
provisioning_profiles:
- ios-profile
certificates:
- ios-certificate
groups:
- shorebird
flutter: 3.22.2
xcode: 15.4
scripts:
- *setup_local_properties
- *shorebird_install
- *flutter_setting
- *patch_android
- *use_provisioning_profiles
- *patch_ios
- *sentry_debug_file_upload
publishing:
slack:
channel: 'your_channel'
notify_on_build_start: true # To receive a notification when a build starts
notify:
success: true # To not receive a notification when a build succeeds
failure: true # To not receive a notification when a build fails
각 Script와 workflow에 대해 설명드리겠습니다. (저희 회사 기준이기에 입맛에 맞게 수정하시면 됩니다.)
각각의 Script 설명
shorebird_install
- &shorebird_install
name: Install Shorebird CLI
script: |
# Install the Shorebird CLI
curl --proto '=https' --tlsv1.2 https://raw.githubusercontent.com/shorebirdtech/install/main/install.sh -sSf | bash
# Set Shorebird PATH
echo PATH="/Users/builder/.shorebird/bin:$PATH" >> $CM_ENV
Shorebird를 install 하는 Script입니다. flow를 시작할 때 실행해 주시면 됩니다.
setup_local_properties
- &setup_local_properties
name: Set up local.properties
script: echo "flutter.sdk=$HOME/programs/flutter" > "$CM_BUILD_DIR/android/local.properties"
안드로이드 빌드할 때 사용하는 Script로, Flutter SDK 경로를 설정할 때 사용합니다.
use_provisioning_profiles
- &use_provisioning_profiles
name: Use provisioning profiles
script: xcode-project use-profiles
iOS 빌드할 때 사용하는 Script로, Xcode가 빌드할 때 프로비저닝 프로필을 사용하도록 합니다.
flutter_setting
- &flutter_setting
name: Flutter setting
script: |
flutter pub get
dart run build_runner build
프로젝트의 pubspec.yaml에 적혀있는 라이브러리를 가져오고, build_runner를 통해 추가적인 파일을 만들어냅니다. (build_runner를 사용하지 않으면 아래 명령어는 빼도 무방합니다.)
Android 관련 Scripts
- &release_android
name: Release Android
script: shorebird release android --flutter-version=3.22.2 --target lib/main_prod.dart
- &patch_android
name: Patch Android
script: |
VERSION=$(grep '^version:' pubspec.yaml | sed 's/version: //')
echo "Version: $VERSION"
shorebird patch android --target lib/main_prod.dart --release-version=$VERSION
- release_andoird : Shorebird를 통해 android를 빌드합니다.
- patch_android : pubspec.yaml의 version을 가져와 Shorebird를 통해 patch를 진행합니다.
iOS 관련 Scripts
- &release_ios
name: Release iOS
script: shorebird release ios --flutter-version=3.22.2 --target lib/main_prod.dart -- --export-options-plist=/Users/builder/export_options.plist
- &patch_ios
name: Patch iOS
script: |
VERSION=$(grep '^version:' pubspec.yaml | sed 's/version: //')
echo "Version: $VERSION"
shorebird patch ios --target lib/main_prod.dart --release-version=$VERSION -- --export-options-plist=/Users/builder/export_options.plist
- release_ios : Shorebird를 통해 iOS를 빌드합니다.
- patch_ios : pubspec.yaml의 version을 가져와 Shorebird를 통해 patch를 진행합니다.
sentry_debug_file_upload
- &sentry_debug_file_upload
name: Sentry Debug File Upload
script: flutter packages pub run sentry_dart_plugin
센트리 디버그 파일을 업로드하여, 오류가 발생한 위치를 알 수 있게 해 줍니다. 센트리를 사용하지 않다면 빼셔도 무방합니다.
Workflow 설명
앱을 스토어에 심사 직전까지 올려주는 app-deploy-workflow,
Shorebird를 통해 코드푸시를 진행하는 patch-workflow가 있습니다.
Workflow에 사용되는 인자에 대해 간단히 설명드리면
- name : Codemagic에서 표기되는 Workflow의 이름입니다. 명확한 이름으로 해주시면 좋습니다.
- instance_type : 가상 환경을 구동할 기기를 뜻합니다. iOS까지 빌드하여야 하기에 무조건 맥으로 설정하여야 합니다. (iOS를 안 하실 거면 Window나 Linux로 하여도 무방합니다.)
- environment : 환경변수들을 지정해 주는 필드입니다.
- ios_signing
- provisioning_profiles : 위에서 설정해 둔 프로비저닝 프로필의 이름을 넣어주시면 됩니다.
- certificates : 위에서 설정해 둔 인증서의 이름을 넣어주시면 됩니다.
- android_signing : 위에서 설정해둔 keystore의 이름을 넣어주시면 됩니다.
- groups : Environment variables에 설정해둔 group의 이름을 넣어주시면 됩니다. shorebird와 구글 API json 그룹명을 넣어주었습니다.
- flutter : flutter 버전을 뜻합니다. 저희 같은 경우는 3.22.2를 사용 중이라 3.22.2를 지정해 주었습니다.
- xcode : xcode 버전입니다. 저희는 xcode 16.0 마이그레이션을 진행하지 않아 15.4를 사용 중입니다.
- ios_signing
- integrations
- app_store_connect : 위에서 설정해 둔 Developer Portal의 이름을 적어주시면 됩니다.
- scripts : 본인이 빌드하고자 하는 순서대로 넣어주시면 됩니다.
- artifacts : 빌드가 완료되면 Codemagic을 통해 받으려고 하는 파일의 경로들입니다. 빌드가 끝나면 다운로드 링크가 제공됩니다.
- publishing : 퍼블리싱 관련 필드입니다.
- app_store_connect : App Store Connect로 업로드합니다.
- auth : 위에서 설정해둔 integration에서 가져오도록 해주었습니다.
- google_play : Google Play Console로 업로드합니다.
- track : Google Play Console에서 설정하신 track명을 적어주시면 됩니다.
- credentials : 위에서 설정한 구글 API의 키값(그룹명 아님!)을 적어주시면 됩니다.
- slack (참고 링크) : 슬랙 메시지를 보내줍니다.
- app_store_connect : App Store Connect로 업로드합니다.
Shorebird 통해서 Code Push 하기
이렇게 Codemagic을 설정하고, deploy flow를 통해서 배포 진행 후 코드 수정 후 patch flow를 실행하시면 됩니다.
배포 후에는 콘솔을 확인해 보시면 아래 사진과 같이 버전이 추가됩니다.
버전명을 클릭하여 아래 화면에 들어올 수 있습니다.
Code Push를 했다면, 이렇게 Patch가 추가됩니다. 이 탭에서 각각의 Patch들을 활성화 / 비활성화할 수 있고, Install 여부를 볼 수 있습니다.
주의사항
현재 배포된 버전과 patch 버전이 무조건 같아야 한다는 것입니다. 예시로 배포 버전 1.1.2+13이면 patch 버전 또한 1.1.2+13이어야 합니다. 메이저, 마이너, 패치, 빌드 넘버까지 모두 같아야 합니다.
또한, 전 글에서 말했듯 Shorebird는 Dart파일의 변경만을 감지하고 적용합니다. 그렇기에 asset을 변경했다거나, 다른 라이브러리를 추가하여 yaml 파일이 달라졌다면, 이는 적용이 되지 않습니다.
Code Push 후기
4~5번 정도의 Code Push를 진행하였는데요, 딱 임시방편의 느낌이 강했습니다.
Shorebird는 앱을 껐다 켜게 되면 적용이 되는데요. 이것이 사람마다 적용 시간이 달랐습니다.
저는 Code Push 후 30분 내로 적용이 되었고, 회사 분들은 1시간, 2시간 등등 편차가 다양했습니다.
그리고 모두가 적용이 되는 것이 아닌 것 같습니다. 한 분이 유독 Code Push가 적용이 안되었습니다. 추측하기로는 자동 업데이트 설정을 끄면 적용이 안 되는 것이 아닐까?라는 생각으로 자동 업데이트 설정을 켜고 앱을 재설치하니 적용이 되었습니다. 정확한 원인인지는 모르겠으나, Code Push 변경 사항이 적용이 되지 않았다면 이를 의심해 볼 수 있습니다.
이러한 점 때문에, 크리티컬 한 이슈가 터졌을 때 약간의 유저라도 불편을 덜 겪게 하자!라고 생각하신다면 Shorebird 사용을 추천드립니다. 그게 아니라면 스토어를 통한 정식 업데이트가 더욱 좋을 수 있습니다.
뭐야 되게 간단하네?라고 생각하실 겁니다. 저도 지금 보니 되게 간단한 내용 같습니다.
하지만 이렇게 구성하기까지 정말 많은 오류와 시행착오를 겪었습니다. 개발 당시 자료가 너무 없었고, 공식 Docs도 지금처럼 세세하게 작성이 안되어 있어, 그냥 제 맘대로 넣어보고, 실패하면 고치고를 수십 수백 번 반복했었습니다. 진짜 맨땅에 헤딩을 하듯 시도했고, 다행히 저는 머리가 깨지지 않고 머리가 단단해졌습니다.
이걸 통해서 자료가 없을 때 개발 하는 법과 가끔은 무식하게 맨땅에 헤딩하는 편이 자료를 찾고 분석하고 진행하는 것보다 좋을 때가 있다를 깨달았습니다. 이 Code Push를 적용하면서 좀 더 한 단계 성장한 기분이 듭니다.
다음 편은 제가 만났던 오류와 제 실수들을 적어보려고 합니다. 많은 도움이 되길 바라겠습니다.
'실무 이야기' 카테고리의 다른 글
[Flutter] Code Push를 해보라고요? (1) - 지피지기 (2) | 2024.11.22 |
---|---|
[Android] 갤럭시 폴드는 없지만 대응은 하고 싶어 (2) | 2024.11.19 |
[Flutter] PG결제 웹뷰 만들다 만난 이슈들 (1) | 2024.01.02 |
[Flutter] 아키텍처에 대한 고민 (2) - 익숙해지니 보이는 것들 (3) | 2023.12.07 |
[Flutter] 아키텍처에 대한 고민 (1) - 처음 해보는 Flutter (2) | 2023.12.07 |