장기간 아카이브와 자동화 테스트를 수행하는 클라우드 Mac에서 가장 흔한 장애 원인이 반드시 코드인 것은 아닙니다. Xcode는 DerivedData, 아카이브, 기기 지원 파일, 시뮬레이터 데이터를 지속적으로 기록합니다. 디스크가 거의 가득 차면 컴파일러가 원인을 파악하기 어려운 쓰기 오류를 내거나, 코드 서명 단계에서 불완전한 결과물만 남길 수 있습니다. 안정적인 대응 방법은 모든 디렉터리를 주기적으로 비우는 것이 아니라, 먼저 사용량을 측정하고 빌드 용량 기준을 설정한 다음 복구 가능성에 따라 단계적으로 정리하는 것입니다.
먼저 디스크 사용량 기준선 설정하기
먼저 시스템의 가용 공간을 기록한 후 개발 관련 디렉터리를 확인합니다. df는 파일 시스템에 얼마나 더 쓸 수 있는지 보여 주고, du는 어느 데이터가 공간을 차지하는지 찾는 데 사용합니다. 두 명령은 서로 대체할 수 없습니다.
df -Pk /
for path in \
"$HOME/Library/Developer/Xcode/DerivedData" \
"$HOME/Library/Developer/Xcode/Archives" \
"$HOME/Library/Developer/CoreSimulator" \
"$HOME/Library/Developer/Xcode/iOS DeviceSupport"
do
if [ -e "$path" ]; then
du -sk "$path"
fi
done
클린 빌드 전, 아카이브 완료 후, 테스트 종료 후에 각각 한 번씩 측정하는 것이 좋습니다. 이 세 수치를 비교하면 작업 한 번으로 늘어난 용량을 파악할 수 있으며, 정상적인 사용량 정점을 공간 누수로 잘못 판단하는 일도 방지할 수 있습니다. DerivedData에서 용량이 큰 디렉터리를 더 자세히 찾으려면 다음 명령을 실행합니다.
du -sk "$HOME/Library/Developer/Xcode/DerivedData"/* 2>/dev/null \
| sort -nr \
| head -20
APFS에 표시되는 가용 공간은 제거 가능한 데이터의 영향을 받을 수 있습니다. 빌드 용량 기준에서는
df의 가용 블록을 확인해야 하며, 디렉터리의 표시 크기만으로 작업이 반드시 완료될 것이라고 판단해서는 안 됩니다.
빌드에 명확한 용량 기준 적용하기
용량 임계값은 경험에 따라 임의로 고정하지 말고 실제 최대 사용량을 기준으로 정해야 합니다. 우선 30GB에서 시작해 전체 아카이브 과정에서 가용 공간이 가장 적었던 시점을 기록합니다. 여러 차례 안정적으로 실행한 뒤에는 임계값을 최대 증가량의 1.5배로 조정하고, 내보낼 결과물에 필요한 공간도 추가로 반영합니다.
다음 스크립트는 파이프라인 맨 앞에 배치할 수 있습니다. 공간이 부족하면 상태 코드 75로 종료하여, 실패할 가능성이 높은 빌드를 시작하는 대신 스케줄러가 해당 작업을 일시적으로 실행할 수 없는 상태로 처리하게 합니다.
#!/bin/zsh
set -euo pipefail
minimum_kb=$((30 * 1024 * 1024))
available_kb=$(df -Pk / | awk 'NR == 2 {print $4}')
if (( available_kb < minimum_kb )); then
printf 'Insufficient disk capacity: %s KB available
' "$available_kb"
exit 75
fi
printf 'Disk capacity check passed: %s KB available
' "$available_kb"
임계값은 노드별로 따로 저장해야 합니다. Xcode 버전, 시뮬레이터 조합, 프로젝트 규모에 따라 최대 사용량이 달라지므로, 소규모 프로젝트의 측정 결과를 대형 워크스페이스에 그대로 적용해서는 안 됩니다.
빌드마다 독립된 디렉터리 사용하기
기본 DerivedData를 공유할 때의 문제는 용량뿐만이 아닙니다. 각 디렉터리가 어느 작업에 속하는지 구분하기도 어렵습니다. 워크스페이스마다 독립된 경로를 지정하면 작업 종료 후 정확한 대상만 삭제할 수 있으며, 실행 중인 다른 빌드에도 영향을 주지 않습니다.
job_root="$HOME/build-jobs/$BUILD_ID"
derived_data="$job_root/DerivedData"
archive_path="$job_root/artifacts/App.xcarchive"
mkdir -p "$job_root/artifacts"
xcodebuild \
-workspace App.xcworkspace \
-scheme App \
-configuration Release \
-derivedDataPath "$derived_data" \
-archivePath "$archive_path" \
archive
BUILD_ID는 작업 시스템에서 제공해야 하며 문자, 숫자, 마침표, 밑줄 또는 하이픈만 포함하도록 제한해야 합니다. 정리하기 전에는 대상 경로가 build-jobs 아래에 있는지도 확인해야 합니다. 빈 변수로 인해 삭제 범위가 홈 디렉터리까지 확대되는 상황을 방지하기 위해서입니다.
복구 가능성에 따라 단계적으로 정리하기
정리는 다시 생성할 수 있는 데이터부터 시작하고, 사람의 확인이 필요한 아카이브는 가장 마지막에 처리해야 합니다.
| 단계 | 데이터 | 권장 작업 | 주요 주의 사항 |
|---|---|---|---|
| 1 | 완료된 작업의 DerivedData | 작업 디렉터리 단위로 삭제 | 빌드 프로세스가 사용 중이지 않은지 확인 |
| 2 | 사용할 수 없는 시뮬레이터 항목 | simctl로 정리 |
Devices 디렉터리를 직접 삭제하지 않음 |
| 3 | 오래된 기기 지원 파일 | 실제 테스트 버전을 기준으로 검토 | 디버깅이 필요한 시스템 버전은 유지 |
| 4 | xcarchive와 dSYM | 사람이 확인한 후 외부로 이전 | 출시된 버전은 반드시 추적 가능해야 함 |
더 이상 유효하지 않은 시뮬레이터는 시스템 도구로 삭제해야 합니다.
xcrun simctl delete unavailable
CoreSimulator/Devices를 직접 비우지 마십시오. 파일 디렉터리와 시뮬레이터 서비스 상태가 일치하지 않으면 이후 기기를 생성하거나 시작할 때 원인을 찾기 어려운 문제가 발생할 수 있습니다. 아카이브 디렉터리도 단순히 “며칠 이상 경과” 같은 조건으로 바로 삭제해서는 안 됩니다. xcarchive 안에는 출시 버전에 해당하는 dSYM이 남아 있을 수 있기 때문입니다. 올바른 방법은 버전, 빌드 번호, 이전 위치를 먼저 기록한 후 로컬 사본을 제거하는 것입니다.
자동 정리에서 피해야 할 세 가지 함정
첫째, 빌드가 진행 중일 때 공유 디렉터리를 정리하지 마십시오. 오래된 파일처럼 보여도 컴파일러가 인덱스나 중간 결과물을 통해 해당 파일을 참조하고 있을 수 있습니다. 정리 작업은 노드 단위 잠금을 확보하거나, 완료 상태로 표시된 독립 작업 디렉터리만 대상으로 해야 합니다.
둘째, “정리 성공”을 “공간 확보 완료”와 동일하게 판단하지 마십시오. 삭제 후 df -Pk /를 다시 실행해 가용 블록이 실제로 증가했는지 확인해야 합니다. 변화가 없다면 삭제 명령을 반복하는 대신 프로세스가 계속 열어 둔 파일이 있는지 확인해야 합니다.
셋째, 스크립트가 아카이브의 중요도를 자체적으로 판단하게 하지 마십시오. 무인 작업은 디렉터리 크기, 마지막 수정 시간, 연결된 빌드 번호 등의 삭제 후보 정보만 정리해야 합니다. 외부로 이전할지 삭제할지는 릴리스 기록에 따라 결정해야 합니다.
재현 가능한 빌드로 최종 검증하기
정리를 마친 후에는 운영 작업과 동일한 아카이브를 최소 한 번 실행해야 합니다. 검증할 때는 시작 시점의 용량, 최저 용량, 종료 시점의 용량, 아카이브 경로, 종료 상태를 기록하고 .xcarchive가 완전하게 생성되었는지 확인합니다. 해당 노드에서 시뮬레이터 테스트도 수행한다면 테스트 매트릭스에 유지된 각 버전을 한 번씩 실행하여 기기가 정상적으로 생성되고 시작되며 종료되는지 확인합니다.
최종 점검 항목은 간단하게 유지할 수 있습니다. 빌드 전 용량 기준을 통과했는지, 작업이 독립된 DerivedData를 사용하는지, 종료 후 남아 있는 컴파일 프로세스가 없는지, 아카이브와 dSYM이 기록되었는지, simctl list에 비정상 기기가 없는지, 남은 디스크 공간이 다음 작업의 임계값보다 큰지 확인합니다. 이 조건을 모두 충족해야 정리 절차가 완결된 것으로 볼 수 있습니다.
자주 묻는 질문
Xcode 빌드 노드에는 최소 얼마의 여유 공간이 필요합니까?
모든 프로젝트에 맞는 고정값은 없습니다. 우선 30GB를 빌드 전 하한으로 두고 전체 아카이브의 최대 사용량을 측정한 뒤, 대형 다중 모듈 프로젝트에는 그 값의 1.5배 이상을 확보합니다.
DerivedData 디렉터리 전체를 삭제해도 됩니까?
활성 빌드가 사용하지 않는다는 점을 확인했다면 가능합니다. 다만 작업 공간마다 별도 DerivedDataPath를 지정하고 완료된 작업의 디렉터리만 삭제하는 방식이 더 안전합니다.
자동 정리에서 제외해야 하는 Xcode 데이터는 무엇입니까?
진행 중인 아카이브, 백업하지 않은 xcarchive, 배포 버전에 대응하는 dSYM, 현재 테스트 매트릭스에서 사용하는 시뮬레이터 기기는 자동 삭제 대상에서 제외해야 합니다.
재현 가능한 환경을 같은 클라우드 Mac에 유지
고정된 기종, 리전 및 대여 기간을 선택하고 완전한 macOS 그래픽 인터페이스와 명령줄을 사용해 개발 또는 자동화 작업을 수행하세요.