← 개발 일기로

Fastlane 듀얼 클라우드 Mac: 빌드·업로드 분리 후 흔한 실패 3가지

Runbook · 2026.06.04 · 약 8분 · 온콜 문서에 붙여넣기

듀얼 클라우드 Mac: 홍콩 archive, 캐나다 Fastlane upload

온콜 중이고 임대 클라우드 Mac 두 대 이상에서 Fastlane으로 iOS를 배포하는데, 「빌드 로그는 녹색인데 TestFlight에 새 빌드가 없다」 또는 「잘못된 패키지가 올라갔다」면 이 글이 대상입니다. 클라우드 도입·두 번째 Mac 여부는 TestFlight 전용 Mac 또는 Xcode 빌드 클라우드 이전을 먼저 보세요 — 여기서는 이미 한 대는 빌드, 한 대는 업로드로 나눴다고 가정합니다.

이 글을 읽고 나면 두 가지를 알 수 있어야 합니다. ① 로그로 인증서·아티팩트·네트워크 중 어디 문제인지. ② 두 Mac의 역할이 맞는지, 기계를 더 사야 하는지.

용어 정리 (아래에서 반복 사용)
  • 빌드 머신: Xcode로 프로젝트를 컴파일하고 설치 패키지(.ipa)만보냄
  • 업로드 머신: 배포 인증서로 서명해 .ipa를 TestFlight에 올림. App Store Connect에 등록하는 출구 IP는 이 호스트만
  • Archive / 빌드: Xcode 배포용 출력. 호스트 간에는 완성된 .ipa만 전달
  • match: Fastlane 배포 인증서 도구 — 한 호스트에서만

건너뛰어도 되는 경우: Mac이 한 대뿐이거나 TestFlight 업로드가 안정적이고 아직 「빌드 + 업로드」로 나누지 않았다면. 여러 클라우드 Mac으로 배포 중이고 파이프라인에 문제가 있으면 계속 읽으세요.

TL;DR(30초)
홍콩 빌드 + 캐나다 업로드 같은 듀얼 클라우드 Mac 구성에서는 병목이 CPU가 아니라 Fastlane의 세 가지 경계 오류인 경우가 많습니다.
  1. 인증서 경계 — 배포 인증서가 빌드 머신에 동기화되어 업로드 머신이 서명 못 함 (가장 위험)
  2. 산출물 경계 — 검증 가능한 .ipa가 아니라 .xcarchive를 DC 간 전송(가장 찾기 어려움)
  3. 네트워크 ID 드리프트 — ASC IP 허용 목록이 오래된 IPv4(조사가 가장 까다로움)
이하 30초 트리아지 트리, 세 가지 장애 모드, 검수표, 4단계 성숙도, 「최종 결론」 블록(그 절만으로도 의사결정 가능) 순입니다.

배경(1분): 2대로 나눈 뒤 터지는 건 경계이지 CPU가 아님

많은 팀이 클라우드 Mac 두 대를 씁니다. 아시아에 가까운 한 대가 낮에 App을 설치 패키지로 컴파일하고, 캐나다 한 대가 Apple에 패키지를 전달합니다(TestFlight / App Store). 두 번째 Mac은 속도 때문인 경우가 많지만, 온콜 시간은 둘 다 인증서·파일 전송에 손대는 데 갑니다 — 빌드는 성공인데 TestFlight에 새 버전이 없는 패턴입니다.

먼저 흔한 잘못된 분리(모델 B), 그다음 우리가 쓰는 분리(모델 A)와 검증 방법을 설명합니다.

권장: 모델 A (빌드는 패키지만, 업로드는 배포만)

한 줄로: 빌드 머신은 .ipa만 만들고, 업로드 머신만 인증서와 TestFlight를 담당합니다. 양쪽에서 match를 돌리지 마세요 — 개인키가 잘못된 호스트에 남습니다.

Dual cloud Mac roles (Model A)
역할 빌드 머신 (홍콩) Example: APAC daytime builds 업로드 머신 (캐나다) Fixed IP for Apple
할 일코드 pull → Xcode 빌드 → .ipa보내기.ipa 수신 → 배포 서명 → TestFlight 업로드
하지 말 것match 금지, TestFlight 업로드 금지전체 프로젝트 재컴파일 금지
다음 호스트로설치 패키지 + RUN_ID없음 (종점: App Store Connect)

