수년간의 커밋 기록과 디자인 원본 파일, 화면 녹화, 테스트 픽스처가 포함된 iOS 저장소를 클라우드 Mac에 처음 준비할 때는 “머신 준비가 느리다”는 현상을 CPU나 디스크 문제로 오인하기 쉽습니다. 하지만 실제 병목은 빌드 전에 발생하는 경우가 많습니다. 일반 Git 객체를 전부 다운로드하고, 체크아웃 단계에서 Git LFS가 모든 대용량 파일을 자동으로 가져오지만, 정작 CI에서는 그중 하나의 App만 빌드하기 때문입니다. 해결책은 디렉터리 전체를 무작정 캐시하는 것이 아니라 입력을 먼저 고정한 다음, 커밋 객체와 작업 트리 경로, LFS 콘텐츠를 계층별로 제어하는 것입니다.
체크아웃 비용부터 측정하기
git clone에 걸린 시간만 기록해서는 안 됩니다. 최소한 네트워크 전송, 작업 트리 구성, LFS 다운로드의 세 단계로 나누고 다음 결과를 저장해야 합니다.
git --version
git lfs version
du -sh .git
du -sh .git/lfs 2>/dev/null || true
du -sh .
git count-objects -vH
git lfs ls-files | wc -l
최초 실행과 기존 작업 트리를 재사용하는 실행은 별도로 측정해야 합니다. 최초 실행에서는 원격 전송 비용을 확인할 수 있고, 재사용 실행에서는 불완전한 정리, 기록 객체의 증가, LFS 캐시 팽창이 드러납니다. 브랜치 이름만 기록하지 말고 최종 커밋 값도 남겨야 합니다.
git rev-parse HEAD
git status --short
최적화의 목표는 디렉터리를 겉보기보다 작게 만드는 것이 아니라, 동일한 커밋과 동일한 디렉터리 집합, 동일한 LFS 객체 집합을 안정적으로 재현하는 것입니다.
부분 클론과 희소 체크아웃 조합하기
부분 클론의 blob:none은 일반 파일 콘텐츠의 다운로드를 뒤로 미루고, 희소 체크아웃은 작업 트리에 실제로 펼칠 디렉터리를 제한합니다. 두 기능은 함께 사용할 수 있지만 Git LFS까지 자동으로 제한하지는 않으므로, 최초 smudge를 명시적으로 건너뛰어야 합니다.
export GIT_LFS_SKIP_SMUDGE=1
git clone --filter=blob:none --no-checkout "$REPO_URL" app
cd app
git lfs install --local
git sparse-checkout init --cone
git sparse-checkout set App Packages Shared
git fetch --depth=1 origin "$BUILD_REF"
git checkout --detach FETCH_HEAD
git rev-parse HEAD
--cone 모드는 디렉터리 단위로 구성된 프로젝트에 적합합니다. 규칙이 단순하고 상위 디렉터리의 파일이 예기치 않게 누락되는 문제도 비교적 적습니다. App, Packages, Shared는 실제 빌드 의존 경로로 바꿔야 합니다. 워크스페이스, 스크립트 또는 설정 파일이 저장소 루트에 있다면 해당 파일이 여전히 포함되는지도 확인해야 합니다.
부분 클론을 사용하려면 원격 서버가 객체 필터링을 지원해야 합니다. 명령 실행 중 필터링 기능에 관한 경고가 표시되면 일반 클론으로 폴백한 것으로 간주하고 .git 크기를 다시 기록해야 합니다. 최적화가 적용되었다고 가정해서는 안 됩니다.
현재 작업에 필요한 LFS 객체만 가져오기
체크아웃을 마친 뒤에도 LFS 파일이 포인터 상태로 남아 있을 수 있습니다. 먼저 현재 커밋이 참조하는 객체를 나열한 다음, 작업에 필요한 경로만 가져옵니다.
git lfs ls-files
git lfs pull --include="App/Assets/**,Shared/Fixtures/**"
git lfs fsck
경로 필터는 파일 확장자를 추측해서 정하는 것이 아니라 빌드 입력을 기준으로 구성해야 합니다. UI 테스트는 이미지, 동영상, 현지화 픽스처에 의존할 수 있습니다. 소스 코드 디렉터리만 가져오면 컴파일은 성공하더라도 테스트가 실행 단계에서 실패할 수 있습니다.
| 검사 항목 | 정상 결과 | 일반적인 문제 |
|---|---|---|
git lfs ls-files |
현재 커밋에서 LFS로 추적하는 항목이 표시됨 | 대상 커밋의 .gitattributes가 체크아웃되지 않음 |
| 파일 헤더 검사 | 파일에 실제 바이너리 콘텐츠가 있음 | 여전히 oid sha256이 포함된 포인터임 |
git lfs fsck |
로컬 객체 검증을 통과함 | 다운로드가 중단되었거나 객체 디렉터리가 손상됨 |
git status --short |
작업 트리에 의도하지 않은 변경이 없음 | 도구가 체크아웃 후 리소스 파일을 다시 씀 |
경로 제한이 없는 공용 초기화 스크립트에 git lfs pull을 넣지 마십시오. 그렇게 하면 모든 작업이 자신과 무관한 리소스까지 다운로드하게 됩니다. 각 파이프라인이 자체 LFS 입력 집합을 선언하도록 하는 편이 더 안정적입니다.
CI의 동시 실행과 자격 증명 처리하기
각 CI 작업은 독립된 작업 트리를 사용해야 합니다. 여러 작업이 쓰기 가능한 저장소 하나를 공유하면 희소 체크아웃 규칙, 인덱스 잠금, LFS 임시 파일이 서로 영향을 줄 수 있습니다. 읽는 코드가 같더라도 두 작업이 .git/info/sparse-checkout을 동시에 수정하게 해서는 안 됩니다.
자격 증명은 가져오기 단계에서만 주입하고 대상 저장소에 필요한 권한으로 제한해야 합니다. git fetch와 git lfs pull이 끝나면 임시 환경 변수와 자격 증명 도우미 설정을 정리해야 합니다. 로그에는 토큰이 포함된 원격 주소를 출력하지 마십시오. 다음 명령으로 표시되는 값이 안전한지 확인할 수 있습니다.
git remote -v
git config --local --get-regexp 'credential|lfs' || true
서브모듈은 별도로 처리해야 합니다. 메인 저장소의 부분 클론 및 희소 체크아웃 규칙은 서브모듈에 자동으로 전달되지 않습니다. 서브모듈에서도 LFS를 사용한다면 해당 디렉터리에서 로컬 LFS 설정을 설치하고 필요한 가져오기 작업을 실행해야 합니다.
안전하지 않은 정리 피하기
git lfs prune은 단독으로 사용하는 저장소에는 적합하지만 여러 작업이 LFS 객체 디렉터리를 공유하는 환경에는 적합하지 않습니다. 공유 환경에서는 작업마다 독립된 디렉터리를 만들고 작업 종료 후 디렉터리 전체를 삭제하는 방식이 더 안전합니다. 작업 트리를 반드시 재사용해야 한다면 동시 실행 중인 작업이 없는지 먼저 확인한 뒤 정리와 무결성 검사를 수행해야 합니다.
빌드 후 추측 대신 빌드 전 검증 사용하기
실제로 xcodebuild를 실행하기 전에 가벼운 검증 단계를 추가합니다. 이 단계에서는 최소한 커밋 값이 올바른지, 작업 트리가 깨끗한지, 핵심 프로젝트 파일이 존재하는지, LFS 포인터가 실제 파일로 교체되었는지 확인하고 디스크 사용량을 출력해야 합니다. 예를 들어 다음과 같이 검사할 수 있습니다.
test -f App/App.xcodeproj/project.pbxproj
test -s App/Assets/LaunchVideo.mov
if grep -q "oid sha256:" App/Assets/LaunchVideo.mov; then
exit 1
fi
git diff --exit-code
git lfs fsck
du -sh . .git .git/lfs
마지막으로 커밋 해시, 희소 체크아웃 디렉터리 목록, LFS include 규칙, 검증 결과의 네 가지 데이터를 보관합니다. 이렇게 하면 클라우드 Mac의 작업이 실패했을 때 먼저 입력이 완전한지 판단한 후 컴파일러, 서명 또는 테스트 로그를 조사할 수 있습니다. 저장소 준비 오류가 무작위 빌드 장애처럼 보이는 상황도 피할 수 있습니다.
자주 묻는 질문
부분 클론과 희소 체크아웃이 Git LFS를 대체할 수 있나요?
대체할 수 없습니다. 부분 클론은 일반 Git 객체 전송을 줄이고, 희소 체크아웃은 작업 트리 경로를 제한하며, Git LFS는 포인터가 가리키는 대용량 파일을 가져옵니다.
체크아웃 후에도 Git LFS 포인터만 남는 이유는 무엇인가요?
smudge를 건너뛴 뒤 git lfs pull을 실행하지 않았을 가능성이 큽니다. 현재 커밋, 포함 경로, 인증 정보와 LFS 설정을 확인한 뒤 필요한 객체를 가져오세요.
모든 CI 작업이 종료 단계에서 git lfs prune을 실행해도 되나요?
저장소와 LFS 객체 디렉터리를 해당 작업만 사용할 때에만 안전합니다. 공유 저장소라면 작업별 독립 공간을 만들고 종료 시 공간 전체를 회수하는 편이 낫습니다.
전용 클라우드 Mac
전용 물리 노드에서 빌드 작업 실행
일·주·월·분기 단위로 MiniRents M4 및 MiniRents M4 Pro를 선택하고, 팀과 코드 저장소 위치에 맞는 노드를 선택하세요. 장비는 전용 물리 머신이며 가상 머신이 아닙니다.