Fastlane + Github Actions release lane 구축 및 안정화
develop 브랜치에 대한 beta lane 자동화 성공 이후, 최종 목표인 main 브랜치의 App Store 배포 자동화를 위해 release lane 구축을 시작했다. 이 과정은 beta lane 구축 경험을 바탕으로 순조로울 것이라 예상했지만, 실제 배포 환경의 미묘한 차이로 인해 새로운 문제들을 마주해야 했다.
문제
main 브랜치에 코드를 머지했을 때, release lane이 실행되어 App Store에 빌드를 업로드하고 심사를 제출하는 과정에서 다수의 오류가 발생했다.
- 빌드 번호 충돌: beta lane에서 해결했던 빌드 번호 중복 오류가 재발했다.
- 비대화형 환경 오류: CI 환경의 특성으로 인해 fastlane이 사용자에게 확인을 요청하며 멈췄다.
- Precheck 한계 봉착: fastlane의 알려진 한계점으로 인해 심사 전 검증 단계에서 오류가 발생했다.
- 수출 규정 준수 정보 누락: 최종적으로 App Store 제출에 필요한 정책적인 정보가 누락되어 심사 제출에 실패했다.
원인 파악 및 해결 과정
각 문제의 근본 원인을 단계적으로 분석하고, 파이프라인의 안정성을 높이는 방향으로 해결책을 적용했다.
1. release lane의 빌드 번호 관리 부재

- 원인: 초기 release lane은 beta lane과 달리 빌드 번호를 자동으로 올리는 로직이 없었다. 이로 인해 Git에 저장된 낮은 빌드 번호를 그대로 사용하여, App Store Connect에 이미 존재하는 높은 빌드 번호와 충돌했다.
- 해결: beta lane의 성공 경험을 release lane에 그대로 적용했다. app_store_build_number 액션을 사용하여 App Store Connect 서버에서 직접 해당 버전의 최신 빌드 번호를 조회하고, 그 값에 1을 더해 새로운 빌드 번호를 설정하도록 수정했다.
// Fastfile
...
latest_build = app_store_build_number(
app_identifier: "com.tomyongji.ios",
version: app_version,
live: false
)
new_build_number = latest_build + 1
...
2. CI 환경에서의 사용자 입력 요청

- 원인: upload_to_app_store 액션은 기본적으로 업로드할 메타데이터의 미리보기를 보여주고, 사용자에게 계속 진행할지 확인을 요청한다. CI 환경에서는 이 질문에 답할 수 없어 오류가 발생했다.
- 해결: upload_to_app_store 옵션에 force: true를 추가하여, "묻지 말고 바로 진행하라"고 명시적으로 지시함으로써 이 문제를 해결했다.
upload_to_app_store(
force: true,
...
)
3. API Key 인증 방식의 Precheck 한계

- 원인: 심사 제출 전 실행되는 Precheck 기능이 인앱 결제 정보를 검증하려 했으나, 현재 사용하는 App Store Connect API Key 인증 방식은 해당 정보를 조회할 권한이 없다는 fastlane의 알려진 한계점 때문에 오류가 발생했다.
- 해결: 이 역시 fastlane이 공식적으로 제공하는 해결책을 사용했다. upload_to_app_store 옵션에 precheck_include_in_app_purchases: false를 추가하여, "Precheck 시 인앱 결제 항목은 검사에서 제외하라"고 설정하여 문제를 우회했다.
upload_to_app_store(
force: true,
...
precheck_include_in_app_purchases: false
)
4. 수출 규정 준수(Export Compliance) 정보 누락

- 원인: 모든 기술적인 문제가 해결된 후, App Store 제출에 필수적인 "앱이 암호화 기술을 사용하는지"에 대한 정책 질문에 답변이 누락되어 최종 단계에서 실패했다.
- 해결: 이 정보는 배포 스크립트가 아닌 앱 자체의 메타데이터에 속하는 것이라 판단하고, 가장 표준적인 방법을 선택했다. 프로젝트의 Info.plist 파일에 ITSAppUsesNonExemptEncryption 키를 추가하고, 값을 false(Boolean)로 설정하여 "표준 암호화만 사용한다"고 명시했다. 이 수정 후 tuist generate를 통해 프로젝트 파일을 업데이트하여 근본적으로 문제를 해결했다.
// info.plist
...
<key>ITSAppUsesNonExemptEncryption</key>
...
결과
- 수정 전: release lane은 빌드 번호 충돌, 사용자 확인 요청, Precheck 및 수출 규정 문제로 인해 매번 다른 단계에서 실패했다.
- 수정 후: Fastfile*과 Info.plist*를 종합적으로 수정하여, main 브랜치에 코드가 머지될 때마다 빌드 번호 관리부터 앱 빌드, App Store 업로드, 릴리스 노트 작성, 심사 제출까지 모든 과정이 완벽하게 자동화됐다.
개선 효과



- 양방향 파이프라인 완성: develop 브랜치는 TestFlight, main 브랜치는 App Store로 배포되는, 역할과 책임이 명확히 분리된 완전한 CI/CD 파이프라인을 구축했다.
- 견고성 극대화: 서버 기준의 빌드 번호 관리, CI 환경을 고려한 명시적 옵션 설정, 프로젝트 메타데이터 강화를 통해, 예외 상황 발생 가능성을 최소화한 매우 견고하고 신뢰성 높은 시스템을 완성했다.
- 완전한 배포 해방: 이제 개발팀은 브랜치 전략에 따라 PR을 머지하는 것 외에, 배포와 관련된 그 어떤 수작업도 신경 쓸 필요가 없어졌다. 이를 통해 얻은 시간과 정신적 여유는 온전히 제품의 가치를 높이는 데 투자할 수 있게 되었다.