Vuncloud 블로그
← 개발 일지로

iOS CI가 느린 이유? GitHub Actions xcodebuild 속도 편차

개발 일지 · 같은 PR이 6분일 때도 18분일 때도 · cold/warm 먼저 분리 · 14일 Shadow 벤치마크 · warm P95 14:12→6:05 ·약 9분 소요

Xcode와 터미널이 보이는 Mac 화면, GitHub Actions iOS CI xcodebuild 지연 진단
TL;DR · 먼저 보고, 그다음 손대기
  • 187번 PR 중 86.6%가 warm — 일상 SLA는 warm만 보면 됨. cold를 P95에 섞지 말 것
  • 의존성 변경, 캐시 삭제, scheme 교체 시 cold가 되고, 벽시계 2–3배 차이는 흔함
  • 둘 다 warm이어도 cache miss, 다중 job 디스크 경합, 테스트·서명이 한 job에 있으면 여전히 들쭉날쭉
  • 대략적 순서: 큐 → cold/warm 분리 → 캐시 → 동시 실행 제어 → 마지막에 하드웨어 (워터폴 분해 참고)

전체 대조 데이터 → GitHub Actions 최적화 기둥 · Benchmark

86.6%
Shadow 샘플이 warm build
14:12→6:05
warm P95 (macos-latest → 전용 M4)
2–3×
cold vs warm 전형적 벽시계 격차

1. CI가 추첨 같음: 같은 commit인데 몇 배 차이

GitHub Actions에서 iOS CI 돌리다 보면 이런 장면 익숙할 겁니다. iOS CI가 느린 이유? GitHub Actions xcodebuild 속도 편차를 검색해 왔다면 특히 그렇죠.

  • 같은 commit 재실행해도 벽시계가 2–3배 달라짐
  • 대시보드 P95는 빨갛게 뜨는데, 체감은 「평소 merge는 그렇게 안 기다림」
  • pod install이 30초였다가, 다음엔 멈춘 것처럼 느껴짐
  • 금요일 오후엔 merge 버튼을 꺼려 함 — CI가 또 느린 쪽에 걸릴까 봐

반드시 CPU가 부족한 건 아닙니다. 팀과 14일 Shadow 듀얼런을 해보니 더 흔한 원인은 숫자를 섞어 봤고, 환경도 불안정한 경우였어요 — cache가 안 남고, 디스크가 경합되면 체감이 추첨 같습니다. 칩 교체는 보통 훨씬 뒤 순서입니다.

이 글은 한 가지만 다룹니다: 빌드가 왜 들쭉날쭉한가. job이 runner 큐에서 대기? → 큐 대응. cache 설정, 구매 vs 임대는 cache 전문ROI 글에 맡깁니다.

2. cold와 warm: 한 냄비에 넣지 말기

자주 빠지는 함정: 모든 빌드 시간을 하나의 P95에 넣는 것. 가끔 cold가 끼면 꼬리가 길어져요 — 데이터만 보면 「매일 느리다」인데, 실제 merge 체감은 그렇지 않을 수 있습니다.

구분 기준 · Shadow 대조에서 쓴 정의
  • warm: 의존성 그대로, cache 유지, scheme 동일 — 대부분 증분 컴파일. 「평소 merge」를 대표
  • cold: lock 파일 변경, cache 삭제, target·scheme 교체, runner 첫 실행 — resolve·pod install·대규모 재컴파일

일상 SLA는 warm P50/P95만 보면 됩니다. cold는 별도 라인으로 — merge 체감과 묶지 마세요.

2.1 언제 cold가 되나

macos-latest에서는 cold가 더 흔합니다 — job 끝나면 workspace가 지워지고 cache가 「정착」하기 어렵거든요.

트리거 전형적 추가 시간 로그 키워드
Podfile.lock 변경 +3–8분 pod install, Downloading dependencies
DerivedData miss / 삭제 +5–15분 CompileSwift, 전체 .o 재생성
scheme / target 전환 +2–10분 다른 xcodebuild -scheme
SPM 의존성 resolve 변경 +1–5분 Resolve Package Graph
Xcode 소버전 업그레이드 (macos-latest) 첫 빌드 +10–20분 새 SDK / 모듈 cache 재구축

