항상 효율적으로 반복되는 시스템을 자동화하려고 하는데,
그 중 하나가 앱 배포 시간을 줄이기 위한 CI/CD 구축하는 것이다.
안드로이드는 배포할 때 생각보다 간단하지만,
iOS는 아카이브 한 후 앱스토어 커넥트에 업로드 한 뒤 심사 요청까지 거쳐야하는 귀찮고 번거로운 작업들이 발생한다.
좋은 코드를 만드는 것도 좋지만, 이러한 반복적인 코드들을 자동화하여 업무의 효율을 높이는 것이 중요하다.
예전에 적용했던 fastlane 자동화 일련의 과정을 공유해보려고 한다.
iOS 배포
- Fastlane 설치
# ruby가 이미 설치되어 있다면 생략
$ brew install ruby
# Fastlane 설치
$ gem install fastlane
- iOS 설정
# /ios
$ fastlane init

- 일단 테스트 플라이트에 올릴 때 사용하기 위해 2번을 선택했다.
+ 추가) 나중에 또 추가할 수 있으니 신중하게 선택 안해도 된다.

apple ID를 입력하라고 나오는데
애플 아이디 입력 후 숫자 6자리를 입력했더니 이런 오류가 나서, 다시 n을 누르니 이중 로그인 절차를 한 번 더 거치고 완료 됐다.


- AppFile
app_identifier("your.app.identifier") # The bundle identifier of your app
apple_id("your-apple-id") # Your Apple email address
Appfile에는 app bundle id와 apple id가 포함되어 있는 걸 확인할 수 있다.
우리 팀은 애플아이디를 공유하고 있지 않고, 각자의 계정을 사용하고 있다.
각자가 배포할 때마다 apple id를 바꿔줘야하면 불편함이 생기므로 이것을 .env 를 이용해 환경변수로 관리한다.
- .env
# /ios 루트 안에 해당 파일을 만든다
$ vim ./fastlane/.env
APP_IDENTIFIER="your.app.identifier"
APPLE_ID="my-apple-id@email.com"
...
이렇게 넣어준 뒤 Appfile을 수정하자.
app_identifier(ENV["APP_IDENTIFIER"]) # The bundle identifier of your app
apple_id(ENV["APPLE_ID"]) # Your Apple Developer Portal username
- Fastfile
실제 커맨드 명령들을 만드는 파일이다.
# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane
default_platform(:ios)
platform :ios do
desc "Push a new beta build to TestFlight"
lane :beta do
# ✅ 자동으로 빌드 넘버를 증가
increment_build_number(xcodeproj: "xxxx.xcodeproj")
# ✅ 빌드할 워크스페이스와 빌드 스키마 지정
build_app(workspace: "xxxx.xcworkspace", scheme: "xxxx")
# ✅ TestFlight 업로드
upload_to_testflight(
# ✅ 업로드 후에 App Store Connect 에 올라가기 전까지 시간이 걸리는데 이걸 기다리고 싶지 않다면 true 로 설정.
skip_waiting_for_build_processing: true
)
slack(
message: "Testflight 배포 성공",
channel: "#r_frontend_deploy",
slack_url: ENV["SLACK_WEBHOOK_URL"],
)
end
error do |lane, exception, options|
slack(
message: "에러 발생 : #{exception}",
success: false,
slack_url: ENV["SLACK_WEBHOOK_URL"],
)
end
end
- SLACK_WEBHOOK_URL 설정
Slack에서 원하는 채널을 선택해서 Webhook을 설정하고, 해당 url을 통해서 요청을 보내면 해당 메세지가 전달되는 방식이다.
https://my.slack.com/services/new/incoming-webhook/ 에 들어가서 설정해보자

슬랙 채널을 하나 생성하고 추가를 하면 이렇게 웹후크 URL이 생성되는데 이를 복사하고, 설정 저장을 누르면 끝!
- TestFlight 배포 설정
원래 실행 명령어는 fastlane ios beta이다. 하지만 우리가 플랫폼을 iOS로 미리 설정해두었기 때문에 이 명령어가 실행 가능하다.
fastlane beta
TIP. 명령어를 실행하기 전에 ios에서는 앱 암호를 발급받아 환경변수로 적용을 해줘야하고, android에서는 서비스 어카운트라는 것을 만들어 접근권한을 부여해주어야 한다.
마주했던 에러
error. 앱 암호 생성 에러
FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD variable
https://support.apple.com/ko-kr/HT204397 해당 링크를 들어가 암호를 설정하자.
앱 암호를 만들고 만들어진 암호를 입력해주면 된다.
이것은 매번 fastlane을 사용할 때 자동적으로 앱 암호로 로그인하게 하기 위함이다!
Could not store password in keychain
앱 암호는 ‘xxxx-xxxx-xxxx-xxxx’ 이렇게 만들어진 암호를 붙여넣으면 된다!
이 암호로 처음에 붙이면 에러가 나는데, 두번째 성공하면 upload가 된다. 이유는 모르겠음..!!
추가적으로 릴리즈를 위한 앱의 자동 배포까지 하고 싶다면
참고한 자료 https://gyuios.tistory.com/241 에서 확인해보자
Android 배포
$ cd my-project/android
$ fastlane init
작업하기 전 체크 사항
- 구글 플레이스토어 어드민 계정 필요
- Google Play Console에 앱 등록
- Google Credential 발급
https://docs.fastlane.tools/actions/supply/ 에 들어가서 json 파일까지 발급 받아서 Appfile에 넣고 온다.
JSON Secret 설정 및 권한 부여
json 파일을 등록하고,
아래 명령어를 통해 다운받은 private key로 구글플레이스토어와 연결이 잘되는지 확인해보자.
$ fastlane run validate_play_store_json_key json_key:/path/to/your/downloaded/file.json

