호댕의 iOS 개발

[Fastlane] Fastlane Match 도입해보기 (계속된 삽질) 본문

Software Engineering/iOS

[Fastlane] Fastlane Match 도입해보기 (계속된 삽질)

호르댕댕댕 2024. 4. 19. 17:08

 

iOS에서 앱을 배포하기 위해선 Code Signing이 필수적이다. 

이를 통해 어떤 사람이 해당 앱에 서명을 했는지 식별하고, 서명이 된 이후에는 앱에 변경 사항이 없다는 것을 보증해준다. 

 

(서명은 앱 빌드 & 아카이빙 시 됩니다)

https://help.apple.com/xcode/mac/current/#/dev3a05256b8

 

https://help.apple.com/xcode/mac/current/#/dev3a05256b8

To see this page, you must enable JavaScript. Pour afficher cette page, vous devez activer JavaScript. Zur Anzeige dieser Seite müssen Sie JavaScript aktivieren. このページを表示するには、JavaScript を有効にする必要があります。

help.apple.com

 

즉, 앱을 배포했다면 해당 앱은 해당 버전에선 더 이상 변경 사항이 없다는 것을 보증한다. 그래서 우리는 버그를 만나게 되면 수정 후 다시 심사를 올리고 배포를 하게 되는 것이다. 

 

이를 위해선 Signing Certificate가 사용된다. 

 

이는 Xcode Project의 Target에서 있는 Signing & Capabilities 탭에서 확인해볼 수 있다. 

요게 제대로 되어 있지 않으면 빌드 시 컴파일 에러가 발생한다. 

(요건 가끔 예제 코드를 받아서 실행시키다보면 만나게 됩니다)

 

하지만 이런 인증서는 배포의 경우 최대 3개까지만 사용이 가능하다.

 

즉 프로젝트를 진행하는 인원이 3명이 넘게 되면 이제 인증서에 대한 관리가 빡세지는 것이다. 

이외에도 모두가 인증서를 각각 가지고 만료 일자가 되면 갱신도 해줘야 한다. 

 

물론 갱신 같은 작업은 엄청 간단하기 때문에 엄청나게 부담은 아니다. 다만 팀이 커지게 되며 Certificate / Provisioning Profiles를 개별적으로 관리하는 것은 분명한 한계를 지닌다. 

(위에서 봤던 인증서 개수의 제한이 가장 명확한 한계점)

 

이런 상황에서 Fastlane을 사용한다면?

Fastlane match를 사용하면 일단 1개의 certificate와 provisioning profile을 공유해서 사용할 수 있다. 

이렇게 하면 팀 전체가 Certificate와 Provisioning Profile의 싱크를 맞출 수 있고, 여기서 발생할 수 있는 문제를 최소화할 수 있다. 

(다만 나는 설정하는데 꽤나 많은 시간이 걸려서 문제가 최소화된 건지는 잘 모르겠다 ㅎㅎ...)

 

Fastlane에선 certificate와 provisioning profile을 저장하는 공간을 3가지로 제공하고 있다. 

  • Google Cloud
  • Amazon A3
  • Git Repository

 

여기서 나는 가장 많이 사용되는 Git Repository를 활용했다. 

 

그림으로 보면 이런 식으로 Git Repository를 통해 팀이 사용하는 Certificate와 Provisioning Profile을 관리할 수 있는 것이다. 

 

https://codesigning.guide/

 

Code Signing Guide for Teams

A new approach to code signing A best practices guide on how to manage certificates and provisioning profiles in your development team. Wait, what is code signing? Code signing is required on iOS when distributing your app to customers. It assures that you

codesigning.guide

 

Fastlane에선 아래와 같은 기능을 사용할 수 있다고 말하고 있다. 

  • 🔄 Git을 사용해서 모든 팀 멤버들에게 iOS / macOS 키와 profile의 싱크를 맞출 수 있음
  • 📦 인증서와 profile을 생성하고 저장하는 모든 어려운 작업을 처리
  • 💻 새로운 기기에서도 빠르게 Code signing을 설정할 수 있음
  • 🎯 여러 target과 bundle identifier가 있는 앱을 작동시킴
  • 🔒 다른 서드파티 서비스 없이 file과 Git repo를 관리할 수 있음
  • ✨ Provisioning profile은 항상 일치하는 certificate와 매치가 됨
  • 💥 만료되거나 유효하지 않은 경우 존재하는 profile / 인증서(certificate)를 쉽게 리셋시킬 수 있음
  • ♻️ --force 옵션을 사용해 모든 장치에서 provisioning profile을 자동으로 갱신
  • 👥 다수의 Apple 계정과 팀을 지원할 수 있음

 

