Git에서 대용량 파일로 인한 성능 문제 해결
대용량 파일로 인해 느려진 Git 저장소를 진단하고, Git LFS를 신중하게 선택하며, 팀에 혼란을 주지 않고 기록을 정리하는 방법을 알아봅니다.
Git에서 대용량 파일로 인한 성능 문제 해결
대용량 파일은 저장소가 이미 사용하기 불편해질 때까지 눈에 띄지 않는 방식으로 Git에 해를 끼칩니다. 단일 비디오, 아카이브, 데이터베이스 덤프 또는 디자인 파일은 누군가 추가할 때 위험해 보이지 않을 수 있습니다. 문제는 해당 파일이 여러 번 변경될 때 시작됩니다. Git은 기록을 유지하며, 모든 클론은 그 기록을 함께 가져와야 합니다.
증상은 처음에는 대개 모호합니다. git clone이 예상보다 오래 걸립니다. git fetch는 호텔 Wi-Fi에서 느리게 느껴집니다. CI 작업은 빌드하기 전에 저장소를 체크아웃하는 데 너무 많은 시간을 소비합니다. 개발자들은 새 클론이 귀찮기 때문에 오래된 로컬 클론을 사용하기 시작합니다. 이때 모든 사람에게 인내심을 가지라고 말하는 대신 저장소를 검사해야 할 때입니다.
대용량 파일이 문제인지 확인
간단한 확인부터 시작하세요:
du -sh .git
git count-objects -vH
du -sh .git은 로컬 저장소 데이터베이스의 무게를 알려줍니다. git count-objects -vH는 느슨한 객체와 팩 크기를 보여줍니다. 팩 크기가 실제 소스 트리에 비해 크다면 기록이 오래된 페이로드를 운반하고 있을 가능성이 높습니다.
현재 체크아웃에서 대용량 파일을 찾으려면:
find . -path ./.git -prune -o -type f -size +10M -print
이것은 현재 존재하는 것만 보여줍니다. 저장소는 몇 달 전에 삭제된 파일 때문에 느려질 수 있습니다. 기록을 검사하려면 Git LFS가 마이그레이션 전에도 유용한 보고서를 제공합니다:
git lfs migrate info --everything --above=10MB
Git LFS가 설치되지 않은 경우에도 Git 플럼빙으로 조사할 수 있지만, 위 명령어는 이 특정 문제에 대해 가장 직접적인 보기인 경우가 많습니다.
Git에 무엇을 넣을지 결정
모든 대용량 파일이 실수인 것은 아닙니다. 소수의 안정적인 바이너리 자산은 괜찮을 수 있습니다. 인프라 코드용 저장소에는 VM 이미지, 데이터베이스 백업, 고객 내보내기 또는 빌드 아티팩트가 포함되어서는 안 됩니다. 게임 저장소에는 합법적으로 아트 및 오디오 자산이 포함될 수 있지만, 이러한 파일은 일반적으로 Git LFS 또는 별도의 자산 시스템이 필요합니다.
실용적인 규칙은 다음과 같습니다: Git은 소스 텍스트와 작은 지원 파일에 탁월합니다. Git은 자주 변경되는 바이너리 블롭에 적합하지 않습니다. 파일을 diff에서 의미 있게 검토할 수 없고 자주 변경된다면 일반 Git 객체로 존재해서는 안 됩니다.
Git LFS의 일반적인 후보는 다음과 같습니다:
*.psd
*.ai
*.mp4
*.mov
*.wav
*.zip
*.uasset
*.fbx
*.blend
광범위한 이미지 패턴에 주의하세요. 디자인 중심 저장소에서는 모든 *.png를 LFS로 추적하는 것이 도움이 될 수 있지만, 작은 아이콘이 많은 웹 앱에서는 번거로울 수 있습니다. 패턴은 실제로 문제를 일으키는 파일과 일치해야 합니다.
향후 대용량 파일에 Git LFS 사용
Git LFS는 Git에 작은 포인터 파일을 저장하고 대용량 콘텐츠를 LFS 저장소에 보관합니다. 일반 Git 기록은 가벼워지고, 사용자는 LFS가 다운로드할 때 작업 트리에서 실제 파일을 얻습니다.
설치 및 초기화:
git lfs install
실제로 필요한 파일 패턴을 추적하세요:
git lfs track "*.psd"
git lfs track "*.mp4"
git add .gitattributes
git commit -m "Track large design and video files with Git LFS"
.gitattributes 파일이 중요합니다. 모든 사람이 동일한 LFS 규칙을 사용하도록 커밋하세요.
그 후에는 파일을 정상적으로 추가하세요:
git add demo.mp4
git commit -m "Add product demo video"
git push origin main
협업자는 저장소 작업 전에 Git LFS를 설치해야 합니다. LFS 지원 없이 클론하면 실제 자산 대신 포인터 파일이 표시될 수 있으며, LFS를 설치하고 다음을 실행해야 합니다:
git lfs pull
또한 Git 호스트의 스토리지 및 대역폭 정책을 확인하세요. Git LFS는 Git 객체 비대화를 해결하지만 대용량 자산을 저장하거나 전송하는 데 비용이 들지 않게 하지는 않습니다.
기존 기록 마이그레이션
오늘 LFS를 활성화한다고 해서 어제의 커밋이 자동으로 수정되지는 않습니다. 700MB 아카이브가 커밋되었다가 나중에 삭제된 경우에도 기록에 남아 있을 수 있습니다. 이를 정리하려면 기록을 다시 작성해야 합니다.
기록 재작성은 커밋 ID를 변경합니다. 기존 클론이 있는 사람은 신중하게 다시 동기화해야 하며, 열린 풀 리퀘스트는 리베이스하거나 다시 생성해야 할 수 있습니다. 유지보수 기간에 이 작업을 수행하고 먼저 미러 백업을 만드세요:
git clone --mirror [email protected]:ORG/REPO.git repo-backup.git
그런 다음 새 클론에서 작업하세요. 작업 트리가 깨끗한지 확인하세요:
git status
마이그레이션될 항목을 검사하세요:
git lfs migrate info --everything --above=10MB
가능하면 패턴별로 마이그레이션하세요:
git lfs migrate import --everything --include="*.psd,*.mp4,*.zip"
또는 저장소에 알 수 없는 대용량 파일이 많으면 임계값 이상의 파일을 마이그레이션하세요:
git lfs migrate import --everything --above=10MB
푸시하기 전에 결과를 검토하세요:
git log --oneline --decorate -5
git lfs ls-files
git status
git lfs migrate info --everything --above=10MB
마이그레이션이 예상대로 작동했다면 다시 작성된 브랜치와 태그를 신중하게 푸시하세요:
git push --force-with-lease origin main
git push --force-with-lease origin --tags
활성 브랜치가 많은 저장소의 경우 중요한 브랜치를 결정하세요. 모든 폐기된 브랜치를 다시 작성할 필요는 없지만, 대용량 객체를 포함하는 브랜치는 원격 저장소를 무겁게 유지할 수 있습니다.
기록 재작성 후
팀원에게 정확히 무엇이 변경되었는지 알리세요. 가장 깔끔한 지침은 종종 다시 클론하는 것입니다. 사람들이 로컬 작업을 가지고 있다면 먼저 저장하세요:
git status
git branch my-work-before-lfs-migration
git fetch origin
git rebase origin/main
지저분한 로컬 클론의 경우, 오래된 기록을 외과적으로 복구하려고 시도하는 것보다 다시 클론하는 것이 덜 위험합니다.
원격 저장소는 즉시 축소되지 않을 수 있습니다. 호스팅 제공업체는 한동안 도달할 수 없는 객체를 유지하며, 일부는 스토리지 숫자가 업데이트되기 전에 지원이나 저장소 유지보수가 필요합니다. 로컬에서는 마이그레이션이 잘 되었다고 확신한 후에 오래된 객체를 정리할 수 있습니다:
git reflog expire --expire=now --all
git gc --prune=now --aggressive
정리 명령어를 검토 대신 사용하지 마세요. 오래된 로컬 객체를 복구하기 어렵게 만듭니다.
동일한 문제 재발 방지
대용량 실수 파일이 계속 나타나는 경우 사전 커밋 또는 사전 수신 확인을 추가하세요. 로컬 사전 커밋 훅은 개발자가 대용량 아티팩트를 커밋하기 전에 경고할 수 있습니다. 서버 측 규칙은 누군가 로컬 훅을 건너뛰더라도 공유 저장소를 보호하기 때문에 더 강력합니다.
간단한 로컬 확인은 선택한 크기 이상의 파일을 LFS로 추적되지 않는 한 거부할 수 있습니다. 정확한 임계값은 프로젝트에 따라 다릅니다. 문서 사이트와 게임 프로젝트는 동일한 제한을 사용해서는 안 됩니다.
또한 파일의 출처를 수정하세요. CI가 저장소 내에 dist/, target/, 커버리지 보고서, 아카이브 또는 스크린샷을 생성하는 경우 .gitignore에 올바른 항목을 추가하세요:
dist/
target/
coverage/
*.log
*.zip
무턱대고 파일을 무시하지 마세요. 무시된 경로가 생성된 출력물이고 소스 입력이 아닌지 확인하세요.
LFS가 답이 아닌 경우
Git LFS는 보편적인 아티팩트 저장소가 아닙니다. 빌드 출력물은 일반적으로 패키지 레지스트리, 객체 스토리지, 릴리스 자산 또는 CI 아티팩트 저장소에 속합니다. 데이터베이스 덤프는 백업 저장소에 속합니다. 대용량 데이터 세트는 데이터 버전 관리 도구나 별도의 스토리지 워크플로가 필요할 수 있습니다.
목표는 모든 큰 파일을 Git에서 숨기는 것이 아닙니다. 목표는 사람들이 도구와 싸우지 않고 클론, 브랜치, 페치 및 검토할 수 있을 만큼 저장소를 빠르게 유지하는 것입니다.
좋은 정리는 세 가지를 남깁니다: LFS에 속하는 파일에 대한 명확한 .gitattributes 규칙, 절대 커밋해서는 안 되는 파일에 대한 .gitignore 규칙, 그리고 기존 클론이 어떻게 다시 동기화해야 하는지 설명하는 짧은 팀 노트입니다. 이것이 수정 사항을 다음 분기에 반복하는 일회성 정리로 만들지 않습니다.