의존성을 자주 올리면 cold가 늘어납니다 — 머신이 늙은 게 아니라 이번 주에 한 일이 다르다는 뜻이에요. 「Pod 올린 주」와 「평소 개발 주」를 나눠 보고하면 숫자가 말이 됩니다.

2.2 warm인데도 왜 불안정한가

둘 다 warm이어도 벽시계가 30% 정도 흔들릴 수 있습니다. 흔한 원인:

  • cache miss: key에 arm64 누락, 브랜치 미바인딩, 여러 job이 같은 슬롯 경합
  • 같은 org에서 macOS job이 몰리면 디스크·네트워크가 서로 끌어내림
  • 이번엔 main만 빌드, 다음엔 unit+UI test 전체 — 작업량 자체가 다름
  • 변경 범위: Pod 소스 vs SwiftUI 프리뷰 한 줄 — compile 양이 크게 다름
개발자가 GitHub Actions iOS CI 빌드 로그를 보며 xcodebuild warm과 cold 소요 시간 차이를 분석하는 모습

3. 시간이 어디로 가나

workflow 각 step에 타임스탬프를 찍으면 벽시계를 대략 다섯 덩어리로 나눌 수 있어요. 아래는 warm일 때 흔한 분포입니다 (프로젝트마다 다름).

iOS CI wall clock 5 segments (warm · illustrative)
① checkout + env setup        ~0:30 – 1:30
② pod install / SPM resolve   ~0:30 – 2:00   (cold 시 ↑↑)
③ xcodebuild compile+link      ~3:00 – 8:00   (코드 변경 범위에 좌우)
④ tests (simulator / unit)    ~1:00 – 6:00   (선택, 흔히 과소평가)
⑤ archive + codesign           ~1:00 – 4:00   (릴리스 파이프라인)

warm P50 합계 흔한 구간: 6 – 14분

실전 팁: step 시간이나 time으로 pod install, xcodebuild build, xcodebuild test를 각각 봅니다. ②가 5분 넘으면 cold·cache부터; ③이 들쭉날쭉하면 DerivedData·동시 실행; ④가 항상 길면 테스트를 분리하거나 nightly 전량으로.

4. 테스트와 서명: 숨은 발목 잡기

「xcodebuild가 느리다」는 피드백을 쪼개 보면, 테스트나 서명이 같은 build에 포함된 경우가 많습니다.

  • Simulator cold start: CI에서 첫 기동에 몇 분 더 — 예열 없으면 job마다 반복
  • UI Test는 unit보다 한 단계 느림. compile과 한 job에 넣으면 P95가 보기 힘듦
  • 인증서, Keychain, Profile 다운로드 — 호스팅 runner에서 job마다 다시 설정하는 경우
  • Archive·IPA는 릴리스 파이프라인용. PR 검증 시간과 섞지 말 것
짧은 팁 · PR과 릴리스는 따로

PR: build + 가벼운 테스트, warm P95만.
TestFlight / 릴리스: 별도 workflow·별도 지표. 한곳에 넣으면 「평소 merge 대기」가 영원히 안 맞습니다.

5. 14일 Shadow 실측

듀얼 트랙 대조: macos-latest와 전용 Mac mini M4에 각각 187회 PR, Xcode 16.2·CocoaPods 1.15.2 맞춤. 전체 방법은 기둥 Benchmark 참고.

분류 샘플 수 비율 macos-latest P95 전용 M4 P95
warm build 162 86.6% 14:12 6:05
cold build 25 13.4% 19:40 11:20
섞어서 계산 (오판하기 쉬움) 187 100% ~16:00+ ~7:30+

cold와 warm을 섞어 P95를 내면 일상 체감이 대략 15–25% 과대평가되어 「당장 머신 바꿔야 한다」는 결론이 나기 쉽습니다. 더 안전한 방법: merge 체감은 warm, 의존성 올린 주는 cold를 따로 기대.

전용 M4에서도 warm이 cold보다 확실히 빠릅니다 — DerivedData·Pods에 고정된 「집」이 있다는 뜻. cache 설정은 cache 전문에서 자세히.

6. 순서 정하기: 파악부터 cache까지

