2026-05-09 Xcode 컴파일러 인덱스 스토어 경로 (INDEX_DATA_STORE_PATH / INDEX_STORE_PATH), 병렬 CI 레인 격리와 임대 Apple Silicon 클라우드 Mac에서의 NVMe 친화적 운영 (HK / JP / KR / SG / US)
병렬 xcodebuild 레인은 모든 부하를 키웁니다—디렉터리가 겹치면 NVMe 임대를 잠식하는 컴파일러 인덱스 샤드도 마찬가지입니다. Xcode는 DerivedData 옆에 인덱스를 두며 Apple은 «엑스코드에서 앱 빌드하기» 문서에서 관계를 설명합니다. 운영팀은 DerivedData/TMPDIR 분리, 병렬 작업 한도, 가독 로그+xcresult 게이트와 결합해 APFS 메타데이터 부하 속에서도 빌드 실패를 설명 가능하게 유지합니다. 2026-05-09 글은 충돌 유형, 경로 패턴, 보존, COMPILER_INDEX_STORE_ENABLE=NO가 타당한 경우를 다룹니다.
Xcode 2026 파이프라인에서도 인덱스 루트 분리가 중요한 이유
증분 컴파일은 예열된 인덱스에 도움이 되지만, CI 플릿이 데스크톱의 단일 사용자 전제를 그대로 가져오는 경우는 드뭅니다. 임대 호스트는 PR을 동시에 멀티플렉스합니다. 충돌은 불투명한 Clang 의존성 스캐너 정체나 중복 모듈 맵을 만듭니다. DerivedData와 함께 인덱스 스토어를 분리하세요—«클린은 성공·더티는 실패» 미스터리를 디버깅한 뒤의 사후 작업이 아니라 처음부터입니다.
공유 빌더에서 인덱스 스토어 충돌의 구조
- 오래된 읽기 쪽 — POSIX 부모 경로를 공유하면 레인 B가 레인 A의 부분 기록 샤드를 읽습니다.
- COW 증폭 — 클리너가 원자적으로 만들어진 아주 작은 샤드를 수천 개 동시에 지우면 APFS 메타데이터 폭풍이 납니다.
- 심볼릭 링크 함정 — 엔지니어가 DerivedData만 빠른 볼륨으로 symlink하고 인덱스 동반 경로를 옮기는 걸 잊습니다.
장시간 병렬 실행에서 iostat을 지켜보세요. 지터는 벽시계 그래프가 움직이기 전에 인덱스 핫스팟을 알려 줍니다.
DerivedData 문서와 연결하는 표준 경로
격리 가이드의 DerivedData 베이스라인을 따른 뒤 Index.noindex/DataStore 스타일 하위 트리를 붙이거나, IDE 기본값 밖에서 순수 xcodebuild를 돌릴 때는 명시적 INDEX_DATA_STORE_PATH를 씁니다. 이름 규칙 예:
BASE="${TMPDIR%/}/job-${JOB_UID}"
DERIVED="$BASE/dd"
IDX="$BASE/clang-index"
export DERIVED_DATA_DIR="$DERIVED"
export INDEX_DATA_STORE_PATH="$IDX"
둘 다 동일한 TMP 부모 아래에 두면 제거 정책이 맞아 떨어지고 xcrun 도구도 단순해집니다.
플래그: INDEX_DATA_STORE_PATH, INDEX_STORE_PATH, COMPILER_INDEX_STORE_ENABLE
현재 워크플로는 Xcode가 Clang에 넘기는 정본으로 INDEX_DATA_STORE_PATH를 우선합니다. 구형 Xcode 릴리스가 얇은 래퍼 안에서 미러 환경 변수를 기대하면 INDEX_STORE_PATH도 동일하게 맞춥니다.
COMPILER_INDEX_STORE_ENABLE=NO가 유효한 경우: 한 번 컴파일하고 버리는 단명 작업—정적 메타데이터 내보내기나 스크립트 자산 검증 등—다만 절약된 I/O가 재실행 시 증분 캐시 손실을 상회하는지 벽시간으로 재보세요.
명시 플래그는 결정적인 xcodebuild -derivedDataPath 선언과 짝을 이뤄 xcbeautify 파이프라인 로그가 근본 원인 분석에서 실제 디렉터리로 거슬러 올라가게 합니다.
Mac mini M4 임대에서 병렬 레인 산출
홍콩, 도쿄, 서울, 싱가포르, 미국 등에서는 CPU뿐 아니라 통합 메모리를 존중해 동시 레인을 배분합니다. 레인이 늘수록 해시 디렉터리 때문에 인덱스 팬아웃이 비선형으로 커집니다. APFS 단편화 지표가 오르면 동시성을 낮춥니다.
불변 조건
- 동시 빌드 두 개를 같은 DerivedData 베이스 이름으로 향하게 하지 않습니다.
- xcresult 번들을 아카이브한 뒤 차가운 인덱스를 디스크에서 치웁니다.
- 풀별로 고정된 Xcode 메이저 버전에 레인 수를 맞춥니다.
보존 일정과 APFS/NVMe 쓰기 증폭
인덱스 디렉터리는 컴파일 객체보다 빨리 어지럽혀집니다. 중단 뒤에도 샤드가 오래 남기 때문입니다. SLA 일수보다 오래된 INDEX_DATA_STORE_PATH를 야간에 쓸어 가는 작업이 급한 rm -rf보다 낫습니다. 아카이브 압축 전에 수백만 개 작은 파일을 압축기가 견디는지 확인하세요—종종 rsync식 하드링크 승격이 더 낫습니다.
9단계 롤아웃 체크리스트
- 리전별 현재 DerivedData와 인덱스 겹침을 재고합니다.
- 오케스트레이션에서 유도한 고유 경로 토큰을 정의합니다.
- 래퍼에 환경 내보내기를 주입합니다(GitLab shell, Jenkins agent, GH Actions shim).
- xcbeautify 가이드에 맞춰 구조화 로그를 맞춥니다.
- 장시간 병렬 리허설로 APFS 단편화 프록시를 측정합니다.
- COMPILER_INDEX_STORE_ENABLE=NO 옵트아웃 레인을 문서화합니다.
- 주간 디스크 기울기가 예산을 넘으면 알림을 연결합니다.
- 온콜에게 인덱스 디렉터리 해부를 교육합니다.
- plist와 래퍼 스크립트 롤백 tarball을 포함한 인프라 PR을 승격합니다.
SLO 표: 컴파일러 인덱스 위생
| 신호 | 임계값 | 조치 |
|---|---|---|
| 공유 인덱스 부모 감지 | 동시 작업이 하나라도 있을 때 | 즉시 실패; 경로 토큰 확대 |
| NVMe 인덱싱 시간 | 벽시간 중 인덱싱 > 12% | 선택적으로 NO 전환 + 레인 재균형 |
| 크래시 후 복구 | 월 수동 정리 > 30분 | TTL 스윕 자동화 |
FAQ
| 질문 | 실무 답변 (2026-05-09) |
|---|---|
| 원격 Xcode Cloud에도 해당? | 개념은 그대로 옮겨집니다—워커가 PR을 멀티플렉스하는 곳에서는 명시 루트가 암묵 기본값을 이깁니다. |
| 빌드마다 깨끗한 호스트? | 단명 머신 이미지도 RAM 디스크 안에 고유 인덱스 경로가 필요합니다. 병렬 스모크가 동시에 뜰 때 레이스 버그를 피합니다. |
Mac mini M4 베어메탈이 인덱스 노이즈를 예측 가능하게 하는 이유
통합 메모리는 과구독 하이퍼바이저를 나눠 쓰는 VM보다 PCIe 왕복을 줄여 Clang 인덱스 작성기를 캐시 핫 상태로 더 오래 유지합니다. 플릿 규모는 지역별 요금으로 조정하고, 멈춘 컴파일 단계를 대화형으로 디버깅할 때는 SSH 접근 가이드를 활용하세요.