결론부터 말하면, 하루 약 500회 iOS CI 빌드라면 대부분 팀에 Mac mini 8대는 필요 없고 Apple Silicon 클라우드 Mac 3대면 충분합니다——전제는 GitHub Actions Job을 계층화하고 셀프호스트 Runner로 빠른 큐와 Release 큐를 분리하는 것입니다. 각 Mac에서 전체 Archive를 동시에 3개 돌리지 마세요.
3개월 전, iOS 팀의 Xcode CI 환경을 인수했습니다. 당시 전제는 다음과 같았습니다.
- 개발자 18명
- 앱 2개(Monorepo 공유)
- CI는 GitHub Actions만 사용
- 하루 약 500회 macOS Job(PR·단위 테스트·야간 배포 포함)
조달안은 Mac mini 8대를 사서 온프레미스 셀프호스트 Runner로 돌리는 것이었습니다. 먼저 2주 workflow 로그를 Job 유형별로 쪼개 보니 체감과 실제가 많이 달랐습니다——약 70%가 PR 검증·통합 빌드, 20%가 Simulator 단위 테스트, Archive+업로드는 약 10%(TestFlight 업로드를 따로 잡으면 Archive와 Upload를 더 나눌 수 있습니다. 아래 그림 참고).
그림 1 · 하루 약 500회 iOS CI 구성(해당 팀 GitHub Actions 2주 실측)
용량 계산: 91 기시에서 63 기시로
500회/일을 24시간에 펴면 평균 약 21회/시——하지만 병목은 피크입니다. 북미·유럽 오전 머지, 배포 전날 PR 폭주 때 평균의 3~5배가 흔합니다. 용량은 피크 대기열로 설계하고, 자정 평균만 보면 안 됩니다.
두 번째 변수는 Job당 기시입니다. Simulator 단위 테스트 4~8분, 의존성 해석 포함 PR 빌드 12~20분, Release Archive+공증+업로드는 25~45분까지 갑니다. 해당 팀 2주 P50 기준 경 Job 6분·중 Job 35분. Archive가 30%라고 잘못 가정하면 「Mac 8대 필수」가 나오지만, 500회 중 무거운 Job은 훨씬 적습니다.
캐시 없음 때 경 325 + 중 175로 하루 약 91 기시, 3대 Mac 24시간 상한 72 기시를 넘습니다. DerivedData/SPM 캐시, L2 직렬, 라벨 분리 후 경 Job 평균 4분·중 Job 핫패스 22분이면 합계 약 63 기시. 피크 계수 1.3 전후면 수용 가능——「3대면 된다」의 수학입니다.
그림 3 · 일일 macOS 기시 수요(동일 500회/일 모델)
Xcode CI 계층화: Archive와 PR을 같은 Mac Runner 큐에 넣지 마세요
500회/일을 버티는 GitHub Actions 파이프라인은 거의 항상 3단 Xcode CI로 나눕니다.
- L0: SwiftLint, 단일 모듈 빌드——
macos-fast라벨. - L1: PR 통합 빌드(Archive 없음)——같은 Fast Mac Runner, 대당 경 Job 2병렬.
- L2: Archive, 공증, TestFlight——
macos-archive, 대당 동시 1개.
GitLab CI, Buildkite, Jenkins macOS Agent도 마찬가지로 라벨 라우팅을 쓰고, 뒤섞인 한 큐로 두지 않습니다. Buildkite 버스트는 Buildkite 자체 macOS Agent와 일일 클라우드 Mac, Runner 풀 상시 vs 탄력은 GitHub Actions macOS Runner 탄력 풀 vs 상시를 참고하세요.
클라우드 Mac 3대 역할 분담(토폴로지)
실제 운영한 정적 3노드는 다음과 같습니다(호스트명은 자유, 역할은 유지 권장).
| 노드 | Runner 라벨 | 역할 | 병렬 |
|---|---|---|---|
| Mac-A | macos-fast |
PR Build, Unit Test | L0/L1 ×2 |
| Mac-B | macos-fast |
Mac-A와 대칭, 빠른 큐 | L0/L1 ×2 |
| Mac-C | macos-archive |
Archive, 공증, Upload | L2 ×1 |
그림 2 · 3노드와 큐(GitHub Actions 셀프호스트 Runner)
fast 2대가 처리량, release 1대가 확정적 출시를 담당합니다. 배포일 L2가 넘치면 Mac-A에 임시 macos-archive를 붙일 수 있으나, 그동안 L0 병렬은 끄세요. Keychain·DerivedData 경합으로 서명이 간헐 실패합니다. 3대 Xcode 마이너는 Xcode 릴리스 노트로 고정하세요.
GitHub Actions Mac Runner가 대기열이 되기 쉬운 이유
많은 팀이 먼저 GitHub 호스팅 macOS Runner 분 패키지를 사고 PR이 늘면 줄을 섭니다. 원인은 「GitHub가 느림」이 아니라 (1) 조직 macOS 동시 한도, (2) workflow마다 매번 전체 Archive, (3) 셀프호스트 Mac Runner를 Job 유형별로 나누지 않아 경 Job이 중 Job에 막히는 것입니다. 전용 클라우드 Mac 3대 이전 호스팅 Runner queue_wait P95는 40분 이상이었고, fast/archive 이중 큐 후 L1 P95는 8분 이내로 내려갔습니다.
정석은 클라우드 Mac 3대를 기선 셀프호스트 풀로 두고, OSS 주나 극단 피크에만 호스팅 Runner로 L0를 보강하는 것——비용을 줄이면서 비밀을 매주 옮기지 않습니다.
셀프호스트 Runner vs Xcode Cloud
Xcode Cloud는 Apple 생태계에 깊이 묶이고 운영 제로를 원하는 팀용. 셀프호스트 Mac Runner는 큐·캐시 키·Archive와 사내 Jenkins/Buildkite 혼용을 직접 잡고 싶은 조직용입니다.
| 항목 | Xcode Cloud | 클라우드 Mac + 셀프호스트 Runner |
|---|---|---|
| 요금 | 분 패키지 + 동시 한도 | 클라우드 Mac 구독/일일, 기시 가시 |
| 큐 | 플랫폼 공통 | fast/archive 라벨 자체 관리 |
| 비밀 | ASC 연동 편함 | Match/Keychain 자체 runbook |
| 적합 | 저빈도 배포·적은 커스텀 | 하루 500+회 iOS CI/CD |
분 패키지 소진 시 전환 신호는 Xcode Cloud 한도와 일일 클라우드 Mac으로 Archive 인수 FAQ를 보세요.
이 팀이 Xcode Cloud를 고르지 않은 이유
Xcode Cloud를 검토했지만 GitHub Actions + 셀프호스트 Runner가 남았습니다. (1) 백엔드·Android가 이미 GitHub, CI 이중화 회피. (2) 커스텀 캐시 키·Monorepo 매트릭스 필요. (3) 배포 주 Job 수가 분 패키지 쾌적 구간을 넘어 대기열을 자체 통제 불가. Xcode Cloud가 나쁜 게 아니라 「하루 500회·큐 통제」 목표와 어긋났습니다.
Bitrise vs 자체 Mac Runner 비용 감
Bitrise 등 모바일 DevOps SaaS는 Agent 운영을 줄이고 동시 플랜으로 과금합니다. 18명·앱 2·하루 약 500 Job 규모면 연간 비용이 클라우드 Mac 3대 구독을 넘는 경우가 많고 Archive 동시도도 플랜 티어에 묶입니다. Runner를 건드리기 싫은 스타트업에 맞습니다. 2주 안에 셀프호스트 Mac Runner를 꾸리는 팀은 보통 3~6개월에 노드 비용을 회수합니다. Bitrise 사용 중에도 L2만 release 전용 노드로 옮기는 부분 이전이 가능합니다.
Buildkite Mac Agent 장단
Buildkite는 큐를 클라우드에 두고 Agent를 자체 Mac에 올려 탄력·Artifact 보존에 강합니다. 반면 편성 학습 비용이 있어 Mac 3대만으로 도입하면 과할 수 있습니다. 해당 고객은 PoC에서 버스트는 우수했으나 최종적으로 GitHub Actions 네이티브 셀프호스트 Runner를 선택——개발이 YAML 한 체계에 익숙하기 때문입니다. 이미 Buildkite가 있다면 3대 클라우드 Mac 라벨 전략은 본문 fast/archive 토폴로지와 같습니다.
클라우드 Mac CI vs 온프레 Mac mini
온프레 Mac mini 8대: CapEx·감가·정전·인증서 감사. 클라우드 Mac 3대: OpEx 예측 가능, 일일 PoC, Git 저장소에 가까운 리전 선택. 대당 하루 14시간 넘는 단조 컴파일·스펙이 수년 고정이면 로컬 CI도 타당합니다. 클라우드 Mac CI는 피크·외주 주·심사 시즌 공증 채널에 맞습니다. 이 팀은 개발용 사무실 Mac 2대만 남기고 무거운 Xcode CI는 클라우드로——8대 mini 유휴를 피했습니다. CircleCI 클라우드 macOS vs 클라우드 Mac Runner SLO는 CircleCI 클라우드 macOS vs 셀프호스트 Runner FAQ를 참고하세요.
큐 SLO: 감이 아니라 데이터로 4대째 결정
모니터링 권장: queue_wait_seconds(P95), run_duration L0/L1/L2 버킷, cache_hit_ratio, l2_concurrent(3 초과 지양). 예: L1 대기 P95 < 8분, L2 P95 < 25분. L2가 3일 연속 기준 초과·캐시 적중 이미 60% 초과면 4대째 release 검토.
캐시: 63 기시의 지렛대
DerivedData 키는 branch + Xcode버전. SPM/CocoaPods lock 변경 시 bust. fast 노드는 읽기 전용 공유, release는 로컬 NVMe에 L2 DerivedData. 서명 재료는 vault 경유, 캐시에 넣지 않음. 키에 macOS/Xcode 마이너가 없으면 업그레이드 후 「적중했는데 링크 실패」가 납니다. 캐시가 63 기시로 내리는 핵심 요인입니다.
GitHub Actions 셀프호스트 Runner 최소 설정
3대 등록: macos-fast ×2, macos-archive ×1. L2에는 concurrency 필수, 배포 Job 상호 cancel 방지.
concurrency:
group: ios-archive-${{ github.ref }}
cancel-in-progress: false
jobs:
archive:
runs-on: [self-hosted, macos-archive]
steps:
- uses: actions/checkout@v4
- run: xcodebuild archive -scheme App -archivePath build/App.xcarchive
release 노드는 전용 macOS 사용자 + Match. 재시작 후 Keychain 해제 스크립트를 먼저 돌린 뒤 야간 큐를 엽니다. 무인 운영은 xcodebuild 공식 문서와 Fastlane을 참고하세요.
배포일: 500회가 650회가 되면
순서: (1) 비핵심 L0 중지. (2) 호스팅 Runner는 L1만 보강. (3) 48시간만 4대째 클라우드 Mac 일일 추가. L2를 대당 2병렬로 고정하지 마세요——공증 랜덤 실패로 갚습니다.
4대째가 진짜 필요한 조건
- L2 대기 P95가 1주 연속 40분 초과, 캐시는 이미 최적화.
- Monorepo 앱 5개 초과, release 1대로 야간 창 부족.
- 모든 PR 전체 Archive——먼저 Job 구조 수정, 기계 추가는 그다음.
안티패턴
모든 PR Archive, Mac Runner 라벨 미분리, 16GB M4에서 Archive 2동시, 캐시 키에 브랜치 없음, 실패율만 보고 queue_wait 무시——「3대 부족」으로 오진해 8대 조달로 갑니다.
FAQ: 검색에 잡히는 짧은 답
하루 500회 iOS 빌드에 Mac 몇 대?
Job을 PR/단위 테스트/Archive로 나누고 DerivedData 캐시가 되면 대부분 팀은 Apple Silicon 클라우드 Mac 3대면 충분: Fast Mac Runner 2 + Release Mac Runner 1. 500회의 절반이 넘게 전체 Archive면 파이프라인을 먼저 고치거나 4대째 release를 계획하세요.
GitHub Actions Mac Runner 동시 Job 수?
16GB M4 기준: 경 Job 2개(PR Build, Unit Test) 또는 Archive 1개. 「Archive 2개」를 상시화하지 마세요.
Archive를 고병렬로 못 하는 이유?
메모리 경합으로 swap, 디스크 큐 지연, Keychain 잠금과 codesign 충돌이 겹쳐 재현 어려운 타임아웃이 납니다. 안정적 컴파일 오류가 아닙니다.
클라우드 Mac이 Xcode Cloud보다 싸나?
장기·고빈도 iOS CI/CD에 전용 셀프호스트 Runner와 비밀 상주가 필요하면 클라우드 Mac 3대 기선 풀이 분 과금보다 읽기 쉬운 경우가 많습니다. 저빈도·운영 제로 우선이면 Xcode Cloud를 먼저 시험하세요.
Bitrise vs 클라우드 Mac 3대?
Bitrise는 운영을 줄이고 빠른 론칭에 맞습니다. 하루 약 500 Job에 큐·캐시를 잡으려면 셀프호스트 Mac Runner + 클라우드 Mac 연간 비용이 낮은 경우가 많고 L2 동시는 직접 정의합니다.
VPSSpark: Fast 2 + Release 1 클라우드 Mac 기선 풀
「하루 500회에 Mac 몇 대?」를 계산 중이라면 먼저 2주 로그로 그림 1 비중을 그리고, 본문 63 기시 모델이 성립하는지 검증하세요. VPSSpark 클라우드 Mac mini M4 / M4 Pro는 일일 PoC와 장기 구독을 지원하며 GitHub Actions 셀프호스트 Mac Runner로 PR과 Archive를 다른 큐에 올릴 수 있습니다.
클라우드 Mac 요금제 또는 VPSSpark 홈에서 리전을 고른 뒤 실제 workflow로 버킷해 3대로 충분한지 결정하세요——먼저 8대를 사지 마세요.