앱을 완성 시켜 배포를 완료했습니다! 👏👏👏

하지만 이번에 앱 출시를 하면서 앱 출시를 위해 해야하는 다양한 과정들이 생각보다 귀찮고 많은 시간이 소요되더군요.
이런 생각을 한 사람들이 저 뿐만이 아니라 많은 사람들이 있었기 때문에 CI/CD 라는게 나왔을 것이라 생각합니다.
그래서 이번에는 CI/CD 툴 중 하나인 Fastlane을 사용해 Testflight 업로드 까지 자동화를 해보았습니다.
Fastlane에서는 다양한 경로를 통해 설치를 지원하고 있습니다.
그 중 Bundler 를 이용한 방법을 추천하고 있네요.
하지만 전 Homebrew를 사용하는 방법이 더 쉬워보여 brew로 설치했습니다.
brew install fastlane
그 후 프로젝트 경로로 이동한 다음 커맨드를 실행합니다.
fastlane init
그러면 아래와 같이 선택 창이 나오는데 저는 테스트플라이트에 배포하는 것이 목적이기 때문에 2번을 선택했습니다.
나중에 직접 다 수정이 가능하니 아무거나 선택하셔도 상관 없습니다!

apple id와, 비밀번호, 2차 인증, 팀 선택 진행

그 후 apple id와, 비밀번호, 2차 인증, 팀 선택 까지 완료하고 나면
GemfileGemfile.lockAppfileFastfile총 4개의 파일이 생성되는데 이 중 Fastfile에서 자동화 작업을 정의하므로 Fastfile을 수정하면 됩니다!
Fastlane은 Ruby로 만들어져 있어 Ruby 문법을 알고 있으면 좋지만 사실 대체적으로 사용되는 메소드들은 도큐먼트에 있으므로 루비를 몰라도 만들 수 있습니다.
그리고 GPT도 잘 알려주기 때문에 ㅎㅎ;;;
Available Actions - fastlane docs(사용 가능한 명령어들)
Fastfile을 열게되면 아래와 같이 기본적으로 세팅되어 있습니다.
default_platform(:ios)
platform :ios do
desc "Push a new beta build to TestFlight"
lane :beta do
increment_build_number(xcodeproj: "프로젝트 명.xcodeproj")
build_app(scheme: "Bomudadima")
upload_to_testflight
end
end
beta 라는 lane이 하나의 작업 라인이라고 보시면 됩니다.
저는 해당 작업 라인에 테스트 플라이트를 올리기 위한 전처리 작업을 진행한 후 테스트 플라이트에 업로드를 진행하도록 구성했습니다.
제가 구성한 작업 구조는 다음과 같습니다.
소스코드는 아래와 같습니다.
default_platform(:ios)
platform :ios do
desc "Push a new beta build to TestFlight"
lane :beta do
today = Time.now.strftime("%Y%m%d")
current_build_number = "#{latest_testflight_build_number}"
if current_build_number.length == 9
current_date = current_build_number[0,8]
current_count = current_build_number[8].to_i
else
# 빌드 넘버가 없거나 형식이 다르면 초기화
current_date = ""
current_count = 0
end
if current_date == today
next_count = current_count + 1
else
next_count = 1
end
new_build_number = "#{today}#{next_count}"
increment_build_number(
xcodeproj: "Run Mile.xcodeproj",
build_number: new_build_number
)
notification(
subtitle: "Build Number: #{new_build_number}",
message: "테스트 플라이트 배포 준비"
)
build_app(
scheme: "Run Mile",
export_options: {
provisioningProfiles: {
"com.mooni.Run-Mile" => "com.mooni.Run-Mile AppStore"
}
}
)
upload_to_testflight(
api_key_path: "connect api key 파일 경로"
)
notification(
subtitle: "Testflight 배포 성공!",
message: "Build Number : #{new_build_number}, 테스트 플라이트 배포에 성공했습니다!"
)
end
# 에러처리 => 시스템 노티 발행
error do |lane, exception, options|
notification(
subtitle: "Testflight 배포 중 오류가 발생했습니다.",
message: "#{exception}"
)
end
end
여기서 중간에 upload_to_testflight에 파라미터로 있는 api_key_path의 경우 직접 발급이 필요합니다.
App Store Connect로 이동합니다.
그 후 키 생성을 통해 API키를 생성하면 p8파일을 다운로드 받을 수 있습니다.
한 번 다운로드 후에는 다시 다운로드가 제한되므로 확실하게 보관해 주시기 바랍니다.

