
Git LFS와 GitHub로 10GB가 넘는 게임 프로젝트 관리하기
대용량 에셋을 Git 저장소와 분리해 관리하는 Git LFS의 원리부터 Unity·Unreal 프로젝트 설정, 기존 이력 마이그레이션, 비용과 협업 규칙까지 정리합니다.
10GB 게임 프로젝트에서 먼저 나눠야 할 것
게임 프로젝트가 10GB를 넘는다고 해서 모든 파일을 Git LFS에 넣어야 하는 것은 아니다. 핵심은 소스와 설정은 일반 Git, 병합하기 어려운 대용량 바이너리 원본은 Git LFS, 언제든 다시 만들 수 있는 생성물은 저장소 밖으로 나누는 것이다.
GitHub는 일반 Git 저장소의 단일 파일을 100MiB보다 크게 푸시할 수 없게 막는다. 또한 일반 저장소는 1GB 미만을 이상적으로 보고 5GB 미만을 강하게 권장한다. .git 폴더 기준 권장 상한도 10GB다. 따라서 수십 GB 규모의 프로젝트를 일반 Git 객체로만 쌓는 방식은 처음에는 동작하더라도 클론, fetch, CI 시간이 빠르게 나빠진다. GitHub의 대용량 파일 안내, 저장소 제한 문서를 기준으로 설계를 잡는 편이 안전하다.

