본문 바로가기
iOS

fastlane 적용하여 앱스토어 배포까지!

by vapor3965 2021. 9. 5.

목차

     

    목차

       

      그동안 듣기만 했던 Fastlane을 드디어 적용해보기로 했다.

      fastlane은 iOS, Android 앱의 CD ( Continuous Deploy ) 의 대표적인 툴이다. 

      CD는 지속적 배포로써, iOS에서는 자동화 배포( 앱스토어, testFlight에 ) 를 도와준다. 

       

      배포해본 사람은 알겠지만..

      배포하고 앱스토어에 제출하는 것 까지 꽤 시간이 걸리고, 그동안의 과정들이 한번에 진행되는게 아니라 계속 확인하면서 클릭 클릭 해주어야 한다. 

      하지만 fastlane을 이용한다면 일련의 과정들을 명령어 하나로만 실행하여 완료될때까지 신경쓰지 않아도 된다! 

       

       

      크게,

      Fastlane을 설치하고,

      Fastlane 설정,

      testflight에 배포

      app store에 배포 하는 방법등을 알아볼 예정이다. 

       


       

       

      fastlane 설치

      우선,

      https://docs.fastlane.tools/getting-started/ios/setup/

       

      Setup - fastlane docs

      Getting started with fastlane for iOS Setup Xcode for fastlane xcode-select --install Installing fastlane fastlane can be installed multiple ways. The preferred method is with Bundler. fastlane can also be installed directly through with Homebrew (if on ma

      docs.fastlane.tools

      위에 나와있는 대로 설치한다. 

       

      설명대로 fastlane은 다양한 방법으로 설치할 수 있는데 Bundler가 가장 추천하는 방법이라고 한다. 

      다른 방법은  Ruby, Homebrew를 통해서 가능하다. 

       

      Bundler가 좋은 이유는, 명확하게 fastlane 버전을 명시해주고, 또한 fastlane의 실행속도가 더 빠를 것이다.  라고 한다! 

       

      아래 명령어로 bundler를 설치하고, 

      gem install bundler

       

      fastlane을 사용할 프로젝트의 최상단에 Gemfile 을 만드는데, 파일안에는 아래를 포함하도록 한다. 

      source "https://rubygems.org"
      
      gem "fastlane"

      그다음에는 아래 명령어를 입력해서 fastlane을 설치한다! 끝! 

      bundle update

       

      bundler로 설치했으니, fastlane 실행은 다음과 같이 실행하면 된다. 

      bundle exec fastlane [lane]

       

      CI에서는 bundle install을  첫 빌드 스텝에 추가한다. 

      fastlane을 업데이트할 때는 아래 명령어를 실행한다. 

      bundle update fastlane

       

       


      fastlane 설정하기 

       

      다시 프로젝트 최상단으로 이동한다음, 아래 명령어를 실행한다. 

      fastlane init

       

      그러면 어떤 방식으로 할건지 1,2,3,4가 나타나는데, 우선 4번을 선택했다.

      어떤 방법으로 설정하느냐에 따라 생성되는 파일들이 달라질 수 있다. 

       

      만약, 앱스토어에 존재하는 앱 metadata를 다운로드하는 걸 골랐다면, 

      아래와 같이 metadata들이 생성될 것이다. 

      metadata는 이제, 앱스토어에 다음 버전을 출시하기 위해서는 스크린샷이랑, 업데이트내용, 등을 작성하는데 그런 파일들이 저장되는 폴더인듯 하다. 

       

      만약 설정하는 도중에,  애플 서버의 연결을 요구한다면 인증이 필요하다.  ( 근데 나는 4번을 해서 그런지 안 떴다 ) 

      그러한 인증은 아래에서 확인할 수 있다.

      https://docs.fastlane.tools/getting-started/ios/authentication/

       

      위 링크에서는, fastlane의 실행은 인증이 필요한 애플 서비스와 상호작용하게 된다.

      여기서는 애플서비스에 연결하는 4가지 방법을 소개한다.

      첫번째는 App store Connect API Key이다.

       

      두번째는 Two-step or two-factor authentication이다. 

      이건 앱 스토어 커넥트 API에 의해 아직 지원되지 않는 실행에 대해서는 Apple ID와 함께 필요하다. 

       

      세번째는 Application-specific passwords로, 

      앱스토어커넥트, 테스트플라이트에 업로드 하는 경우에 생성하는 방법이다. 

       appleid.apple.com/account/manage

      여기로 들어가서 앱 암호를 생성하여 이용한다. 

      • 보안 - 에서 암호 생성을 통해 암호를 생성하고, 
      • 해당 암호를 
      • fastlane폴더안에 .env  라는 파일을 만들어서 FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD = 암호 를 작성해준다 

       

      .env파일은 환경변수로 이를 이용하여 다른 파일에서도 값을 불러올 수 있다.

      .env파일에 키와 값의 형태로 저장하고, 

      Appfile 을 열어서  아래와 같이 ENV[ 키 ] 로 지정한다면 .env에 있는 값을 불러오게 된다. 

      app_identifier(ENV["APP_IDENTIFIER"])
      apple_id(ENV["APPLE_ID"])

       

       

       


       

      TestFlight에 제출하기 

      과정에서 코드사이닝에 대해 처리하는 방법도 알아야하는데, 우선 쉬운 내용부터 먼저 설명하겠다 

       

      Fastline파일로 가서 아래와 같은 비슷한 형식으로 작성하면 된다.  

      :beta 는 이제 작성한 코드의 이름을 beta라고 짓는다는 뜻이다. 

      ( 아래는, beta 이름의 함수로, 앱을 빌드하고, testflight에 업로드 하겠다는 뜻이다!! ) 

      ( 함수안에 각각의 액션들을 열거하면 된다 )

      ( 각 줄들을 Action이라고 부른다. )  

      lane :beta do
      
        build_app(scheme: "MyApp")
        
        upload_to_testflight
      
      end

       

      Action에는 파라미터가 담길 수도 있다.

      그래서 궁금한 파라미터들은 fastlane docs에서 검색하면 나온다. 

       

       

       

      그래서 위는 다음과 같이 실행할 수 있다. 

      bundle exec fastlane beta

       

      build_app에 사용된 scheme파라미터는 xcode scheme을 말한다. 

      scheme을 지정안하면 scheme리스트가 나오면서 선택하라고 뜬다.

      매번 같은 scheme으로만 배포한다면, 미리 파라미터에 지정하는게 좋겠다. 

       

       

       

      또 다른 장점으로는, 액션에는 빌드 넘버를 증가시킬 수도 있다...! 

      빌드넘버는 Target의 Build를 말한다. 

      이제 이 빌드번호가 테스트플라이트에 올리면, 

      Version과 함께, 빌드 번호도 같이 나타난다. 

      그래서 아래와 같은 액션으로 빌드넘버를 변경할 수도 있는데,  increment_build_number

      latest_testflight_build_number 액션을 통해서 가장 최근 testflight의 빌드넘버를 가져와 + 1 할수도 있다! ( 대박 ) 

      ( 그래서 빌드넘버는 정수로 하는게 좋나보다. 그동안 날짜형식으로 20190502.01 이렇게 했었는데.. )  

      increment_build_number({
        build_number: latest_testflight_build_number + 1
      })

       

       

       

      또 다른 장점으로는, 액션에는 버전 넘버를 증가시킬 수도 있다.

      만약, 이전에, 2.1.0 버전을 앱스토어에 제출하고, 성공적으로 업데이트됐고,

      버전넘버를 고치지 않고 그대로 testflight에 올리게 되면, 에러난다. 이미 2.1.0은 닫혔기 때문에, 올려줘야한다. 

       

      testFlight을 올리기 전에 다음과 같은 액션으로 버전넘버도 증가시킬 수 있다. increment_version_number

      increment_version_number(
        version_number: "2.1.1" # Set a specific version number
      )

       

       

      그리고 또 다른 장점으로는 ㅎ 슬랙에 푸시할 수도 있다. 

      여기서 slack액션의 옵션들을 확인할 수 있다.

      실행 결과를  슬랙에 보낼 수 있는데, 

      우선 슬랙에서 앱 - Incoming WebHook을 추가한다. 

      그러면 선택한 채널에 대한 webHook URL을 준다. 

      그 URL을 slack_url 파라미터에 지정하면 된다.

       

      터미널로 우선 테스트 해볼 수 있다. 

      fastlane run slack message:"테스트입니다." slack_url:https://hooks.slack.com/services/추가적인url

      그럼 성공했다는 내역과 함께 슬랙에도 뜬다

       

       

       

       

      일단 쉽고 흥미있는 얘기부터 먼저 꺼냈고...

      TestFlight와, AppStore에 제출할때는, 

      그 과정에서 Codesigning이 필요한데,  여러 방법이 있다. 아래에서 확인할 수 있다.

      https://docs.fastlane.tools/codesigning/getting-started/

       

      우선 CodeSigning에 대한 개념은 아래 블로그에서 잘 설명해주셨습니다.

      https://medium.com/jinshine-기술-블로그/코드사이닝-인증서-프로비저닝-프로파일이란-2bd2c652d00f

       

      CodeSigning이란?

      애플인증서와,  프로비저닝 프로파일을 갖추는 과정을 말한다. 

       

      본래 애플만이 애플디바이스에 앱을 실행하도록 허용하는데, 

      이를 애플인증서를 통해서 개발자가 Apple 대신 앱을 실행할 수 있는 권리를 허용하도록 해주는 것!

      프로비저닝 프로파일 디바이스가 나를 신뢰하는지를 확인하기 위한 파일!

      즉 디바이스에 설치할 앱이 안전한지를 확인하는 거죠. 

      프로비저닝 프로파일을 만들기 위해서는, App ID, 애플 인증서,  디바이스의 UUID가 필요하다. 

      그러면 App ID ( 앱스토어에 등록될 Bundle ID) 를 만들기 위한 과정도 필요하죠. 

       

      여튼, 이러한 과정들을 수작업으로 개별적으로 만들고 할 수 있다.

      ( 수작업으로 하는 방법도 위의 블로그에서 잘 설명해주셨습니다 ) 

       

      또한 Xcode내에서 자동적으로 코드사이닝을 만들어줄 수도 있다. 

       

      여튼! 위의 개념들을 종합해보면 디바이스에 앱을 설치하는 경우와 앱을 배포할때도, 프로비저닝 프로파일이 필요하다는 걸 알 수 있다.

       

      ( 저는 지금까지 Automatically manage signing으로 체크하고 배포를 해왔었는데요, 

      아무래도 앞으로 취업을 해서 협업을 하게 된다면 ... 뭔가 좋은 방법은 아니라고 생각이 되네요. )

       

       

      자, 그럼  fastlane에서 자동화 배포를 하기 위해서 코드사이닝을 어떻게 할까?

      fastlane에서 소개하고 있는 코드사이닝의 방법은,  크게 4가지 방법이 있다.

       

      1번째 방법은 match를 이용하는 방법.( 이 방법을 추천한다고 합니다 ) 

      private key와 인증서를 깃 리포에 저장하여, 다른 팀원들가 같이 사용하는 방법이다. 

      이를 통해서는 많은 팀원들이 있고, 새로온 팀원이 손쉽게 적용할 수 있다는 장점이 있다. 

       

      2번째 방법은 cert, sigh를 이용하는 방법.

      만약 매번 갖고있는 certificate를 폐기하지 않으면서 자동화된 셋업을 하고 싶다면, cert, sigh가 적합하다

       

      3번째 방법은Automatically manage Signing feature를 이용하는 방법.

      이 방법은 항상 안전하게 잘 작동하리라고 보장하지 않는다.

       

      4번째 방법으로는 직접 하는 방법.

       

       

      다른 분들의 블로그를 보면 match를 많이 사용하시는데, ( 협업하는 곳에서는 match가 좋을 것 같아요. ) 

      ( match도 해볼려고 했지만 뭔가...어려워서 포기! ) 

      저는 이번에는 직접 인증서와 프로비저닝 파일을 만들고, 4번째 방법을 이용해보겠습니다. 

       

      정말 간단하다. 배포에 필요한 Distribution 용 프로비저닝 파일을 각 target에 매핑만 시켜주면 된다.

        #... 생략 
        build_app(
          export_method: "app-store",
          export_options: {
            provisioningProfiles: { 
              "com.example.bundleid" => "Provisioning Profile Name",
              "com.example.bundleid2" => "Provisioning Profile Name 2"
            }
          }
        )
        #... 생략

       

       

       

      그래서 일단 적용해본 코드는 다음과 같다. 

      ( 중간에 에러가 발생한다면 이것도 슬랙에 푸시하도록 하는 코드도 추가했다. - 블로그 참고했다.

       내 앱은 테스트하는 사람이 없으므로 build_app - configuration을 Release로 해두었다 

      platform :ios do
        desc "build app and upload to testflight"
        lane :beta do
          increment_version_number(
              version_number: "2.1.1" # Set a specific version number
          )
          
          increment_build_number(
              build_number: latest_testflight_build_number + 1
          )
          
          build_app(
            scheme: "EasyToDoList",
            configuration: "Release",
            export_method: "app-store",
            export_options: {
              provisioningProfiles: { 
                "com.example.bundleid" => "Provisioning Profile Name",
                "com.example.bundleid2" => "Provisioning Profile Name 2"
              }
            }
          )
          
          upload_to_testflight
          
          slack(
            message: "Testflight 배포에 성공했습니다!",
            slack_url: "https://hooks.slack.com/services/T"
          )
        end
        
        error do |lane, exception, options|
          slack(
            message: "에러 발생 : #{exception}",
            success: false,
            slack_url: "https://hooks.slack.com/services/T"
          )
      
        end
      end

       

       

       

      이제 이걸 아래와 같이 실행해보면,  

      bundle exec fastlane beta

       

      계정 증명에 대한 암호를 입력해야한다.  ( 나는 fastlane세팅에서 4번을 선택해서 그런가 이때 떴다 ) 

      이건 환경변수로 만들어 둘 수 있다고 한다. 

      비밀번호가 맞는다면, 6자리 확인코드도 입력해야한다. 

       

       

       

      그럼 시간을 기다리다 보면!!

      에러가 뜨지 않는다면 이렇게 뜬다!

      ( fastlane이 나의 21분을 아껴줬다...ㅎ ) 

       

       

       

       


       

      앱스토어 배포하기 

       

      마찬가지로, 위에서 했던것처럼 Fastfile안에서 명령어들을 입력해서 실행함수를 작성해서 배포한다. 

       

      이미 testflight 제출하는 부분에서 대부분의 개념은 설명한 것 같아서 여기는 비교적 쉽다(?)

       

      이제 필요한 액션들을 나열하고, 

      빌드 액션을 추가하고, 

      앱스토어에 제출한다는 액션을 추가하면 된다. 

      upload_to_app_store

      해당 액션에는 굉장히 많은 파라미터가 있으니, 여기를 참고하면 좋다 

      잠깐봤는데, metadata를 업데이트하고, 제출만할지, 또는 제출하고 리뷰도 할건지, 리뷰가 잘 됐다면 바로 릴리즈할건지, 등등... 굉장히 많다. 

       

      그리고 블로그에서 좋은 파라미터를 봤는데, 

      특정 버전을 직접 입력해주고 싶은 경우에,  아래와 같이 입력하면 ,

        lane :release do |options|
          if options[:v] 
            increment_version_number(
                version_number: options[:v]
            )

      다음과 같이 입력해서 실행할 수 있다! 

      그러면 버전넘버도 2.1.1로 올라간 상태로 된다! 

      bundle exec fastlane release v:"2.1.1"

       

      우선 테스트로, 아래와 같이 파라미터를 지정해서 실행해보면 

            upload_to_app_store(
              app_version: options[:v],
              submit_for_review: false,
              force: true,
              automatic_release: false,
              skip_screenshots: true,
              skip_metadata: true
            )

       

      앱스토어에 2.1.1 버전 생겼다!! 신기!! ( 원래 2.1.0 판매 준비됨 만 있었는데! )

      submit_for_review를 false로 함으로써, 업로딩 하자마자 바로 제출한다고 하지 않았다.

      그러므로 먼저 이게 생성되고, 테스트플라이트에 나중에 업로드 된다. 

      수동으로 테스트플라이트에 검사된 후에 그 빌드를 추가해주고, 심사를 위한 제출을 클릭해야한다. 

       

       

       

      그리고 이번에는 정말 심사까지 하기위해 단번에 제출하려고, 아래와 같이 고쳐서 실행해봤다. 

            upload_to_app_store(
              app_version: options[:v],
              submit_for_review: true,
              force: true,
              automatic_release: true,
              skip_screenshots: true,
              skip_metadata: true
            )

       

       

      첫번째 에러 발생 - Export compliance is required to submit

      하지만! 아래와 같이 뜨면서 스스로 제출하지 못했다.( ? ) 

      ( 에러긴 하지만 문제가 없는 에러랄까.. 어차피 해당 항목만 체크하고 심사를 위한 제출 버튼만 눌러주면 되니..

      하지만 이건 기대하는 자동화의 80프로밖에 되지 못하니, 고쳐보자 ) 

      신기하게도, 제출하고자 하는 빌드에는 추가됐다! 

       

       

      이 경우에는 Info.plist에 추가하거나,

          <key>ITSAppUsesNonExemptEncryption</key>
          <false/>

      upload_to_app_store 액션에 다음과 같이 추가해도 된다. 

      submission_information: { export_compliance_uses_encryption: false }

       

      나는 Info.plist에 추가했고!

      다시 fastlane을 실행시켜본다. 

       

       

       

       

      두 번째 에러 발생 : Use of Advertising Identifier (IDFA) is required to submit

      Add information to the :submission_information option...

       

      흑,   이번에는 기대한대로 수출규정 문서를 알아서 처리해줬고, 빌드에도 잘 들어가있다!

      하지만 에러가 떴다! 

       

      IDFA에 대한 정보도 제출할 때 필요하다고 한다. 

      IDFA에 대한 설명은 Zedd님이 아주 잘 설명해주셨어요. 또 왜 필요한지도! 

       

      분명 내 기억에는 작년에 배포할때는 심사를 위한 제출 누르면 IDFA에 관한 항목들을 설정했었는데 

      몇일 전에 배포할 때는 안뜨던데... ( 물론 내 앱이 IDFA를 사용한다라고 프로젝트에 추가하지도 않긴했다 ) 

       

      여튼,  아래와 같이 upload_to_app_store 액션에 추가해준다. 

      submission_information: { add_id_info_uses_idfa: false }

       

       

      3번째 실행 !!

       

      성공!!

       

      이번에는 심사를 위한 제출 까지 fastlane이 스스로 눌러줬다!! 

       

      성공한 코드는 다음과 같았다. 

        lane :release do |options|
          if options[:v] 
            increment_version_number(
                version_number: options[:v]
            )
            increment_build_number(
                build_number: latest_testflight_build_number + 1
            )
            build_app(
              scheme: "EasyToDoList",
              configuration: "Release",
              export_method: "app-store",
              export_options: {
                provisioningProfiles: { 
                  "com.example.bundleid" => "Provisioning Profile Name",
                  "com.example.bundleid2" => "Provisioning Profile Name 2"
                }
              }
            )
            upload_to_app_store(
              app_version: options[:v],
              submit_for_review: true,
              force: true,
              automatic_release: true,
              skip_screenshots: true,
              skip_metadata: true,
              submission_information: { add_id_info_uses_idfa: false }
            )
            slack(
              message: "App store 배포에 성공했습니다🎉!",
              slack_url: "https://hooks.slack.com/services/T"
            )
          end
        end
        error do |lane, exception, options|
          slack(
            message: "에러 발생 : #{exception}",
            success: false,
            slack_url: "https://hooks.slack.com/services/T"
          )
        end

       

       

       

       


      앱스토어 업데이트 사항 변경하기 

      위 뿐만 아니라 다음에 출시하고자 하는 버전들에 대해서 입력할 수 있는 칸들이 여러개 있다. 

       

      이러한 것들을 metadata라고 부르는데, 이또한 fastlane을 이용해서 업데이트 시킬 수 있다. 

       

       

      deliver를 통해서 metadata들을 앱스토어커넥트에 업로드 한다고 한다. 

       

      우선, 기존 버전에 있는 내용들을 가져와보겠다. 

      fastlane deliver init

       

      이렇게 하면 

      fastlane/metdata/ 에 관련정보들이 생긴다! 

      실제로 txt파일들을 눌러보면 이전 버전에 쓰인 내용들이 담겨있는걸 볼 수 있다. 

       

      그래서 이번에는 2.1.2버전을 만들면서, 아래와 같이 직접 업데이트 사항을 작성해보고, 실제로 이게 반영이 되는지 보려고 한다!

       

       

      우선 submit_for_review와 automatic_release를 false로 두고

      skip_metadata를 false로 두었다. 

            upload_to_app_store(
              app_version: options[:v],
              submit_for_review: false,
              force: true,
              automatic_release: false,
              skip_screenshots: true,
              skip_metadata: false,
              submission_information: { add_id_info_uses_idfa: false }
            )

       

      두구두구 !! 

      와우 성공!!

       

       


      후기

      처음에는 굉장히 낯설고 어려웠는데 계속 찾아볼 수록 감이 오고 그랬다. 

      덕분에 코드사이닝의 대한 개념도 조금 알 수 있었고, 좋은 시간이였다.

       

      결과적으로 단 한줄의 명령어로,

      아카이브 - 클릭 클릭 - 앱스토어 커넥트에 업로드 - 앱스토어 버전추가 - 앱스토어 해당 버전으로 옮겨주고 - 앱스토어 심사를 위한 제출까지 눌러준다. 

      정말 신세계다!

      이제는 더이상 컴퓨터앞에서 기다리면서 클릭해줄 필요가 없어졌다... 

      ( 이제 이렇게 자동화란것에 관심을... ) 

       

      그리고 문서에 보면 굉장히 많은 액션과 파라미터가 많기 때문에 이보다 훨씬 다양하게 사용할 수 있겠다. 

       

      추가적으로... 환경변수를 이용하여 좀 더 유연하게 fastlane을 작성할 수 있다. 

      아래에서 확인할 수 있다.

      https://docs.fastlane.tools/advanced/other/

       

      Fastfile이 있는 같은 디렉토리에 .env 파일을 생성한다. 

      환경변수를 이용하면 fastlane 코드를 작성할 때 환경변수를 이용할 수가 있다. 

       

       

       

      지금은 로컬에서만 fastlane을 이용했는데, 

      아래와 같이 굉장히 많은 CI와 통합할 수 있다고 한다. 

      아마 실무에서는 아래와 같은 CI와 통합해서 사용할 것 같다. 

       

       

       


      앱스토어 커넥트 까지 업로드하는 과정 

       

       

       

       

       

       

       

       

       

       


      참고

       

      https://docs.fastlane.tools

       

      fastlane docs

      fastlane fastlane is the easiest way to automate beta deployments and releases for your iOS and Android apps. 🚀 It handles all tedious tasks, like generating screenshots, dealing with code signing, and releasing your application. You can start by creati

      docs.fastlane.tools

      https://medium.com/hcleedev/ios-배포-자동화-fastlane-시작부터-적용까지-3d9107cdc3b4

       

      iOS — 배포 자동화, Fastlane 시작부터 적용까지

      Fastlane의 설치 방법부터 인증 방법, beta, release 예시까지 알아보자

      medium.com

       

       

      댓글