그렇다면 어떻게 사용할까?

지금까지 왜 Fastlane match를 활용해야 하는지와 사용했을 때 얻을 수 있는 이점에 대해 살펴봤다. 

하지만 사용할 수 없다면 앞선 내용들은 모두 무용지물이니 요 부분이 가장 중요할 것이다. 

 

요 작업을 하면서 대부분의 사람들은 docs에 나온대로 뚝딱뚝딱 잘 만 하던데 나는 기존 프로젝트에 도입을 해서 그런지, 내가 이런 인프라 설정이 약한 것인지는 모르겠지만... 정말 많은 시행착오를 겪었다. 

(아직도 완전히 해결된 것은 아니다... 이게 어떤 사람은 에러 없이 잘 되는데 어떤 사람은 또 안되는 경우도 있고 해서...)

 

기본적인 Fastlane 설치 방법은 fastlane Docs에 잘 나와있긴 하다.

 

Setup - fastlane docs

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

docs.fastlane.tools

 

 

그리고 기본적으로 fastlane에 대한 기본 셋팅은 이전 프로젝트에 되어 있어서 GemFile / FastFile, AppFile, MatchFile은 설정이 되어 있었다. 

 

 

기본적인 과정은 공식 문서를 참고해주세요.
아래는 굵직하게 이슈가 있거나 정리해봄직 한 부분을 정리했습니다

새롭게 공용 Certificate & Provisioning Profile을 생성


1. Fastlane 설치

fastlane 설치는 아래 명령어로 간단하게 진행했다. 

brew install fastlane

 

그리고 기분좋게 fastlane match init을 해서 match 설정을 시작하려 하자마자 에러 발생 🚨🚨

 

2. 터미널에 Fastlane match init 명령어 호출

이제 match를 시작하기 위해 요 명령어를 호출했다.

하지만 시작부터 에러 발생 ㅎㅎ.... 

 

🚨 fastlane match init 시 발생 에러  (Unable to locate Xcode. Please make sure to have Xcode installed on your machine)

Xcode를 현재 2개 사용 중이라 발생했던 에러였다. 

 

15.3에선 Archive로 ipa 파일 추출할 때 강제 종료되는 버그가 있어서 15.2로 다운그레이드 후 다른 프로젝트와 Swift Tool 버전이 맞지 않아 15.3도 따로 사용하고 있었는데 요것 때문에 발생한 에러였다. 

 

Unable to locate Xcode. Please make sure to have Xcode installed on your machine 해결 방안

Xcode > Preference > Location에서 현재 프로젝트에서 사용 중인 Xcode로 변경해주면 에러 해결

여기서 Command Line Tools를 현재 사용 중인 버전에 맞게 골라주면 된다. 

 

여기가 15.3 버전 Xcode로 되어 있어 문제가 발생한 것이었고 이렇게 수정해주고 나면 문제없이 명령어 실행이 됐다. 

이후 나오는 것은 일단 자신의 상황에 맞는 옵션 선택만 해주면 잘 됐다.

 

(저장 위치, 레포 주소 요런 것들을 잘 적어주시면 됩니다)

 

3. AppFile 확인

Appfile에선 아래와 같은 내용들을 작성한다. 

  • app_identifier : 현재 앱에서 사용 중인 Bundle Identifier
  • apple_id : 현재 공용으로 생성한 Apple 계정
  • team_id : Apple Developer에 로그인 후 밑으로 쭉 내리면 멤버십 세부 사항에 있는 팀 ID

  • itc_team_id : AppStoreConnect에 로그인 후 (링크)를 누르면 확인이 가능합니다. 이렇게 하면 JSON 형식의 데이터를 확인할 수 있는데 여기서 contentProviderId를 확인하면 됩니다.

4. 기존 Provisioning Profile 삭제

최대 3개까지만 사용이 가능하고 이제 더 이상 개인 계정이 아닌 공용 계정을 사용할 예정이기 때문에 기존 Provisioning Profile을 제거하는 것을 권장하고 있습니다. 

 

이는 아래 명령어를 사용하면 아주 쉽게 삭제가 가능하다. 

fastlane match nuke development // 개발용
fastlane match nuke appstore // 배포용

흠... 삭제는 아주 쉽게 가능하다. 

 

여기서 username을 묻는데 요건 공용으로 만든 개발자 계정을 입력해주면 된다. 

