← 기술 블로그로

Xcode 26 Beta 테스트 비용 급증?
Runner 격리 플레이북으로 해결

원격 Mac mini에서 Xcode 26 beta CI와 self-hosted runner 이중 격리
프로덕션은 Xcode 16 고정, beta는 전용 Runner——WWDC 후 iOS CI는 디스크를 분리.

결론: WWDC 26 이후 CI에서 Xcode 26 beta를 검증하려면 main workflow를 macos-latest로 바꿔 기도하는 방식이 아닙니다. 원격 Mac에서 Runner 두 레인으로 분리하는 것이 정답입니다. 프로덕션은 Xcode 16 안정판에 고정하고, beta는 전용 label과 별도 DerivedData 디렉터리로 돌립니다.

세 가지 철칙: ① 프로덕션 job에서 sudo xcode-select 금지; ② beta와 프로덕션의 -derivedDataPath는 물리적으로 분리; ③ iOS 27 Simulator runtime은 beta Runner에 한 번만 사전 설치하고 job마다 다운로드하지 않기.

글의 범위: 「WWDC 후 CI가 왜 느려지는가」( WWDC26 iOS CI 지연 글 )는 다루지 않습니다. 48시간 안에 실행 가능한 Runbook만 제공합니다.

6월 10일 글에서 말했듯 WWDC 이후 iOS CI의 충격은 캐시 초기화 + SDK 비대화 + 호스팅 Runner 혼잡이 겹친 결과입니다. 일주일이 지나 Slack 질문은 실무형으로 바뀌었습니다——「beta는 어느 Mac에 깔까?」「한 대에 Xcode 두 개?」「main이 빨갛게 되면 누구 책임?」. 답은 단순합니다: 원격 Mac mini를 self-hosted runner로 쓰고, beta 검증과 App Store 릴리스를 완전히 분리하세요. self-hosted가 없다면 먼저 iOS CI 가속 가이드를 읽고, 노드별 월 비용은 6개 지역 Runner TCO를 참고하세요.

1) 흔한 오해: Mac 한 대 혼용 ≠ 절약

WWDC 직후 가장 흔한 잘못된 결정은 CI Mac이 딱 한 대인 환경에 Xcode 16과 26 beta를 같이 설치하고, workflow의 xcode-select -s로 전환하는 것입니다. 월 한 대 요금처럼 보이지만 실제 비용은 이렇게 튑니다:

  • 경합: job이 병렬로 돌 때 나중에 실행된 xcode-select가 전역 경로를 바꿔, 프로덕션 Archive가 beta 컴파일러를 쓰는 사고가 납니다.
  • 캐시 오염: ~/Library/Developer/Xcode/DerivedData를 공유하면 Swift module 버전이 섞여, 로컬 재현 불가한 「유령 버그」가 CI에서만 빨갛게 뜹니다.
  • 디스크 경쟁: Xcode 두 벌 + Simulator runtime 두 벌이면 80GB 이상은 흔합니다. 16GB 메모리 Mac은 beta 풀 빌드 중 swap으로 모든 job이 느려집니다.
한 줄 판단: main을 매일 갱신하고 TestFlight 페이스를 지켜야 하는 팀 → 프로덕션 Runner와 beta Runner는 반드시 분리. 월 1회 릴리스에 beta는 nightly만 도는 소규모 팀만 단일 Mac 시간 분할을 고려할 수 있으며, 그때도 DerivedData는 나눠야 합니다.

2) 듀얼 Runner 아키텍처: label 풀과 workflow 분류

권장 최소 구성——원격 Mac mini M4 두 대(또는 프로덕션 1대 + beta 일일 임대 트라이얼):

RunnerGitHub LabelXcode 버전담당 job
프로덕션 Aself-hosted, macos, ios-prodXcode 16.4 (고정)main Archive, TestFlight, 릴리스 tag
Beta Bself-hosted, macos, xcode26-betaXcode 26 betaios-27-* 브랜치, nightly 적응, API 탐색