큐 문제를 제외한 뒤(또는 이미 크지 않다면) 이 순서로 — 먼저 구매 얘기하지 마세요.

  1. 빌드에 태그: cold vs warm (Podfile.lock 변경 여부, cache hit)
  2. 일상 SLA는 warm P95만; cold는 주간 리포트나 별도 라인
  3. DerivedData, Pods, SPM cache 전략 확정 — cache 모범 사례 (준비 중)
  4. macOS job 과밀 금지: self-hosted는 1–2 동시 실행; 호스팅도 workspace 공유 최소화
  5. PR 검증과 릴리스/signing 분리 — 테스트가 merge 지표를 오염시키지 않게
  6. cache까지 했는데도 부족하면 M4 / M4 Pro — 칩과 공수
workflow snippet · warm / cold tag (illustrative)
- name: Classify build type
  run: |
    if git diff --name-only HEAD~1 | grep -q Podfile.lock; then
      echo "BUILD_TYPE=cold" >> $GITHUB_ENV
    else
      echo "BUILD_TYPE=warm" >> $GITHUB_ENV
    fi

- name: Record wall clock
  run: |
    echo "build_type=${BUILD_TYPE}" >> metrics.csv
    echo "wall_sec=$(( $(date +%s) - START ))" >> metrics.csv

7. 자주 묻는 질문 (FAQ)

같은 commit 재실행에 2–3배 차이, 정상인가요?

macos-latest에서는 흔합니다. 한 번은 cache full hit, 다음엔 miss+큐가 겹치면 다른 빌드처럼 보여요. 두 번의 pod install·cache hit 로그부터 보고, 칩 교체는 나중에.

P95는 어떻게 계산해야 하나요?

일상 merge 체감은 warm P95로. 2주에 30샘플 정도면 안정적. cold는 별도 집계나 횟수만 — 섞으면 구매 결정이 치우칩니다.

pod install이 매번 느린데 CocoaPods 탓인가요?

호스팅 runner에서는 Pods가 「살 곳」이 없고 cache key에 브랜치·아키텍처가 빠진 경우가 더 많아요. self-hosted 고정 디스크면 warm 때 30초 이내가 흔합니다.

Mac mini M4로 바꾸면 편차가 사라지나요?

대조에서 warm P95가 크게 줄고(−57%), σ도 수렴(−40%)했지만, cold/warm 미분리·cache 미설계면 전용 Mac에서도 스파이크는 남습니다.

느린 게 큐인가요, build인가요?

로그 맨 앞 Waiting for a runner 대기 시간을 보세요. 큐는 벽시계에 포함되지만 GitHub 분 단위 과금은 아닙니다. 큐가 거의 0인데도 느리면 이 글의 빌드 쪽 → cache로.

더 읽을 거리?

cache YAML·key 설계 → cache 전문; 구매 vs 임대 → ROI 모델월 500회 빌드 선택.

8. 마무리

GitHub Actions iOS CI가 「느리다」는 말은 순수 CPU 부족인 경우가 드뭅니다. 더 자주 겹치는 건:

  1. cold와 warm을 섞어 P95가 올라감
  2. 호스팅 job 종료 시 디스크 초기화로 cache가 안 남음
  3. 테스트·서명과 PR build가 한 job에 섞임

warm P95를 먼저 제대로 잰 뒤 cache → 동시 실행 → 하드웨어 순으로. 14일 Shadow에서 지표·cache만 맞춰도 warm P95가 14:12에서 6:05까지 — 머신 구매를 먼저 결정할 필요는 없었습니다.

DerivedData에 고정된 「집」이 필요하신가요?

Vuncloud Cloud Mac M4 Pro는 1TB 데이터 디스크·actions-runner 사전 설치. DerivedData / Pods를 디스크에 계속 두면 호스팅 runner식 「매번 cold」가 줄어듭니다.

Cloud Mac 요금제 보기 · CI/CD 연동 FAQ

개발 일지 · iOS CI

빠르고 느린 것부터 보고 칩 교체

cold/warm 분리 · 캐시 우선 · Shadow 듀얼런 1주

필러 Benchmark 읽기
한정 혜택 요금제 보기