당사 2대는 Hashvps 독립 Mac mini에서 동작합니다. 선택 이유는 고정 IP + 역할 분리(업로드 IP만 ASC, 빌드 IP 불필요)입니다. 홍콩 노드 사양은 홍콩 Mac mini 임대를 참고하세요.

빌드 · match 없음 업로드 · 서명 권한 유일 build → export .ipa no certs · no upload includes build ID certs + TestFlight upload fixed public IP registered in ASC .ipa → DC 간 최소 단위는 xcarchive가 아니라 검증 가능한 IPA
모델 A: match·서명은 업로드 머신만. 빌드는 IPA 전달

당사 2대는 Hashvps 독립 Mac mini에서 동작합니다. 선택 이유는 고정 IP + 역할 분리(업로드 IP만 ASC, 빌드 IP 불필요)입니다. 홍콩 노드 사양은 홍콩 Mac mini 임대를 참고하세요.

흔한 실수: 모델 B (둘 다 「도와주는」 상태)

모델 B는 역할이 갈라지지 않은 상태입니다. 1주차에 우리도 이렇게 했습니다. 겉으로는 두 대 분담이지만 실제로는:

  • 둘 다 match → 배포 개인키가 빌드 머신에 남음 → 업로드 머신 서명 실패 → TestFlight 계속 실패
  • 빌드에서 .xcarchive rsync → 업로드에서 재 export, 빌드와 동일 SHA 검증 불가 → 산출물 혼선·Invalid Binary
  • 양쪽에서 각각 export_ipaExportOptions.plist 2벌 드리프트 → 업로드는 성공하지만 빌드 승격 불가

기존 파이프라인에 하나라도 해당하면 해결책은 「Mac 한 대 더」가 아니라 build / upload role split(모델 A)가 필수입니다.

관측 가능성: build와 upload가 같은 빌드인지

