수동 업로드는 성공했지만 원격 맥의 자동 실행은 서명이나 인증 단계에서 멈춥니다.

가장 빠른 해결책은 테스트·아카이브·업로드 Lane을 먼저 분리하고, Apple silicon 원격 맥에서 Xcode 27, Ruby, Bundler, fastlane 버전을 고정한 뒤 TestFlight와 복구 절차를 검증하는 것입니다.

이 글은 Windows 또는 Linux에서 개발하며 원격으로 iOS 빌드와 출시를 진행하려는 독립 개발자를 위한 안내서입니다. 반복적으로 TestFlight에 올리는 앱 운영자와 임시 환경을 상시 iOS 패키징 서버로 바꾸려는 작은 팀에도 맞습니다.

마지막 업데이트: 2026년 9월 13일. Xcode 27의 공식 요구 사항과 업로드 범위는 Apple의 Xcode 시스템 요구 사항빌드 업로드 안내를 기준으로 다시 확인해야 합니다. 현재 확인 가능한 Xcode 27 RC와 정식 버전은 구분해야 하며, 정식 출시일과 최종 시스템 요구 사항은 배포 시점에 재검토해야 합니다.

시작 전에 자동화의 경계를 정합니다

fastlane은 테스트 실행, Archive 생성, 서명 처리와 업로드를 하나의 흐름으로 연결할 수 있습니다. 그러나 macOS, Xcode, Apple 개발자 계정이 없어도 되는 도구는 아닙니다. 특히 자동화가 성공했다는 말은 여러 단계를 나누어 판단해야 합니다.

  • 테스트: 코드와 테스트 대상이 통과했는지 확인합니다.
  • Build: 앱이 컴파일되는지 확인합니다.
  • Archive: 배포 가능한 아카이브가 생성되는지 확인합니다.
  • Export: 필요한 배포 형식의 IPA가 만들어지는지 확인합니다.
  • Upload: App Store Connect로 파일이 전송되는지 확인합니다.
  • 처리: Apple 서버가 빌드를 처리하고 테스트 대상으로 연결하는지 확인합니다.
  • 배포: 테스트 사용자 지정 또는 심사 제출을 별도로 실행합니다.
