Vuncloud 블로그
← 필드 노트로 돌아가기

GitHub Actions iOS CI가 왜 느릴까? CocoaPods / SPM / DerivedData 캐시 최적화 (2026)

필드 노트 · GitHub Actions에서 CocoaPods / SPM / DerivedData 캐시 · workflow 예제 ·약 12분

GitHub Actions iOS CI 캐시 최적화: CocoaPods SPM DerivedData Xcode 빌드 지연
TL;DR · 먼저 결론

GitHub Actions iOS CI가 느릴 때 범인은 CPU가 아니라 캐시가 없거나 key가 어긋난 경우가 많습니다. 핵심은 세 군데입니다:

  • CocoaPods: Pods/ 미캐시 → 매 run마다 pod install 처음부터
  • Swift Package Manager(SPM): 의존성 그래프를 매번 resolve, .build가 job마다 지워짐
  • Xcode DerivedData: 콜드 빌드로 Swift 전량 컴파일·모듈 재구축

CocoaPods / SPM / DerivedData 캐시를 제대로 연결하면 warm 빌드 벽시계가 보통 30%–60% 줄어듭니다(Shadow 대조는 워터폴 분해).

30–60%
warm 빌드 시간 전형적 단축 폭
3
CocoaPods · SPM · DerivedData
1–5분
캐시만으로 흔한 절약(레이어당)

1. GitHub Actions iOS CI가 느리게 느껴지는 이유

먼저 나오는 말은 대개 이렇습니다. 「macos-latest가 약한 거 아냐?」「M4나 상위 머신으로 갈아타야 해?」

현장의 Xcode CI 지연에서는 병목이 CPU보다 눈에 잘 안 띄는 세 가지 비용에 몰리는 경우가 많습니다.

  1. 의존성 재 resolve(CocoaPods / SPM)
  2. DerivedData 콜드 스타트(전량 컴파일)
  3. actions/cache 미스 — 매번 첫 빌드처럼 느껴짐

GitHub Actions는 이를 증폭합니다. runner는 일회용(job마다 깨끗한 디스크), 캐시가 저절로 남지 않고, 다중 브랜치·다중 job에서 key가 쉽게 오염됩니다. 같은 commit인데 빠른 run과 느린 run을 추적 중이라면, 먼저 cold/warm을 나눈 뒤 이 글의 캐시 설계에 맞춰 보세요.

2. 벽시계가 사라지는 지점

2.1 CocoaPods(Pods 캐시)

전형적 콜드 비용: pod install3–8분.

본질: 매 CI에서 pod install을 처음부터 — resolve, 다운로드, 통합을 전부 다시.

대응: actions/cachePods/ 저장. key는 Podfile.lock 해시 + github.ref + arm64. CI에서는 pod install --deployment.

2.2 Swift Package Manager(SPM)

전형적 비용: 패키지 그래프 resolve에 1–5분.

본질: 매 run 재 resolve, .build 삭제, Package.resolved가 key에 없음.

대응: ~/Library/Caches/org.swift.swiftpm.build 캐시. key에 Package.resolved 해시(§3.2).

2.3 Xcode DerivedData

전형적 콜드 증분: 전량~준전량 컴파일 5–15분.

본질: DerivedData 미재사용 → Swift 전량 컴파일, 에셋 재처리, 모듈 재구축.

대응: xcodebuild -derivedDataPath DerivedData로 경로 고정 후 해당 경로 캐시(§3.3).

팀이 GitHub Actions workflow를 검토: CocoaPods·SPM·DerivedData 캐시와 iOS CI 최적화

3. 동작하는 GitHub Actions iOS CI 캐시 설정

runs-on: macos-latest용. 아래 세 블록을 같은 job에 pod install / xcodebuild 앞에 넣으세요(저장은 actions/cache@v4가 자동 처리).

3.1 CocoaPods 캐시(필수)

CocoaPods cache · GitHub Actions
- name: Restore Pods cache
  uses: actions/cache@v4
  with:
    path: Pods
    key: pods-arm64-${{ github.ref }}-${{ hashFiles('**/Podfile.lock') }}
    restore-keys: |
      pods-arm64-${{ github.ref }}-

- name: Pod install
  run: pod install --deployment

3.2 SPM 캐시(필수)

SPM cache · iOS CI
- name: Restore SPM cache
  uses: actions/cache@v4
  with:
    path: |
      ~/Library/Caches/org.swift.swiftpm
      .build
    key: spm-arm64-${{ github.ref }}-${{ hashFiles('**/Package.resolved') }}
    restore-keys: |
      spm-arm64-${{ github.ref }}-

3.3 DerivedData 캐시(임팩트 큼)

DerivedData cache · xcodebuild
- name: Restore DerivedData cache
  uses: actions/cache@v4
  with:
    path: DerivedData
    key: dd-arm64-${{ github.ref }}-${{ hashFiles('**/Podfile.lock') }}
    restore-keys: |
      dd-arm64-${{ github.ref }}-

- name: Build iOS
  run: xcodebuild -scheme MyApp -derivedDataPath DerivedData ...

스텝 시간을 비교하기 전에 로그에서 Cache hit occurred를 확인하세요. 미스면 key와 path부터 — Xcode 버전 탓으로 돌리지 마세요.

4. cache key 설계(여기 건너뛰지 말기)

iOS CI 최적화가 runner가 아니라 key에서 무너지는 사례, 현장에서 흔합니다.