그리고 사용할 passphrase(비밀번호)를 묻는다. 요건 추후 팀원들이 인증서와 Provisioning Profile을 불러올 때에도 사용이 되니 꼭 잘 기억해놓자!!!

 

그런데 비밀번호를 입력할 때 문제가 생겼다. 

 

bad decrypt
Couldn't decrypt the repo, please make sure you enter the right password!

 

아니 이름만 보면 무슨 비밀번호가 잘못 됐다는 것인데 아무리 해봐도 안된다.

 

🚨 Couldn't decrypt the repo, please make sure you enter the right password! 해결 방안

저번에 한 번 fastlane match를 도입하다가 계속 안돼서 방치하던 레포를 그대로 사용했더니 발생한 에러였다. 이유는 모르겠지만 저번과 동일한 비밀번호를 사용하면서 이 문자열을 입력했는데 계속 저런 에러가 발생했고 아예 레포를 지우고 다시 동일한 이름으로 레포를 생성했더니 해결이 됐다. 

 

이렇게 기존 Provisioning Profile도 삭제 완료!

 

5. 여러 app identifier 사용 중인 경우 이에 대한 대응 (+ multi target)

현재 앱은 OneSignal Extension / Widget을 사용하고 있는 Multi target 앱이었고, 거기다가 Debug / Release 따로 app identifier를 쓰고 있다보니 조금 더 복잡했다. 

 

여기서 target / identifier에 맞게 인증서를 생성해야 했다.

 

https://docs.fastlane.tools/actions/match/#handle-multiple-targets:~:text=Handle%20multiple%20targets

 

match - fastlane docs

type Define the profile type, can be appstore, adhoc, development, enterprise, developer_id, mac_installer_distribution, developer_id_installer development

docs.fastlane.tools

 

요 부분에서도 약간 막혔지만 이건 공식 문서에 설명이 나와있었다. 

 

인증서를 생성하는 명령어는 다음과 같다. 

fastlane match development // Debug
fastlane match appstore // Release

하지만 이렇게 하면 AppFile에 등록한 Bundle Identifier에 해당하는 인증서만 생성된다. 

 

즉 현재 앱에선 Debug와 Release의 Bundle Identifier가 다른데 동일하게 인증서가 생성되는 것이다. 

이렇게 되면 안된다!!

 

fastlane match appstore -a tools.fastlane.app

그럴 땐 요런 식으로 -a를 붙이고 해당하는 Bundle Identifier를 적어주면 된다. 

 

이렇게 하면 일단 새로운 공용 계정 Certificate와 Provisioning Profile을 등록할 수 있다. 

 

6. Xcode 설정 변경

글 초반에 말했듯  Xcode Project의 Target에서 있는 Signing & Capabilities 탭에서 Certificate와 Provisioning Profile에 대한 설정을 할 수 있다. 

 

  1. Automatically manage signing 체크 해제
  2. 적합한 Provisioning Profile 선택

 

Xcode 설정 변경도 추가로 해줘야 하는데 이는 새로운 컴퓨터에서 추가한 Certificate와 Provisioning Profile을 받을 때 좀 더 문제가 생겼고 개선한 부분이 있어 뒤에 조금 더 추가적인 내용이 존재한다. 

 

이렇게 빌드하니 잘 됐기 때문에 흠.. 생각보다 쉽게 됐는데 생각했다.. 하지만 아직 갈 길이 멀었다.

 

 

다른 컴퓨터에서 인증서를 받고 이에 대한 처리


1. Certificate & Provisioning Profile을 Git 레포에서 불러오기

불러오는 명령어 자체는 간단하다. 

fastlane match development --readonly // Debug
fastlane match appstore --readonly // Release

--readonly를 붙이지 않으면 새로운 인증서를 다시 생성하기 때문에 이미 생성이 됐다면 read only로 불러와야 한다. 

 

🚨 'Error Cloning certificates repo, please make sure you have read access to the repository you want to use' issue 에러 발생

이 경우 토큰이 없어서 접근하지 못하는 문제이다. 

 

파란색으로 나온 부분처럼 다시 레포를 clone한 뒤 username(이전에 설정한 공용 ID를 사용)와 passphrase(Github 상에서 token 재생성 후 확인)을 적어주니 정상적으로 Git Repository에서 Certificate와 Provisioning profile을 받아올 수 있었다.

 

🚨 'wrong final block length' and 'password has been deleted' issue 에러 발생