완성되면 키 ID, Issuer ID도 새로 생기는데 해당 정보도 필요하므로 기억해놓습니다!
이 다음에 Fastfile이 담겨있는 fastlane 폴더에 json 파일 하나 만들어 아래와 같이 채워주세요.
파일이름은 아무렇게 하셔도 상관없습니다.
{
"key_id": "키 ID",
"issuer_id": "Issuer ID",
"key": "-----BEGIN PRIVATE KEY-----\n여기 키 정보\n-----END PRIVATE KEY-----",
"duration": 1200,
"in_house": false
}
차례대로
그 후 해당 파일 경로를 api_key_path에 채워줍니다!
upload_to_testflight(
api_key_path: "fastlane/(키파일이름).json"
)
다음 터미널을 통해 실행시키고자 하는 lane 명을 실행시켜주면 완료됩니다.
저는 기존 이름 beta 그대로 사용했습니다!
fastlane beta
대략 4~5분의 시간을 거쳐….

성공했다는 메시지와 함께 업로드가 완료됩니다!
테스트 플라이트에 업로드 까지 확인이 되었습니다.
이렇게 Fastlane을 사용해 테스트플라이트 배포를 자동화 해보았습니다.
여기서 조금만 더 응용하면 앱스토어 배포까지 자동화 할 수 있다고 하네요!
곧 앱스토어 배포도 도전 해 본 후 후기글을 올려보도록 하겠습니다 ㅎㅎ
라고 넘어가기엔 성공하기 전까지 수많은 오류들이 제 앞을 가로막았었기 때문에 이 과정 또한 공유해보고자 합니다.
인증서의 문제가 있을 때 나오는 에러입니다.
저는 개인 프로젝트이기 때문에 singing 관리를 자동으로 해놓았습니다.(Xcode의 Automatically manage signing)
이 과정에서 사용되는 Profile에 Apple Distribution 인증서가 포함되어 있지 않을 경우가 있습니다.
수동으로 변경한 후

여기서 Provisioning Profile의 i 버튼을 누르면 인증서 목록이 나옵니다.

이렇게 Certificates에 배포용 인증서(Apple Distribution)이 포함되어 있는지 확인하면 됩니다.
만약 안되어있을 경우 새로운 배포용 인증서를 발급하여 Provisioning Profile 생성 후 수동으로 적용해 주시면 됩니다.
위와 같이 Provisioning Profile을 등록해도 똑같이 에러가 날 경우 fastfile의 build_app에 다음과 같이 파라미터를 추가합니다.
build_app(
scheme: "Run Mile",
export_options: {
provisioningProfiles: {
"번들 ID" => "Provisoning Profile 이름"
# 예시
# "com.mooni.Run-Mile" => "com.mooni.Run-Mile AppStore"
}
}
)
HealthKit을 사용하는 프로젝트일 경우 Provisioning Profile에 HealthKit Capabilities가 추가되어 있는지, 또한 프로젝트의 entitlements에도 관련 정보가 포함되어 있는지 확인해야 합니다.
저의 경우 위와 같이 다 포함되어 있는데도 계속 오류가 나 Profile을 새로 다운로드 받아 적용하니 오류가 해결되었습니다;;
App Store Connect API Key 입력에 문제가 있는 경우입니다.
{
"key_id": "키 ID",
"issuer_id": "Issuer ID",
"key": "-----BEGIN PRIVATE KEY-----\n여기 키 정보\n-----END PRIVATE KEY-----",
"duration": 1200,
"in_house": false
}
여기서 key값을 입력할 때
-----BEGIN PRIVATE KEY----- 다음 개행 문자(\n)
-----END PRIVATE KEY----- 전 개행 문자(\n)
를 반드시 포함시켜 주어야 합니다.
또한 p8 파일을 열면 키 값이 여러줄로 되어 있는데 해당 값을 그대로 복붙하지 말고 한 줄로 이어서 넣어주어야 합니다.