가장 흔한 운영 사고는 「어제 IPA를 오늘 올렸다」입니다. 빌드·업로드 양쪽 로그에 같은 필드를 강제로 출력합니다:

  • RUN_ID(파이프라인 1회 ID. 예: hk-build-88421
  • GIT_SHA(짧은 commit)
  • 산출물 경로 + SHA256(build/manifest.json 기록)
빌드 성공 · 업로드 성공(동일 RUN_ID)
# 홍콩 · build · build
[15:11:42]: Successfully exported: ./build/MyApp-20260604-1502.ipa
[15:11:42]: RUN_ID=hk-build-88421  GIT_SHA=a3f91c2  SHA256=9f2a…

# 캐나다 · upload · upload
[02:22:01]: RUN_ID=hk-build-88421  GIT_SHA=a3f91c2  ipa_sha256=9f2a…
[02:24:18]: Successfully uploaded package to App Store Connect

온콜 규칙: 업로드 로그에 같은 RUN_ID가 없으면 산출물 불일치로 처리. ASC부터 의심하지 마세요.

30초 트리아지: TestFlight에 새 build 없음?

전체 로그부터 열지 마세요. 아래 트리를 한 단계만 따라가면 해당 절로 갑니다(Runbook 북마크 권장).

온콜 진단 트리(Runbook 복사용)
TestFlight에 새 build 없음?
 ├─ 업로드 RUN_ID ≠ 빌드 RUN_ID (또는 manifest 없음)
 │     → 함정 2 · 아티팩트 경계
 ├─ 로그에 match / AppStoreDistribution / code signing identity
 │     → 함정 1 · 인증서 경계
 └─ upload 성공인데 ASC 비어 있음 / 403 / Invalid Binary (빌드 전부 녹색)
       → 함정 3 · 네트워크 신원 드리프트
세 가지 장애 · 한눈에(온콜용)
모드 로그 키워드(grep) Release 영향
함정 1 인증서 경계 AppStoreDistribution, No matching provisioning, match failed 차단: TestFlight / 스토어 제출 전면 중단
함정 2 산출물 경계 RUN_ID 불일치, Invalid Binary, export_method 충돌 높음: 잘못된 패키지·승격 불가 가능
함정 3 ID 드리프트 403, upload OK인데 processing 없음, ASC 네트워크 제한 간헐 차단: 「미스터리 누락」처럼 보임

세 가지 실패 모드(상세)

함정 1: 인증서 경계 오류

30초 판별: 빌드 archive 초록, 업로드 빨강, match / signing 단계에서 실패.

로그 키워드: AppStoreDistribution, Could not find a matching code signing identity, No matching provisioning profiles.

Release 영향: 차단급 — 개인키가 업로드 머신으로 돌아올 때까지 TestFlight / App Store 업로드 불가.

현상: 빌드 archive 초록, 업로드 upload 빨강. TestFlight 새 build 없음.

전형 로그
Could not find a matching code signing identity for type 'AppStoreDistribution'
❌  Lane upload failed

근본 원인: 모델 B — 빌드가 여전히 match(appstore) 실행, Distribution 개인키가 업로드에 없음.

수정: 빌드에서 모든 match 제거. 업로드만 match(rotate는 업로드만·독립 유지보수 창). match readonly 참고.

함정 2: 산출물 경계 오류

30초 판별: 빌드/업로드 로그의 RUN_ID, ipa_sha256 대조. 또는 ASC Invalid Binary인데 빌드에 signing 오류 없음.

로그 키워드: RUN_ID 불일치, Invalid Binary, 양쪽에서 export_ipa / ExportOptions 두 번.

Release 영향: 높음 — 옛 패키지·잘못된 commit 업로드, processing 정지. 파이프라인이 즉시 빨갛지 않을 수 있음.

근본 원인: DC 간 .xcarchive 전송 또는 양쪽 export. DC 간 최소 단위는 SHA 대조 가능한 IPA이지 archive 디렉터리가 아님.

수정: 빌드에서 export_ipa 1회 + manifest.json. 업로드는 upload만, 재 export 금지.

함정 3: 네트워크 ID 드리프트

30초 판별: Fastlane upload 성공. 빌드·업로드 signing 모두 초록. TestFlight 패키지 없음 또는 ASC 403.

로그 키워드: 403, Successfully uploaded인데 build 없음, ASC 네트워크 거부(빌드 로그 정상).

Release 영향: 간헐 차단 — 될 때도 있고 안 될 때도 있어 온콜 인내를 가장 소모.

근본 원인: 업로드 IPv4와 ASC IP 허용 목록 불일치(제3류 잠재 장애).

수정: 업로드에서 매일 curl -4 ifconfig.me로 ASC 대조. 드리프트 시 허용 목록 갱신 + 알림.

제대로 나눴는지 판단

게이트, FAQ, 온콜 항목을 아래 검수표로 통합했습니다. 분리 1주 후 각 행이 자동으로 「예」가 되어야 합니다.

듀얼 Mac 분리 검수(모델 A)
검수 항목 기대 결과
RUN_ID 정합빌드 export와 업로드 upload 로그에서 RUN_ID, GIT_SHA, ipa_sha256 일치
빌드에 Distribution 없음빌드 키체인/로그에 AppStoreDistribution, match 단계 전혀 없음
업로드는 upload만업로드 lane 로그에 match(또는 resign)+ upload_to_testflight만. ARCHIVE SUCCEEDED 없음
산출물 형태DC 간 파일은 200MB 미만 .ipa + manifest. .xcarchive rsync 없음
ASC 신원업로드 현재 IPv4 = ASC 허용 목록. 빌드 IP는 ASC 미등록
Runner 분리role=ios-build-hkrole=ios-upload-ca 라벨 분리. workflow needs 직렬

성숙도: 지금 어느 단계?

장애 대응은 「오늘 밤 어떻게 끄나」, 단계 판단은 「다음 주 아키텍처를 바꿀까」를 결정합니다. 아래 4단계로 유지·수정·role split을 고르세요.

Stage 1: 단일 Mac Fastlane

특징: Mac runner 1대. match + build + upload가 동일 Fastfile·동일 키체인. 먼저 디스크, Derived Data, GitHub Actions 과금 창을 최적화한 뒤 build 노드 추가 검토.

결론: 듀얼 Mac 불필요. APAC 빌드만 느리면 먼저 build 노드 추가. upload 분리는 나중.

Stage 2: 2대 있으나 role split 미적용(모델 B)

특징: Mac 2대 이상. 여러 대에서 match / export / upload 실행. 본문 세 경계 오류가 로그에 자주 등장.

결론:3대째를 추가해도 해결 안 됨. 인증서 드리프트와 산출물 불일치만 증가. 다음은 runner 수가 아니라 모델 A로 수렴.

Stage 3: Role split(모델 A · 본문 목표)

특징: build / upload 책임 분리. DC 간은 RUN_ID 붙은 IPA만. match는 upload 노드만. 업로드 egress IP 고정.

결론: ✔ 검수표가 안정적으로 채워짐 → build runner 가로 확장(APAC 병렬 빌드) 또는 upload 전용기 강화 가능. 고정 IP·노드별 계약은 Hashvps 요금제 참고(먼저 upload ASC IP 고정, 이후 build 확장).

Stage 4: Multi upload node(고급)

특징: upload 리전 복수(US / EU / APAC 등). ASC API Key·IP 전략 리전별. 산출물 승격·컴플라이언스 감사 독립 라인.

결론: 배포 시스템 영역. 「CI용 Mac 한 대 더」가 아님 — 산출물 저장소·정책·감사 필요, 본 Runbook 범위 밖.

단계 → 액션(의사결정 폐루프)
단계 지금 해야 할 일
Stage 1단일 Mac 유지. 빌드·업로드 시간대 최적화
Stage 2증설 중단. 모델 A + 검수표 완주
Stage 3build 가로 확장. upload 전용기·모니터링 강화
Stage 4별도 프로젝트: 다리전 배포·컴플라이언스(Fastlane 패치 아님)
업그레이드 트리거(문제가 이미 발생했음을 인정)
CI에서 이미 「TestFlight가 가끔 안 올라옴 + 여러 Mac runner + match가 여러 노드」가 보이면 role split 필수 단계입니다. runner 증설 단계가 아닙니다. Stage 2에 머물면 위 트리아지·모델 B 안티패턴으로 lane을 고치고 3대째 구매는 미루세요.

최종 결론(이 절만으로 실행 가능)

아래 세 조건을 동시에 만족하면 이 절로 결정하고 전문 재독은 불필요합니다:

  • 이미 Mac runner 2대 이상(또는 동등 멀티노드 CI)
  • Fastlane에서 TestFlight 불안정 / 업로드 실패match failed, processing 정지, 가끔 패키지 없음)
  • match여러 머신에서 실행됐을 가능성