항상 발생하는 에러는 아닌 것 같았다. 2개의 다른 컴퓨터에서 시도를 했는데 1개는 정상적으로 넘어갔고, 다른 1개만 문제가 발생했다. 

 

MatchFile에 환경 변수를 설정하여 아예 비밀번호 관련 입력을 하지 않도록 했다.

 

username("개발자 계정 입력")

ENV['MATCH_PASSWORD'] = "이전에 입력했던 passphrase 입력"

이렇게 해놓으면 MATCH_KEYCHAIN_PASSWORD라는 키값으로 passphrase가 입력된다. 

 

그리고 ENV의 키 값을 넣을 때 작은 따옴표를 써야 했다. 

공식문서에서도 작은 따옴표를 사용하고 있어서 요게 맞는 것 같다. (구글링하다보면 가끔 큰 따옴표를 쓰는 경우가 있던데... 잘못 쓴건가..)

일단 요렇게 MatchFile을 통해 문제는 해결! 

 

공식문서에서는 암호화를 권장하긴 했는데 일단 올라가는 Github 레포지토리가 애초에 private으로 되어 있어서 크게 문제가 없을 것으로 판단했고 일단 저렇게 작업을 해서 해결을 했다. 

 

 

https://ios-development.tistory.com/1164

 

[fastlane] fastlane 환경변수 사용 방법 (.env.default 사용하여 가장 간단한 match 사용방법, Certificate 갱

Fastlane match란? Certificate, Provisioning Profile을 특정 git 레포에 저장해놓고 개발자들 사이 or ci/cd 때 쉽게 관리할 수 있는 기능 mathc명령어를 통해 terminal에서 Apple 개발자 사이트에 접속하여 Certificate

ios-development.tistory.com


🚨 'wrong final block length' and 'Couldn't decrypt the repo, please make sure you enter the right password!' issue 에러 발생

이 경우 위 방법을 사용했을 때에도 동일하게 에러가 발생했다.

 

이때 MatchFile에서 환경변수 설정한 부분에서 키값의 작은 따옴표를 다시 작성해줬더니 잘 동작했다.

흠... 작은 따옴표의 인코딩 에러로 인해 문제가 발생했던 것 같다. 

 

🚨 'No matching provisioning profiles found for {Provisioning Profile name}' issue 에러 발생

 

이 경우는 -a로 app identifier를 지정해주면 된다. AppID로 지정해놓은 것과 받아오는 인증서 간 차이가 있는 경우 발생하는 문제이다. 

하지만 요 경우는 에러 문구가 발생했다고 해서 잘못된 인증서가 오거나, 인증서를 못 받는 문제 자체는 없었다. 

 

그래도 말한대로 

fastlane match appstore --readonly -a tools.fastlane.app

이런 식으로 올바른 identifier를 지정해주면 해당 에러는 사라지게 된다. 

 

2. Xcode Project의 Target에서 있는 Signing & Capabilities 탭에서 Provisioning profile 다운로드

🚨 No matching provisioning profiles found and can not create a new one because you enabled readonly. Check the output above for more information. 에러 발생

Xcode > Target > 프로젝트 > Build Setting > Signing > Code Signing Identity에서 Debug / Release 모두 각각 지정해줌

(기본 설정은 Auto로 되어 있음)

 

제대로 provisioning profile을 지정하지 못하는 것 같아서 수동으로 지정을 해놓았더니 해당 문제는 해결이 되었다. 

 

요것도 1 곳에선 제대로 해결이 되었는데 1 곳에선 제대로 해결이 되지 않아 추가 검토는 필요하다. 

 


아직 완전히 해결을 하진 못했지만 그래도 1곳에선 새로운 컴퓨터에서 생성한 인증서를 받는 것까지 완료해서 오류에 대한 기억이 가물가물해지기 전에 작성해봤다. 

 

다른 글에선 쉽게 쉽게 하시는 것 같던데... 진짜 너무 많은 예외 케이스를 만나서 빡셌다... 

자료도 많이 없고 어디서 문제가 생겼는지 명확히 말해주지를 않다보니 디버깅이 쉽지 않았다. 

 

그래도 직접 해보며 왜 fastlane을 써야 하고 어떻게 써야 하는지 좀 더 감이 온 것 같다. 

아직 Fastfile을 능숙히 설정하여 CI / CD까지 적용하진 못했지만 말이다...

 

나처럼 도입에 애를 먹고 계신 분들이 계시다면 도움이 되었으면 좋겠다 🙏

Comments