Fastlane 배포 자동화 적용 과정

 

항상 효율적으로 반복되는 시스템을 자동화하려고 하는데,

그 중 하나가 앱 배포 시간을 줄이기 위한 CI/CD 구축하는 것이다.

 

안드로이드는 배포할 때 생각보다 간단하지만,

iOS는 아카이브 한 후 앱스토어 커넥트에 업로드 한 뒤 심사 요청까지 거쳐야하는 귀찮고 번거로운 작업들이 발생한다.

 

좋은 코드를 만드는 것도 좋지만, 이러한 반복적인 코드들을 자동화하여 업무의 효율을 높이는 것이 중요하다.

 

예전에 적용했던 fastlane 자동화 일련의 과정을 공유해보려고 한다.

 


 

iOS 배포

  • Fastlane 설치
# ruby가 이미 설치되어 있다면 생략
$ brew install ruby

# Fastlane 설치
$ gem install fastlane
  • iOS 설정
# /ios
$ fastlane init
iOS fastlane init시 나오는 화면 (4가지 중 1개 선택)
  • 일단 테스트 플라이트에 올릴 때 사용하기 위해 2번을 선택했다.
    + 추가) 나중에 또 추가할 수 있으니 신중하게 선택 안해도 된다.

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

 
로그인 성공 시 Appfile과 Fastfile이 생성된다.
  • 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
Google Play Store에 연결 성공

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를 구축한 나, 제법 멋지군

+ Recent posts