👉 더 이상 머신을 추가하지 마세요.

👉 오늘부터 가능한 세 가지:

  1. 중단: upload 외 노드의 match / sync_code_signing(서명 권한은 upload만)
  2. 강제: DC 간은 .ipa + manifest.json만(.xcarchive rsync 금지)
  3. 통일: RUN_ID + GIT_SHA + ipa_sha256. 업로드 전 반드시 검증

위 세 가지를 못 하면: 여전히 Stage 2(모델 B). 증설은 장애 증폭이지 수리가 아님. Fastfile / workflow 라벨을 먼저 고치고 검수표 통과 후 build 확장을 논의하세요.

업로드 Fastfile(모델 A · 발췌)
lane :upload_only do |options|
  verify_run_id!(options) # manifest.json
  match(type: "appstore", readonly: true)
  upload_to_testflight(ipa: options[:ipa_path], api_key_path: "asc_api_key.json")
end
변경 규율
lane 분리 주에는 match rotate 금지. 인증서 변경은 독립 이벤트. 양 lane 중지 후 업로드에서만 작업.

자주 묻는 질문

빌드에서 서명 없이 archive 가능? 프로젝트 설정에 따름. 당사는 빌드 export로 업로드가 최종 app-store 서명하는 IPA를 넘김(또는 빌드는 컴파일 검증만, 업로드에서 resign). 핵심은 match가 한 대뿐이라는 점.

match 만료가 가까울 때? 업로드만, non-readonly 유지보수 창에서 rotate. profile 안정까지 빌드 중지.

출장 Runbook과 차이? 출장용은 현지 Wi‑Fi·사람 조작. 본문은 DC 역할과 Fastlane 경계. 검수표는 그대로 재사용.

시리즈: 본문은 ① Runbook: 듀얼 클라우드 Mac + Fastlane 장애 대응(TestFlight 미업로드 / match failed / 멀티 Mac iOS CI). 후속: ② Build·Sign·Distribute 설계, ③ 모델 B 안티패턴. 선정은 TestFlight 전용 Mac.

더 읽기

역할 분리·노드는 홍콩 요금가격. upload 전용 Mac 검토는 TestFlight 글부터.

Hashvps

Stage 2? role split 후 확장

upload 전용 고정 IPv4(ASC 화이트리스트). build는 APAC에서 수평 확장.

요금 보기
한정 혜택