Xcode 컴파일 캐시 원리와 적중(히트) 조건 대조표
Xcode 컴파일 캐시의 실체는 주로 Derived Data 아래 객체 파일·Swift 모듈·인덱스·빌드 기술자입니다. 소스·생성 코드·OTHER_SWIFT_FLAGS 등 입력과 컴파일러·SDK 지문이 맞으면 재컴파일을 건너뛰기 쉽습니다. 원격 Mac의 iOS CI에서 잡마다 작업 디렉터리를 버리면 -derivedDataPath가 흔들려 적중률이 떨어지기 쉽습니다.
| 조건 | 캐시 적중에 미치는 영향 | 운영 팁 |
|---|---|---|
| Xcode·Swift 버전 | 불일치 시 대부분 미스 | xcodebuild -version, swift --version를 캐시 키에 포함 |
| Derived Data 경로 | 고정 경로가 안정적 | -derivedDataPath "$CI_DERIVED_DATA"를 항상 명시 |
| SwiftPM 의존성 | Package.resolved 변경 시 무효화 |
-clonedSourcePackagesDirPath "$CI_SPM_DIR"로 공유 캐시 |
| 빌드 설정 전환 | Debug↔Release 등으로 무효화 | 시나리오별로 DD 하위 디렉터리 분리 |
캐시 키 예: runner.os + lockfile 해시 + Xcode 라벨 + scheme. CocoaPods·클론 단계와 맞추려면 Git·CocoaPods CI 가속과 함께 설계하세요.
원격 노드 예열(Derived Data 워밍)과 정리(클린업) 전략
동일 러너를 장기 사용하면 빌드 가속에 유리합니다. 예열은 의존성 해석 + 일반 build, 정리는 LRU로 오래된 DD부터 지우는 방식이 균형이 좋습니다. 아래는 복사해 쓸 수 있는 환경·명령 예시입니다.
- 도구체인 고정:
export DEVELOPER_DIR=/Applications/Xcode_16.2.app/Contents/Developer - SPM 선해결:
xcodebuild -scheme "YourApp" -resolvePackageDependencies -clonedSourcePackagesDirPath "$CI_SPM_DIR" -derivedDataPath "$CI_DERIVED_DATA" - 시뮬레이터 빌드 본체:
xcodebuild -scheme "YourApp" -destination 'platform=iOS Simulator,name=iPhone 16' -derivedDataPath "$CI_DERIVED_DATA" -clonedSourcePackagesDirPath "$CI_SPM_DIR" build - CI에서 인덱스 부하 완화:
export COMPILER_INDEX_STORE_ENABLE=NO(CI 전용; 로컬과 분리)
- 사용률 경고: 데이터 볼륨 85% 초과 → 로그·알림. 노드 안정성 모니터링과 연동.
- 적극 정리: 90% 부근이거나 여유가 20GB 미만 → 해당 프로젝트 DerivedData 하위만 삭제(전체 삭제는 최후 수단).
- 용량 점검:
du -sh "$CI_DERIVED_DATA"/* 2>/dev/null | sort -hr | head - 시뮬레이터 비대화: 주간 점검에
xcrun simctl delete unavailable포함
clean build와의 파라미터(플래그) 취사선택
항상 clean은 재현성과 맞바꿔 비용이 커지고, 항상 증분은 빠르지만 캐시 손상 리스크가 있습니다. 아래 의사결정 매트릭스로 PR·나이틀리·제출용 파이프라인에 배치하세요.
| 파이프라인 | 권장 스탠스 | xcodebuild 측 판단 |
|---|---|---|
| PR·피처 | 증분 우선 | 동일 -derivedDataPath 유지, 기본적으로 clean 생략. 실패 시 부분 clean만. |
| 나이틀리 통합 | 주간 또는 태그 기준 full clean | xcodebuild clean -scheme … 또는 DD 하위 폴더 삭제를 스케줄. |
| 릴리스·아카이브 | 클린 쪽 | 산출물 재현성 우선. 캐시는 의존성 fetch에 두고 컴파일은 클린 검토. |
| 서명·임베딩 오류 다발 | 범위 한정 clean | 프로비저닝·Entitlements 변경 후 해당 scheme의 DD만 삭제 후 재실행. |
pod install 캐시 복원과 Derived Data를 같은 러너에서 돌리면 헤더 검색 경로 불일치가 줄어듭니다. 풀·재시도 쪽은 원격 Mac 풀 안정성 FAQ도 참고하세요.
실패 폴백과 디스크 워터마크 임계 FAQ
폴백 순서: (1) 동일 DD에서 재시도 → (2) 해당 프로젝트 DD만 삭제 → (3) 새 -derivedDataPath → (4) 러너 로테이션 또는 전 DD 삭제.
- 여유(MB):
df -m "$CI_DERIVED_DATA" | awk 'NR==2{print $4}'— 예: 15360MB(약 15GB) 미만 경고, 10240MB 미만이면 빌드 중단 검토. - 사용률(%):
df -h "$CI_DERIVED_DATA" | awk 'NR==2{gsub(/%/,"",$5); print $5}'— 85 초과 알림, 92 초과 시 신규 잡 스로틀. - 재시도: 컴파일 단계 2~3회, 지수 백오프 30~90초. 동시 다발 빌드로 IOPS가 포화면 병렬도 하향.
Q. ModuleCache 관련 오류가 늘었습니다.
A. Xcode 업데이트 직후 흔합니다. 해당 DerivedData를 지우고 DEVELOPER_DIR가 여러 Xcode를 가리키지 않는지 확인하세요.
Q. 병렬 잡에서 링크가 간헐적으로 실패합니다.
A. 동일 -derivedDataPath를 다중 프로세스가 공유하는 경우가 많습니다. 잡별 하위 디렉터리 또는 락을 두세요.
Q. 캐시 효과를 지표로 보고 싶습니다.
A. xcodebuild 로그의 컴파일 건수·경과 시간과 DD 크기 이동 평균을 대시보드화하세요. 운영 문의는 고객 지원 페이지를 이용할 수 있습니다.
맺음말
요약: Xcode 컴파일 캐시는 -derivedDataPath 고정과 도구체인 지문을 포함한 캐시 키로 적중률을 올리기 쉽습니다. Derived Data 예열은 SPM 해석 + 일반 build, 정리는 사용률 85%/90%와 여유 용량의 이단 임계가 다루기 쉽습니다. clean build는 릴리스 계열에, PR은 증분에 두면 빌드 가속과 노드 안정성을 함께 잡을 수 있습니다. 전용 원격 Mac에서 DD를 장기적으로 키우려면 아래 앵커 텍스트로 이동하세요(로그인 없이 열람 가능한 페이지만 연결했습니다).