다음 기준은 실무에서 무난한 출발점이다.
| 분류 | 예시 | 권장 위치 |
|---|---|---|
| 텍스트이며 병합 가능한 파일 | C++, C#, 셰이더 소스, .meta, .ini, .uproject, YAML 설정 | 일반 Git |
| 큰 바이너리 원본 | .psd, .blend, .fbx, 텍스처 원본, 오디오 원본 | Git LFS |
| 엔진이 재생성하는 파일 | Unity Library, Unreal DerivedDataCache, 빌드 결과물 | .gitignore 또는 아티팩트 저장소 |
| 배포용 결과물 | 설치 파일, 패치 파일, 플레이 가능한 빌드 | GitHub Releases, CI 아티팩트, 오브젝트 스토리지 |
Git LFS는 Git 저장소에 큰 파일의 실제 내용을 넣는 대신 작은 포인터 파일을 커밋한다. 실제 바이너리는 LFS 저장소에 올라가며 LFS가 설치된 클라이언트가 체크아웃할 때 내려받는다. 포인터 파일은 대략 다음처럼 파일의 해시와 크기만 가진다.
version https://git-lfs.github.com/spec/v1
oid sha256:...
size 84977953
시작 전 확인할 GitHub 한도와 비용
10GB가 넘는 프로젝트에서는 LFS 사용량을 프로젝트 용량이 아니라 이력 전체와 다운로드량으로 계산해야 한다. 예를 들어 2GB 텍스처 팩을 수정해 다시 푸시하면 GitHub LFS에는 새 버전 전체가 저장된다. 1바이트만 바꿔도 2GB를 더 사용한다고 생각하는 편이 맞다.
현재 GitHub의 파일별 LFS 한도는 Free·Pro 2GB, Team 4GB, Enterprise Cloud 5GB다. 계정 플랜별 스토리지와 월간 다운로드 대역폭도 다르다. Free와 Pro는 각각 10GiB이며 Team과 Enterprise Cloud는 각각 250GiB가 포함된다. 배포 대상이 많은 게임이라면 LFS 파일을 포함한 ZIP 다운로드와 CI의 LFS 다운로드도 대역폭을 사용한다는 점을 꼭 확인해야 한다. GitHub LFS 개요, Git LFS 과금 문서를 참고하자.
특히 LFS는 10GB 이상의 프로젝트를 올릴 수 있게 해 주는 도구이지 무제한 저장소가 아니다. 대용량 에셋을 자주 다시 내보내는 팀은 다음을 분리하는 편이 낫다.
- 작업 중인 원본과 현재 게임에 필요한 런타임 에셋은 LFS로 관리한다.
- 일별 백업, 폐기 예정 원본, 대규모 캡처 파일은 별도 오브젝트 스토리지나 자산 관리 시스템에 둔다.
- 플레이어 배포용 빌드는 LFS가 아니라 Release나 배포 저장소에 올린다.
새 프로젝트에 Git LFS 적용하기
팀원 모두 Git LFS를 설치한 뒤 저장소마다 한 번 초기화한다.
git lfs install
git lfs track "*.psd"
git lfs track "*.blend"
git lfs track "*.fbx"
git lfs track "*.png"
git lfs track "*.tga"
git lfs track "*.wav"
git lfs track "*.mp4"
git add .gitattributes
git commit -m "Configure Git LFS tracking"
git lfs track은 .gitattributes를 수정한다. 이 파일은 팀원이 같은 추적 규칙을 받도록 반드시 커밋해야 한다.
*.psd filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text
*.fbx filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text
여기서 확장자를 넓게 잡는다고 항상 좋은 것은 아니다. 예를 들어 Unity의 .meta 파일은 텍스트 파일이므로 일반 Git에 두어야 한다. C# 코드와 셰이더 소스도 마찬가지다. Unreal의 .uasset, .umap은 일반적으로 병합이 어려운 바이너리이므로 LFS 대상 후보지만 팀의 엔진 버전과 워크플로에 맞게 실제 생성량을 살핀 뒤 적용하는 것이 좋다.
# Unreal Engine에서 자주 LFS로 관리하는 바이너리
*.uasset filter=lfs diff=lfs merge=lfs -text
*.umap filter=lfs diff=lfs merge=lfs -text
추적 규칙을 추가한 뒤에는 새로 추가하는 파일부터 LFS에 들어간다. 이미 일반 Git으로 커밋한 대용량 파일은 자동으로 옮겨지지 않는다.
Unity와 Unreal에서 제외할 파일
저장소를 가볍게 유지하는 가장 큰 효과는 LFS 규칙보다 .gitignore에서 나온다. 엔진이 다시 만들 수 있는 캐시와 중간 산출물을 버전 관리하지 않는 것이 원칙이다.
Unity는 보통 Assets, Packages, ProjectSettings를 관리하고 Library, Temp, Logs, obj, 빌드 폴더는 제외한다. Unity 에셋의 GUID를 담은 .meta 파일은 반드시 함께 관리해야 참조가 안정적이다.
# Unity
[Ll]ibrary/
[Tt]emp/
[Ll]ogs/
[Oo]bj/
[Bb]uild/
[Bb]uilds/
UserSettings/
Unreal은 Binaries, Intermediate, Saved, DerivedDataCache를 기본적으로 제외하는 경우가 많다. 다만 플러그인이나 외부 SDK가 포함된 프로젝트는 필요한 바이너리가 있을 수 있으므로 무작정 광범위한 규칙을 복사하기보다 새 PC에서 클론 후 프로젝트가 재생성 가능한지 검증해야 한다.
# Unreal Engine
Binaries/
Intermediate/
Saved/
DerivedDataCache/
.vs/
기존 저장소의 큰 파일을 LFS로 옮기기
이미 큰 파일이 일반 Git 이력에 들어갔다면 .gitattributes만 추가해도 과거 커밋은 작아지지 않는다. 이때는 이력을 다시 작성해야 한다. 작업 전에는 미러 백업을 만들고 모든 팀원에게 푸시 중단 시간을 공지해야 한다.
# 별도 작업 디렉터리에서 수행
git clone --mirror [email protected]:ORG/GAME.git GAME.git
cd GAME.git
git lfs install
git lfs migrate import --everything --include="*.psd,*.blend,*.fbx,*.tga,*.wav,*.uasset,*.umap"
git push --force --all
git push --force --tags
git lfs migrate import는 대상 파일이 들어 있는 커밋의 해시를 바꾼다. 이미 복제한 팀원은 기존 브랜치를 계속 사용하지 말고 새로 클론하는 것이 가장 단순하고 안전하다. 보호 브랜치의 강제 푸시 정책과 오픈된 PR도 사전에 처리해야 한다.
마이그레이션 뒤에는 다음 명령으로 LFS 추적 상태와 객체 무결성을 확인한다.
git lfs ls-files
git lfs fsck
git count-objects -vH
대용량 프로젝트의 클론과 CI 최적화
모든 개발자가 모든 고해상도 에셋을 즉시 받을 필요는 없다. 예를 들어 툴 프로그래머나 서버 개발자는 필요한 에셋만 내려받도록 설정할 수 있다.
$env:GIT_LFS_SKIP_SMUDGE = "1"
git clone [email protected]:ORG/GAME.git
Set-Location GAME
git lfs pull --include="Assets/Characters/**,Assets/UI/**"
이 방식은 처음 클론할 때 LFS 자동 다운로드를 건너뛴 뒤 필요한 경로만 가져온다. 다만 에디터가 참조하는 파일이 빠진 상태로 열리면 오류가 날 수 있으므로 역할별로 필요한 경로를 문서화해야 한다.
CI에서도 같은 원칙이 적용된다. 코드 검사나 문서 빌드처럼 에셋이 필요 없는 작업은 LFS 다운로드를 생략한다. 실제 게임 빌드 작업만 전체 에셋을 받도록 분리하면 시간과 대역폭을 줄일 수 있다.
충돌보다 먼저 막아야 할 바이너리 동시 수정
Git LFS는 큰 파일을 저장해 주지만 Photoshop, Blender, Unreal 바이너리 에셋의 의미 있는 병합을 만들어 주지는 않는다. 두 사람이 같은 바이너리를 수정하면 보통 한쪽 변경을 선택해야 한다.
공유가 어려운 파일에는 LFS 잠금을 사용한다.
git lfs lock Assets/Characters/Hero/Hero.fbx
# 파일 수정과 커밋, 푸시 후
git lfs unlock Assets/Characters/Hero/Hero.fbx
잠금은 기술적 장치일 뿐이다. 에셋을 캐릭터, 레벨, 머티리얼 단위로 나누고 담당 범위를 정하는 규칙이 함께 있어야 충돌이 줄어든다. 특히 하나의 거대한 레벨 파일을 여러 사람이 동시에 편집하는 구조는 LFS를 써도 해결되지 않는다.
운영 체크리스트
.gitattributes와.gitignore는 코드 리뷰 대상으로 관리한다.- 100MiB 이상 파일이 일반 Git에 들어가지 않도록 사전 훅이나 CI 검사를 둔다.
- 월간 LFS 스토리지와 대역폭, 특히 CI와 외부 다운로드량을 확인한다.
- LFS 파일을 바꿀 때는 전체 새 버전이 저장된다는 점을 고려해 불필요한 재내보내기를 줄인다.
- 이력 마이그레이션은 백업, 푸시 중단, 강제 푸시, 팀원 재클론을 하나의 작업으로 계획한다.
- 배포용 빌드와 재생성 가능한 캐시는 Git과 LFS에서 분리한다.
10GB 이상의 게임 프로젝트를 안정적으로 운영하는 기준은 저장 공간의 크기보다 파일의 성격을 구분하는 데 있다. 소스와 설정은 Git의 장점을 그대로 활용하고 큰 바이너리는 LFS로 옮기며 생성물과 배포물은 별도 경로로 분리하자. 이 원칙을 초기에 정해 두면 프로젝트 규모가 커져도 저장소와 협업 흐름을 훨씬 예측 가능하게 유지할 수 있다.