workflow는 runs-on으로 하드 분류합니다. beta 브랜치가 ios-prod label을 타는 것은 금지:

.github/workflows/ios-prod.yml — 프로덕션 lane
name: iOS Production CI
on:
  push:
    branches: [main, release/*]
jobs:
  archive:
    runs-on: [self-hosted, macos, ios-prod]
    env:
      DEVELOPER_DIR: /Applications/Xcode_16.4.app/Contents/Developer
      DERIVED_DATA: /var/ci/deriveddata/prod
    steps:
      - uses: actions/checkout@v4
      - name: Build & Archive
        run: |
          xcodebuild -scheme MyApp -configuration Release \
            -derivedDataPath "$DERIVED_DATA" \
            -archivePath build/MyApp.xcarchive archive
.github/workflows/ios-beta.yml — beta lane
name: iOS 27 Beta Adapter
on:
  push:
    branches: [ios-27-*, feature/siri-ai-*]
  schedule:
    - cron: '0 2 * * *'   # nightly, merge 차단 안 함
jobs:
  beta-build:
    runs-on: [self-hosted, macos, xcode26-beta]
    continue-on-error: true   # beta 실패가 main을 막지 않음
    env:
      DEVELOPER_DIR: /Applications/Xcode_26_beta.app/Contents/Developer
      DERIVED_DATA: /var/ci/deriveddata/beta
    steps:
      - uses: actions/checkout@v4
      - run: xcodebuild -scheme MyApp -sdk iphonesimulator build \
          -derivedDataPath "$DERIVED_DATA"

Runner 등록과 label 명명은 GitHub self-hosted runner 문서를 참고하세요. label은 계약——label을 바꾼 사람이 책임집니다.

3) 원격 Mac에 Xcode 26 beta 설치와 다중 버전 공존

베어메탈 원격 Mac에서는 두 Xcode를 /Applications에 나란히 두고 디렉터리 이름으로 버전을 구분할 수 있습니다. beta가 안정판을 덮어쓰지 않게:

  1. Apple Developer Downloads에서 Xcode 26 beta(.xip)를 받아 SSH로 원격 Mac에 로그인한 뒤 /Applications/Xcode_26_beta.app에 풉니다.
  2. 프로덕션 Mac은 DEVELOPER_DIR 환경 변수만 받고, workflow에 절대 경로를 씁니다. job 내부 sudo xcode-select -switch 금지.
  3. 최초 설치 후 xcodebuild -runFirstLaunch와 라이선스 동의를 수동으로 한 번 실행——매 CI job에 넣지 마세요.
  4. iOS 27 Simulator runtime은 beta Mac에 사전 설치: Xcode → Settings → Platforms에서 일괄 설치; workflow에서 -downloadPlatform 단계 삭제.

로컬 개발에서도 여러 Xcode를 쓰는 팀은 Xcode 빌드 지연 해결의 하이브리드 워크플로를 참고하세요. 로컬에서 Swift 작성, 무거운 컴파일은 클라우드 M4에——beta 적응도 동일하고, 16GB 노트북에 beta 인덱싱과 풀 빌드를 얹지 마세요.

4) DerivedData / Pods / SPM 3종 캐시 격리

WWDC 시즌 캐시가 죽는 근본 원인은 컴파일러와 module 형식 변경이지 「캐시가 고장」이 아닙니다. 격리 전략:

표: 프로덕션 vs beta Runner 캐시 경로 (고정 경로 권장, job 간 영속)
캐시 유형프로덕션 경로Beta 경로비고
DerivedData/var/ci/deriveddata/prod/var/ci/deriveddata/betaworkflow에 -derivedDataPath 고정
CocoaPods/var/ci/cocoapods/prod/var/ci/cocoapods/betaCP_HOME_DIR 또는 --deployment
SPM/var/ci/spm/prod/var/ci/spm/betaclonedSourcePackagesDirPath
ModuleCacheDerivedData 부모 디렉터리 종속독립 beta 트리기본 ~/Library 공유 금지

actions/cache는 WWDC 시즌에 부족한 경우가 많습니다: Xcode 메이저 전환 시 cache key가 전부 무효화되고, 수 GB DerivedData 업로드 네트워크 시간이 로컬 디스크보다 손해일 때가 많습니다. self-hosted의 가치는 디스크가 job을 넘어 살아남는 것——두 번째 beta build에서야 20분대에서 10분대로 내려갑니다. Flutter 3종 캐시는 Flutter iOS CI, 서명과 TestFlight는 iOS CI 가속 가이드 Signing 절을 보세요.

Runner 초기화 스크립트 (1회만 실행)
sudo mkdir -p /var/ci/{deriveddata,cocoapods,spm}/{prod,beta}
sudo chown -R $(whoami) /var/ci
# 디스크 모니터: DerivedData 팽창 시 lane별 정리, 디스크 전체 rm 금지
du -sh /var/ci/deriveddata/*

5) 전형적 함정: beta 크래시, SDK 비대, 키체인 혼선

현장에서 자주 보는 사고와 예방책:

  • beta 빨강이 merge를 막음: beta workflow에 continue-on-error: true, required status check로 두지 않기. beta 불안정은 예상 범위이지 엔지니어 탓이 아닙니다.
  • 프로덕션이 beta SDK 사용: Archive 로그에서 DTXcodeDEVELOPER_DIR 확인; prod job 시작에 test "$DEVELOPER_DIR" = "/Applications/Xcode_16.4.app/Contents/Developer" 어설션.
  • 키체인 / Match 인증서 혼선: Runner 두 대는 각각 독립 login keychain; Fastlane match git_url은 공유 가능하나 인증서 import keychain 비밀번호는 기기별 분리. Apple Xcode 지원 매트릭스 참고.
  • 디스크 풀: beta DerivedData + Simulator runtime 두 벌은 급증; beta Mac 512GB SSD 권장, beta 트리에서 14일 이상 미접근 subfolder 주간 cron 삭제.
  • 병렬 Archive OOM: M4 16GB에서 Archive 2개 동시는 swap; 프로덕션 concurrency 1, beta 1–2 조정.

6) 샘플: Runner 분리 전후 동일 저장소 P50 (SLA 아님)

Swift/UIKit + CocoaPods 중간 규모, main 프로덕션 job WWDC 후 1주차 비교——미분리(전원 beta 업그레이드) vs 듀얼 Runner(프로덕션 Xcode 16 유지):

지표미분리 (main beta화)듀얼 Runner 격리
main Archive P50~42 min~11 min (WWDC 전과 유사)
beta 적응 job P50(prod와 한 대 경쟁)~22 min (1주차 풀, 2주차 ~12 min)
main beta 오인 실패율높음 (컴파일러/캐시 혼용)거의 0
필요 Mac 수1대 (겉보기 절약)M4 2대 또는 프로덕션 1 + beta 일일

수치는 저장소마다 다릅니다. 자사 workflow로 48시간 A/B를 돌리세요. 핵심은 「얼마나 빨라지나」가 아니라 main이 beta 대금을 내지 않는다는 점입니다.

7) 48시간 롤아웃 체크리스트

  1. Day 0 오전: 프로덕션 Xcode 버전 잠금, prod workflow에 DEVELOPER_DIR 고정; main에 「Xcode 26 업그레이드」 CI 변경 merge 금지.
  2. Day 0 오후: 원격 Mac mini(또는 48h 일일 임대)를 xcode26-beta Runner로 등록; Xcode 26 beta + iOS 27 runtime 설치.
  3. Day 1: /var/ci/... 캐시 디렉터리 생성; beta workflow 첫 풀 빌드 통과; prod job 영향 없음 확인.
  4. Day 2: beta workflow를 nightly + ios-27-* 브랜치 트리거로 변경; GitHub branch protection에서 beta check required 제거.
  5. 검수: main Archive 3회 연속 < 15 min (프로젝트별); beta job 실패 시 Slack @channel 금지.

두 번째 Mac 월 임대가 맞는지 불확실하면, 일일 beta Mac으로 iOS 27 적응 spike를 끝낸 뒤 본계약 판단——TCO 템플릿은 MacBook Pro vs 클라우드 Mac 결정. 툴체인이 macOS 전용인 이유는 Xcode 툴체인 macOS 전용 글 참고.

8) 자주 묻는 질문 (15개)

1. 원격 Mac 한 대에 Xcode 두 개? 가능. 다른 .app 이름으로 공존; CI에서는 DEVELOPER_DIR 지정, 전역 xcode-select 의존 금지.

2. beta Runner 24GB 필수? 단일 scheme 중간 규모면 16GB M4로 충분한 경우 많음; 다중 target 병렬 Archive는 24GB 권장.

3. 프로덕션 Mac에서 가끔 beta job? 비권장. 시간 분할해도 DerivedData는 최소 분리; 가능하면 물리 분리.

4. 호스팅 macos-latest가 beta Runner 대체? 아님. ephemeral 디스크는 매번 콜드 스타트, WWDC 시즌 bootstrap만 15분+, 영속 캐시 없음.

5. actions/cache로 충분? 메이저 전환 시 key 무효; 큰 DerivedData up/down은 로컬 디스크보다 불리.

6. beta 불안정으로 CI 전체 빨강? 예상 범위; beta lane optional, main merge 차단 금지.

7. prod가 beta 컴파일러 안 쓰는지 확인? Archive 로그 DTXcode 또는 job 시작 DEVELOPER_DIR 어설션.

8. Simulator runtime 매 job 다운로드? 하지 않음. beta Mac 1회 사전 설치, workflow download 삭제.

9. Runner 두 대 다른 리전? 가능. 프로덕션은 팀 가까운 노드; beta는 prod와 동일 리전이 ops 단순.

10. OpenClaw로 beta Runner 관리? webhook 트리거 가능; Gateway는 생략. CI 등록은 OpenClaw CI Runner FAQ.

11. 일일 beta Mac으로 충분? 적응 spike는 충분; nightly 장기 운영은 월 임대가 유리.

12. DerivedData 몇 GB에서 정리? lane당 40GB 초과 시 scheme별 정리; 프로덕션 lane 신중, beta 우선 삭제.

13. Swift 6 동시성 검사 더 엄격하면? beta lane만 strict 플래그, prod는 현 설정 유지하며 단계 이전.

14. WWDC 글과 관계? 그 글은 「왜 느린가」, 이 글은 「Runner 어떻게 나누나」.

15. 48h 안에 2대 필수? main이 beta 안 건드리면 prod 1대로 OK; beta 적응은 일일 Mac 도착 후 lane 오픈.

Beta는 실험, 프로덕션은 반드시 안정

WWDC 후 가장 비용 대비 좋은 구성은 월 임대 프로덕션 Runner 1대 + 온디맨드 beta Mac입니다. 프로덕션 Mac mini M4를 7×24로 TestFlight 페이스를 지키고, beta는 일일 임대로 iOS 27 적응을 시험한 뒤 본계약 여부를 결정하세요. Nuvcloud 베어메탈은 디스크 독점, DerivedData가 job을 넘어 유지; M4 16GB면 대부분 iOS Archive 충분, 24GB는 다중 scheme 병렬용. 저전력·팬리스로 무인 CI에 적합합니다.

WWDC 후 Xcode 26 beta CI를 설계 중인데 main을 실험장으로 쓰고 싶지 않다면, Nuvcloud 클라우드 Mac mini M4가 가장 저렴한 분리 출발점입니다—— 요금제 바로 확인 , 48시간 안에 beta / 프로덕션 Runner를 나누세요.

LIMITED 요금 보기