업로드가 끝났다고 곧바로 테스트 가능한 빌드가 된 것은 아닙니다. Apple은 App Store Connect에서 빌드 상태를 별도로 표시하므로 [빌드 상태 설명](https://developer.apple.com/help/app-store-connect/reference/app-uploads/app-build-statuses)을 기준으로 최종 상태를 확인해야 합니다.

로컬 맥이 없어도 fastlane으로 iOS 앱을 패키징할 수 있나요?

가능합니다. 다만 Xcode가 실행되는 macOS 환경과 프로젝트에 맞는 서명 자산이 필요합니다. Windows 또는 Linux에서는 코드를 작성하고, 원격 맥에 SSH로 접속해 테스트와 Archive, 업로드를 실행하는 방식이 현실적입니다.

첫 자동화 전에 수동으로 한 번 성공한 Archive와 TestFlight 업로드를 남겨 두십시오. 이 기준선이 없으면 이후 실패가 프로젝트 설정 때문인지, 인증 때문인지, 원격 환경 때문인지 분리하기 어렵습니다.

첫 번째 시간에 Xcode 27과 실행 환경을 고정합니다

먼저 원격 맥의 칩과 macOS가 현재 Xcode 27 요구 사항을 충족하는지 확인합니다. Xcode 27 RC를 정식 버전처럼 취급하지 말고, 운영 배포에 사용할 버전을 별도 기록하십시오.

그다음 시스템 Ruby나 제약 없는 전역 설치에 의존하지 않도록 프로젝트 안에 의존성을 선언합니다.

# Gemfile
source "https://rubygems.org"

gem "fastlane"
bundle install
bundle exec fastlane --version
xcode-select -p
ruby --version
locale

Gemfile.lock은 저장소에 함께 보관합니다. fastlane의 기본 설치 흐름은 공식 설정 문서를 따르되, 팀마다 Ruby 실행 위치와 Bundler 호출 방식을 하나로 통일해야 합니다.

다음 항목도 기록합니다.

  • Xcode 경로와 선택된 개발자 디렉터리
  • Ruby와 Bundler 실행 환경
  • UTF-8 Locale 설정
  • Workspace, Scheme, Bundle ID의 설정 위치
  • 빌드 산출물과 로그를 저장할 경로
  • 원격 맥에서 실행할 사용자와 Keychain 접근 방식
이 기록은 새 호스트로 옮길 때 필요한 재구성 기준입니다. 원격 맥을 [MACGPU의 원격 맥 환경](https://macgpu.com/ko/index.html)으로 바꾸더라도 이 기준 파일이 있으면 도구를 다시 맞추기 쉽습니다.

두 번째 단계에서 Lane을 세 개로 나눕니다

처음부터 하나의 명령으로 테스트, 서명, 업로드를 모두 실행하지 마십시오. 한 단계가 실패했을 때 책임 범위를 좁힐 수 있도록 다음처럼 분리합니다.

# Fastfile
default_platform(:ios)

platform :ios do
  lane :verify do
    run_tests(
      workspace: "YOUR_WORKSPACE.xcworkspace",
      scheme: "YOUR_SCHEME"
    )
  end

  lane :archive do
    build_ios_app(
      workspace: "YOUR_WORKSPACE.xcworkspace",
      scheme: "YOUR_SCHEME",
      output_directory: "YOUR_OUTPUT_DIRECTORY",
      output_name: "YOUR_ARCHIVE_NAME.ipa"
    )
  end

  lane :upload_testflight do
    pilot(
      ipa: "YOUR_OUTPUT_DIRECTORY/YOUR_ARCHIVE_NAME.ipa",
      skip_waiting_for_build_processing: true
    )
  end
end

위 값은 실제 계정이나 프로젝트 값이 아닌 자리 표시자입니다. 저장소에는 실제 Bundle ID, Team ID, Scheme, 호스트 주소와 비밀 경로를 넣지 마십시오.

verify의 성공 조건은 테스트 결과 파일과 통과 상태입니다. archive는 IPA 또는 xcarchive와 빌드 로그를 남겨야 합니다. upload_testflight는 전송 로그와 App Store Connect의 빌드 상태를 남겨야 합니다. 단순히 명령이 성공 상태로 끝났다는 이유만으로 전체 배포를 성공 처리하지 않는 것이 핵심입니다. build_ios_app의 옵션과 산출물은 [fastlane 공식 빌드 문서](https://docs.fastlane.tools/actions/build_ios_app/)를 기준으로 프로젝트에 맞게 정합니다. 각 Lane에는 성공 산출물, 로그 위치, 중단 조건을 문서화하십시오.

세 번째 단계에서 서명과 인증을 분리합니다

코드 서명 자산과 App Store Connect 업로드 인증은 같은 권한이 아닙니다. 인증서의 개인 키와 Provisioning Profile이 없으면 앱 서명을 완료할 수 없습니다. 반대로 App Store Connect API Key는 업로드와 관리 API 인증에 사용되지만 인증서 개인 키를 대신하지 않습니다. fastlane의 API Key 방식은 공식 인증 문서에서 지원 범위와 제한을 확인해야 합니다.

선택지는 세 가지로 나누어 판단합니다.

<
방식적합한 경우주의할 점평가
기존 서명 자산을 원격 맥에 제한적으로 가져오기한 앱을 짧게 검증할 때개인 키와 프로파일의 보관 위치를 따로 관리해야 합니다빠른 검증에 적합
Xcode 자동 서명프로젝트 설정이 단순하고 계정 접근이 안정적일 때비대화형 실행에서 계정 상태와 프로파일 변경을 확인해야 합니다설정은 쉽지만 통제 범위가 좁음
통제된 동기화 방식반복 출시와 여러 앱을 관리할 때저장소 접근 권한과 키 교체 절차를 별도로 운영해야 합니다상시 운영에 적합
비밀값은 제한된 환경 변수, Keychain 또는 접근 권한을 줄인 보안 파일로 주입합니다. 개인 키, API Key, 토큰, 비밀번호를 Fastfile이나 코드 저장소에 직접 작성하지 마십시오.

Apple ID와 App Store Connect API Key 중 무엇을 사용해야 하나요?

업로드 자동화에는 API Key를 우선 검토할 수 있지만, 이것만으로 코드 서명에 필요한 인증서와 개인 키가 준비되는 것은 아닙니다. 개발자 계정의 역할과 앱 범위를 확인하고, 사람이 직접 로그인해야 하는 절차가 남아 있는지 먼저 구분하십시오.

네 번째 단계에서 TestFlight를 끝까지 검증합니다

첫 목표는 심사 제출이 아니라 TestFlight 업로드입니다. 다음 순서로 실행합니다.

  1. 수동 기준선과 같은 Scheme으로 verify를 실행합니다.
  2. archive를 실행하고 IPA 또는 아카이브를 보관합니다.
  3. 빌드 번호와 버전 번호가 의도한 값인지 확인합니다.
  4. upload_testflight를 실행합니다.
  5. 업로드 로그와 App Store Connect의 빌드 상태를 각각 저장합니다.
  6. 처리 완료 후 테스트 그룹과 연결되는지 확인합니다.
  7. 그다음에만 메타데이터 변경이나 심사 제출을 추가합니다.
fastlane의 TestFlight 업로드 동작은 [pilot 공식 문서](https://docs.fastlane.tools/actions/pilot/)를 사용 기준으로 삼습니다. Apple에서 앱 기록이 아직 생성되지 않았다면 [App Store Connect 앱 기록 생성 안내](https://developer.apple.com/help/app-store-connect/create-an-app-record/add-a-new-app)를 먼저 확인해야 합니다.

TestFlight에 보이는 것과 심사에 제출하는 것은 별개입니다. 실제 제출은 새 버전 생성, 빌드 선택, 필수 메타데이터 검토를 거쳐야 합니다. Apple의 새 버전 생성 절차제출용 빌드 선택 안내를 기준으로 마지막 단계를 분리하십시오.

첫 주에는 복구 가능한 상시 흐름으로 바꿉니다

한 번 성공한 Lane을 바로 상시 서버로 사용하지 마십시오. 다음과 같은 실패 상황을 각각 실행해 보십시오.

  • SSH 연결을 끊은 뒤 작업 상태와 로그가 남는지 확인합니다.
  • 원격 사용자 세션을 다시 시작한 뒤 Keychain과 환경 변수가 살아 있는지 확인합니다.
  • 호스트를 재시작한 뒤 Xcode 선택 상태와 작업 디렉터리를 확인합니다.
  • API Key 또는 서명 자산이 만료된 상황에서 명확한 중단 로그가 나오는지 확인합니다.
  • 실패한 작업을 같은 빌드 번호로 재실행할 때 중복 업로드 문제가 없는지 확인합니다.
복구를 위해 실행 명령, 시작 시각, 로그 경로, 산출물 위치를 한 파일에 남기십시오. 장시간 작업은 SSH 세션에만 묶지 말고 원격 작업 관리자나 터미널 세션 유지 방식을 사용하십시오. 다만 특정 도구가 재시작 뒤 작업을 자동으로 이어 간다고 가정하지 말고, 중단 지점부터 재실행하는 절차를 정의해야 합니다.

Xcode 27 정식 버전으로 바꾸는 Lane과 의존성 업그레이드용 검증 Lane도 운영 배포 Lane과 분리합니다. 먼저 별도 환경에서 verifyarchive를 실행하고, TestFlight 업로드까지 확인한 뒤 기본 도구를 바꾸십시오.

배포 방식을 결정하기 전에 이 표를 채웁니다

아래 목록은 구성 완료 여부를 확인하는 실행용 점검표입니다.

  • [ ] Apple silicon 원격 맥의 macOS와 Xcode 27 요구 사항을 확인했습니다.
  • [ ] Xcode 27 RC와 정식 버전을 구분해 기록했습니다.
  • [ ] Ruby, Bundler, fastlane 버전을 Gemfile.lock으로 고정했습니다.
  • [ ] Workspace, Scheme, 출력 경로를 자리 표시자에서 실제 설정으로 연결했습니다.
  • [ ] 테스트, Archive, TestFlight 업로드 Lane을 분리했습니다.
  • [ ] 인증서 개인 키와 Provisioning Profile의 보관 위치를 제한했습니다.
  • [ ] App Store Connect API Key의 역할과 앱 범위를 확인했습니다.
  • [ ] IPA 또는 아카이브, 로그, App Store Connect 상태를 각각 보관했습니다.
  • [ ] SSH 단절, 사용자 재로그인, 호스트 재시작을 시험했습니다.
  • [ ] Xcode와 fastlane 업그레이드용 별도 검증 Lane을 만들었습니다.

상황에 맞는 원격 맥 운영안을 고릅니다

도구 체인을 고정한 뒤에는 사용 빈도와 복구 요구 사항으로 운영 방식을 결정합니다. 장기 보관이 필요한지, 물리 장치 접근이 필요한지도 함께 판단해야 합니다.

<
운영안잘 맞는 상황실제 부담평가
임시 원격 맥처음 한 번 빌드와 TestFlight 흐름을 검증할 때환경을 다시 만들고 비밀값을 재주입해야 합니다초기 검증에 적합
상시 원격 맥반복 출시, 예약 작업, 고정된 Xcode 환경이 필요할 때접근 권한, 패치, 인증서 교체를 계속 관리해야 합니다자동화 운영에 적합
로컬 맥디버깅과 기기 연결을 자주 직접 해야 할 때장비 비용과 고정된 작업 공간이 필요합니다대화형 개발에 적합
분리 운영검증과 실제 출시를 격리해야 할 때두 환경의 버전 차이를 관리해야 합니다소규모 팀의 안정성에 유리
**원격 맥이 재시작된 뒤 fastlane 작업은 어떻게 복구하나요?**

재시작 자체가 작업을 이어 준다고 가정하지 말고, 마지막으로 확인된 산출물부터 다시 시작합니다. 로그에서 테스트와 Archive의 성공 여부를 확인한 뒤, 이미 유효한 IPA가 있으면 업로드 단계만 재실행합니다. IPA가 없거나 서명 상태가 불명확하면 테스트부터 다시 실행하는 편이 안전합니다.

현재 환경에서만 잠깐 검증한다면 임시 사용으로 충분합니다. 반대로 매주 반복 출시하고 고정된 도구 체인을 유지해야 한다면 상시 접속 가능한 원격 맥을 별도로 두는 편이 관리하기 쉽습니다. MACGPU의 맥 대여 선택지를 검토할 때도 먼저 필요한 Lane과 복구 기준을 정한 뒤 기간을 선택하십시오.

현재 방식과 원격 맥을 마지막으로 비교합니다

Windows 또는 Linux만으로 개발을 계속하면 Xcode 실행, 코드 서명, Archive 생성 단계에서 결국 별도 macOS 환경이 필요합니다. 개인 맥을 추가하면 초기 장비 비용뿐 아니라 저장 공간, 운영체제 업데이트, 전원과 네트워크 유지, 팀원의 접근 권한까지 직접 관리해야 합니다.

반면 원격 맥은 완전히 대화형인 로컬 개발을 대신하지 못합니다. 실제 iPhone 연결이나 장시간 UI 디버깅이 중요하다면 로컬 장비가 더 적합할 수 있습니다. 그러나 이미 수동 배포를 끝냈고, 고정된 도구 체인으로 반복 빌드와 TestFlight 업로드를 수행하려는 경우에는 완전한 권한을 가진 원격 맥이 더 단순한 운영 선택이 될 수 있습니다.

따라서 먼저 임시 환경에서 Lane과 서명을 검증하고, 이후 상시 온라인 환경이 필요해졌을 때 MACGPU의 맥 대여를 비교하는 순서가 안전합니다. 발행 빈도가 낮으면 짧은 기간으로 시작하고, 지속적인 iOS 패키징 서버가 필요할 때만 장기 환경으로 전환하십시오.