git에 올라가면 안되는 파일 .env나 json 파일은 .gitignore에 저장한다!
- Firebase App Distribution 추가
테스트앱을 내기 위해서 Firebase App Distribution에 올리기 때문에 Firebase App Distribution까지 자동화까지 하기로 한다.
fastlane과 Firebase App Distribution 연결
# firebase_app_distribution을 설치한다.
fastlane add_plugin firebase_app_distribution

firebase 공식 문서를 보면 action으로 firebase_app_distribution_login이 있다는 데 해당 action이 없는 것을 확인했다.
궁금해서 해당 fastlane github issue 올렸더니..
버전 0.5.0에서 부터는 firebase_app_distribution_login이 deprecated가 되고, firebase CLI를 설치 해야한다고 한다.
# Firebase CLI를 전역적으로 설치한다.
$ npm install -g firebase-tools
# 설치 후 Firebase 계정에 로그인한다.
$ firebase login
위 단계를 완료하면 Firebase CLI를 사용하여 Firbase App Distribution과 같은 다른 Firebase 서비스를 사용할 수 있다.
- Fastfile
##########################################
########## Firebase Distribution #########
##########################################
buildDir = "./build"
lane :firebase do
firebase_app_distribution(
app: ENV["FIREBASE_APP_ID"],
# 그룹명은 firebase에 있는 group alias를 사용해야한다.
groups: "tester_groups",
debug: true
)
slack(
message: "App Distribution 업로드 성공",
# 해당 slack 채널명 사용
channel: "#r_frontend_deploy",
# iOS에서도 사용했던 웹 훅을 연결해준다. android도 .env 파일을 만들어줄 것
slack_url: ENV["SLACK_WEBHOOK_URL"],
)
end
error do |lane, exception, options|
slack(
message: "에러 발생 : #{exception}",
success: false,
slack_url: ENV["SLACK_WEBHOOK_URL"],
)
end
+) 추가적으로 App Store 배포까지 해보자
desc "Deploy a new version to the Google Play"
lane :playStore do
releaseFilePath = File.join(Dir.pwd, "my-release-key.keystore")
gradle(task: "clean")
gradle(
task: 'bundle',
build_type: 'Release',
properties: {
"android.injected.signing.store.file" => releaseFilePath,
"android.injected.signing.store.password" => ENV["STORE_PASSWORD"],
"android.injected.signing.key.alias" => ENV["KEY_ALIAS"],
"android.injected.signing.key.password" => ENV["KEY_PASSWORD"]
}
)
upload_to_play_store(
track: 'production',
release_status: 'draft',
)
slack(
message: "Google Play Store 업로드 성공",
channel: "#r_frontend_deploy",
slack_url: ENV["SLACK_WEBHOOK_URL"],
)
end
releaseFilePath도 ./env 파일 내에 관리해도 된다.
현재는 /fastlane 파일 안에 my-release-key.keystore를 저장해줬는데 두 번 저장되는 꼴이 되기 때문에 경로를 잘 설정하면 될 것 같다!
후기
그동안 하던 스프린트가 마치고, 시간이 남아 자동화 배포까지 적용 해보았다.
처음에는 낯설었던 fastlane이 에러 코드만 보고도 어떤 부분이 문제인지 알 수 있을 정도로 익숙해졌다.
fastlane 자동화 시스템을 갖추는 데까지는 1~2일 소요되지만, 정말 업무 생산성을 높일 수 있는 시스템인 것 같다.
action으로 버전과 빌드 번호를 증가시키고 슬랙에도 푸시할 수 있으니 얼마나 편리한가 …!
이런 자동화 시스템을 잘 활용하여 업무 생산성을 높이기 위해 노력해야겠다.
프론트 CI/CD를 구축한 나, 제법 멋지군

'React-Native' 카테고리의 다른 글
[react-native] iOS HTTP 통신 ATS policy (0) | 2024.07.21 |
---|---|
[react-native] react-native와 webview 통신 (0) | 2023.09.05 |
[react-native] 앱 웹뷰 구글 애드센스 광고 추가하기 (0) | 2023.08.11 |
[RN 최적화] react-native-bundle-visualizer 사용기 (0) | 2023.07.28 |
react-native 렌더링 최적화 1 (0) | 2023.07.17 |