✔ 넣어야 할 것 ❌ 흔한 실수
아키텍처(arm64) arm64/x86 미분리 — runner 바꾸면 전부 미스
브랜치(github.ref) 락 파일만 — DerivedData가 브랜치 간 오염
락 파일 해시 restore-keys가 너무 넓음(예: dd-만) → 잘못된 히트
restore-keys 폴백

락 파일이 바뀌면 dd-arm64-${{ github.ref }}- 같은 접두사로 일부 재사용 가능. 다중 scheme이면 key에 ${{ matrix.scheme }}. 같은 runner에서 병렬 job이 DerivedData 루트를 공유하지 않게 — ${{ github.run_id }} 하위 디렉터리로 격리.

5. self-hosted / Cloud Mac(고급)

Mac mini나 Cloud Mac self-hosted runner라면 actions/cache에만 묶이지 않습니다 — 디스크가 남아 warm이 더 안정적입니다.

  • DerivedData 경로 고정
  • Pods 디렉터리 고정
  • 온디스크 warm 캐시(job당 30–90초 업로드/다운로드 생략)
self-hosted 고정 경로
export DERIVED_DATA=/Volumes/Data/DerivedData/App-${{ github.run_id }}
export PODS_ROOT=/Volumes/Data/Pods/${{ github.ref_name }}

job 전체 예시와 1TB 데이터 디스크 메모: 아래 workflowCI/CD 연동 FAQ.

self-hosted · 고정 DerivedData + Pods
env:
  DERIVED_DATA: /Volumes/Data/DerivedData/App-${{ github.run_id }}
  PODS_ROOT: /Volumes/Data/Pods/${{ github.ref_name }}

jobs:
  build:
    runs-on: [self-hosted, macos-m4-ios]
    steps:
      - uses: actions/checkout@v4
      - name: Prepare dirs
        run: mkdir -p "$DERIVED_DATA" "$PODS_ROOT"
      - name: Pod install
        run: pod install --deployment
      - name: xcodebuild
        run: xcodebuild -scheme MyApp -derivedDataPath "$DERIVED_DATA" build

6. 캐시 미스 ≠ 느린 runner(흔한 오독)

GitHub Actions iOS CI가 느리다고 runner나 Xcode 버전 탓을 하기 쉽습니다. 실제로는 아래가 더 많습니다.

보이는 현상 더 그럴듯한 원인
갑자기 빌드가 느려짐 캐시 미스
P95가 흔들림 cold 빌드가 warm 통계에 섞임
무작위로 느려짐 병렬 job의 DerivedData 경합
의존성이 처음부터 재빌드 cache key 오설정

iOS CI가 느린 이유? GitHub Actions xcodebuild 속도 편차와 함께 보세요: cold/warm 분리 → 캐시 조정 → 그다음 하드웨어 평가(2026년, iOS CI/CD가 Mac mini M4에서 도는 이유).

7. 실측 개선 폭

캐시만 고쳤을 때 전형적 절약:

레이어 콜드 미스 시 추가 캐시 연결 후
CocoaPods 3–8분 warm에서 보통 <30초–3분
SPM 1–5분 히트 시 resolve 대폭 단축
DerivedData 5–15분 warm은 대부분 증분 컴파일

14일 Shadow에서 캐시 최적화만으로 warm 벽시계가 약 −1:40. 큐 제거와 self-hosted 고정 디스크를 겹치면 warm P95는 14:12 → 6:05(−57%) — GitHub Actions macOS 러너 최적화 참고.

8. FAQ

GitHub Actions iOS CI는 왜 느린가?

CPU보다 CocoaPods / SPM / DerivedData가 미캐시이거나 key가 어긋난 경우가 많습니다. 일회용 runner가 미스를 키웁니다.

GitHub Actions에서 CocoaPods를 캐시하려면?

Pods/를 캐시. key: pods-arm64-${{ github.ref }}-${{ hashFiles('**/Podfile.lock') }}. §3.1 참고.

iOS CI에서 SPM을 캐시하려면?

swiftpm 글로벌 디렉터리와 .build를 캐시. key는 Package.resolved에 바인딩. §3.2 참고.

DerivedData 캐시 path는 어떻게?

actions/cachepathxcodebuild -derivedDataPath와 일치해야 합니다. 시스템 기본 경로는 필요 없습니다.

캐시가 너무 큼?

GitHub은 항목당 약 10GB 상한. DerivedData는 scheme별로 key를 나누거나 self-hosted 고정 디스크에 두고 업로드를 생략.

macos-latest vs self-hosted?

호스팅은 actions/cache만 가능, job 사이에 지워질 수 있음. self-hosted는 /Volumes/Data 고정으로 warm이 안정적. GitHub Actions macOS 러너 최적화에서 대조.

9. 정리와 관련 가이드

iOS CI 최적화에서 ROI가 큰 건 칩 교체 전에 CocoaPods·SPM·DerivedData 캐시를 연결하는 것 — workflow는 오늘부터 시험할 수 있습니다.

같은 시리즈:

DerivedData와 Pods 경로를 고정하고 싶다면?

Vuncloud Cloud Mac M4 Pro는 1TB 데이터 디스크 포함 — self-hosted iOS CI용. actions/cache 왕복을 줄이고 warm을 안정시키기 좋은 구성입니다.

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

필드 노트 · iOS CI

GitHub Actions iOS CI가 느리다면? 이 세 캐시부터

CocoaPods · SPM · DerivedData · workflow 예제

폭포 차트 −1:40
한정 혜택 요금제 보기