Git에서 대용량 파일의 미래는 Git임
(tylercipriani.com)- Git 프로젝트가 최근 공식적으로 대용량 파일 관리 문제를 직접 해결하기 시작함
- Git LFS는 사용자에게 여러 가지 비용, 벤더 종속성 등을 유발하는 임시방편임
- 최근 partial clone 기능으로 Git 자체만으로 대부분의 LFS 역할을 대체할 수 있게 됨
- 앞으로는 large object promisor라는 새로운 솔루션도 공식 Git에 통합 준비 중임
- 이러한 변화로 대용량 파일 관리의 궁극적인 해법이 외부 확장이 아닌 Git 자체로 귀결될 전망임
Git의 대용량 파일 문제와 변화
만약 Git에 대적할 존재가 있다면, 그건 바로 대용량 파일 문제임
대용량 파일은 Git 저장소를 비대화시키고, git clone
속도를 저하시키며, 대다수 호스팅 환경에도 악영향을 줌
Git LFS의 등장과 한계
2015년 GitHub는 Git LFS를 출시해 대용량 파일 문제를 우회했음
하지만 Git LFS 자체가 새로운 복잡성과 저장 비용을 추가함
Git 커뮤니티는 조용히 대용량 파일 근본 문제를 고민해 왔고, 최근 Git의 공식 릴리즈에서 LFS 없이 대용량 파일을 관리할 새로운 방향성이 제시됨
오늘 당장 가능한 방법: Git LFS를 partial clone으로 대체
partial clone의 원리
- Git LFS: 대용량 파일은 저장소 밖에 두고, 필요한 파일만 다운로드해 작업하는 구조임
-
Git partial clone(2017년 도입):
-
--filter
옵션으로 원하는 크기 이상의 blob을 제외하고 복제 - 필요할 때만 해당 대용량 파일만 서버에서 내려받음
-
Partial clone을 통해 미리 대용량 바이너리 파일을 모두 다운로드하지 않아도 됨
- Partial Clone Design Notes, git-scm.com
partial clone과 LFS의 공통점
- 체크아웃 용량 최소화: 최신 버전만 받고 전체 파일 히스토리는 생략함
- 빠른 복제: 대용량 파일 전송이 없으니 clone 속도가 빠름
- 빠른 세팅: shallow clone과 달리 프로젝트 전체 히스토리 접근 가능함
partial clone 활용 예시
대용량 PNG 파일의 히스토리가 많은 repo 복제 속도 및 디스크 차지 실례:
- 일반 clone시 거의 4분, 1.3GB 공간 차지
- partial clone 및 100KB blob 제한 적용시 6초 만에 복제, 49MB 차지
- 원본 대비 복제 속도 97% 개선, 체크아웃 크기 96% 축소
partial clone 한계
- 필터링한 데이터가 필요할 경우(예:
git diff
,git blame
,git checkout
), Git이 서버에 파일 요청함 - 이는 Git LFS와 동일한 특징임
- 실무에서는 바이너리 파일에 blame 할 일은 드묾
Git LFS의 문제점
- 높은 벤더 종속성: GitHub 구현체는 자체 서버만 지원, 요금 부과 및 종속성 초래
- 비용 문제: 50GB 저장시 GitHub LFS는 연 $40, Amazon S3는 $13
- 되돌리기 힘듦: 한번 LFS로 전환시, 히스토리 재작성 없이 원상복구 불가
- 지속적 세팅 비용: 모든 협업자가 LFS 설치 필수, 설치 안 하면 파일 대신 메타데이터 파일(혼란 유발)
앞으로의 전망: Large Object Promisor
대용량 파일은 호스팅 플랫폼(GitHub, GitLab)에서도 비용적 문제를 일으킴
Git LFS는 대용량 파일을 CDN으로 오프로딩하면서 서버 비용을 줄임
Large Object Promisor란?
올해 초, Git은 large object promisor라는 기능을 공식적으로 머지함
이 기능은 LFS와 유사하게 서버 쪽의 저장소 부하를 줄이지만, 사용자 복잡성은 크게 줄임
서버에서 바이너리로 압축된 대용량 blob 관리를 개선하는 기능임
Git LFS의 대안이 되는 솔루션임
– Large Object Promisors, git-scm.com
동작 원리
- 사용자가 대용량 파일을 Git 호스트에 push
- 호스트가 백엔드 promisor에 대용량 파일 오프로딩 처리
- clone시 Git 호스트가 클라이언트에 promisor 정보 제공
- 클라이언트는 필요시 해당 promisor에서 자동으로 대용량 파일 받음
현재 도입 현황과 과제
- 대용량 promisor는 아직 개발 중이며, 2025년 3월 일부 코드가 Git에 머지됨
- GitLab 등에서 추가 구현 및 미해결 이슈 논의 진행 중
- 대중적 도입까지는 아직 시간이 필요함
- 당분간은 대용량 파일 저장에 Git LFS 의존 불가피
- promisor가 보급되면 GitHub에도 100MB 넘는 파일 업로드가 가능해질 전망
결론: Git의 대용량 파일 미래는 Git
Git 프로젝트는 여러분을 대신해 대용량 파일 문제를 끊임없이 고민 중임
오늘은 여전히 LFS 의존이 남아있지만, 머지않아 대용량 파일을 Git만으로 손쉽게 관리할 수 있는 시대가 도래할 것임
미래에는 Git에 MP3 라이브러리를 넣겠다는 생각만이 대용량 활용을 가로막는 마지막 장애가 될 전망임
Hacker News 의견
-
예전의 svn만 해도, 대용량 바이너리 파일이 많은 150GB 작업 디렉토리에서도 별문제 없이 잘 작동했음, 반면에 git은 그렇지 않음. 왜 svn이 대용량 바이너리 파일에서 git과 다른 접근을 하는지, git이 똑같이 할 수는 없는 건지 궁금함. 게다가 바이너리 데이터를 다룰 때 꼭 필요한 기능이 파일 잠금인데, 특정 파일을 한 명만 작업하고 나머지는 읽기 전용이어야 혼란스러운 머지 문제를 피할 수 있음. 대용량 파일을 외부로 오프로드한다고 해서 실제 성능이나 안정성 문제가 개선되는 건지 잘 이해가 안 됨. 결국 저장소가 다를 뿐이지, 저장소는 저장소임. 오프로드는 사실상 퍼블릭 git 포지가 대용량 파일 저장비용을 회피하려는 방법 같음
- git과 svn은 완전히 다른 설계임. git은 완전히 분산형이기에 모든 저장소가 모든 파일의 전체 히스토리를 가져야 하고, 잠금 개념은 무의미함. 프로젝트에 맞는 버전관리시스템을 선택하면 됨, git이 만능이어야 한다는 건 아님
-
Large object promisors 개념이 마음에 듦. S3 같은 곳을 쉽게 연결해서 쓸 수 있다면 기존 LFS에서 바로 넘어갈 것 같음. S3는 대용량 바이너리 파일을 버전관리할 때 시너지가 큼. 인텔리전트 티어링으로 데이터가 오래될수록 자동으로 저렴한 스토리지 티어로 옮겨가는 장점도 있음. 10년된 데이터를 복원하느라 반나절 걸려도 상관없음
-
나도 같은 생각임. 왜 처음부터 기본으로 이 방식이 안 됐는지 이해가 안 됨. 작은 git LFS 서버를 직접 돌리고 있는데, git이 S3를 네이티브로 지원만 해주면 바로 바꿀 준비가 되어 있음
-
지금 직장에서 LFS 오브젝트를 비용절감을 위해 버킷에 캐싱하고 있음. PR 실행 때마다
git lfs ls-files
로 파일 목록 받고, gcp에서 가져오고, git lfs checkout으로 로컬에 오브젝트 저장 후, pull로 빠뜨린 것만 추가로 받음. 캐싱 안 된 파일은 gcloud storage rsync로 다시 버킷에 올림. 개발자 입장에서 추가 설정 필요 없이 새 객체만 pull하면 되고, Github UI도 저장소 상태에 혼동이 없음. 예전엔 LFS 백엔드 직접 올릴까 했는데, 이 방법이 당장의 가장 큰 문제를 해결해줌. Github이 LFS 파일 CI에서 받을 때마다 트래픽 요금이 과다했고, 캐시 10GB 제한과 브랜치 간 공유 불가 탓에 매번 다시 받아야 했음. 캐시 용량을 돈 주고라도 늘리고 싶었지만 그 방법도 없었음. 이걸 개발자에게 적용하려면 git hook만 추가해주면 될 정도로 간단함 -
S3가 Amazon 관련 서비스인지 궁금함
-
-
Git LFS가 좋지 않은 점을 여러 가지 언급하면서, 벤더 락인이 있다는 건 동의하지 않음. GitHub가 오픈 클라이언트와 서버를 제공하므로 해당 주장은 부당함. 다만, LFS는 오프라인/스니커넷 작업에서는 작동하지 않고, 이는 흔한 경우는 아니지만 언급할 가치가 있음. large object promisor가 LFS의 클라이언트 측 복잡성을 서버로 옮긴 듯보이는데, 결국 복잡도만 변하는 것 같음. git 서버가 LFS 서버와 오브젝트 저장소로 파일을 업로드하는 구조라면, 다른 트레이드오프가 따름. 퍼블릭 git 서버에서 promisor 리모트를 숨겨두고 업로드할 때 어떤 일이 생길지 궁금함
-
LFS가 진짜로 별로라고 생각함. 서버 구현도 엉망이고, 객체 내용과 저장 방법이 혼재됨. opt-in 방법도 형편없어서 아무 생각 없이 쓰면 실제로 원하는 파일 대신 작은 텍스트 파일만 생김. 새로운 솔루션이 더 나은지는 모르겠지만 LFS가 좋지 않다는 점은 분명함
-
최근 알게 된 또 다른 Git LFS의 문제는, 마이그레이션이 상위 커밋들의
.gitattributes
까지 오염시킨다는 것임. 즉, 커밋 A→B→C 순서에서 C에서만 대용량 파일을 LFS로 추가했다면 A, B도 존재하지 않는 LFS 파일을 가리키는.gitattributes
가 생김. 마이그레이션 과정에서.gitattributes
가 히스토리를 따라 거꾸로 전파되는데, 현재 커밋의 실체 존재 여부는 참조하지 않기 때문임 -
예전에는 Git LFS가 SSH를 지원하지 않아, SSL 인증서를 반드시 받아야 했고, 이 때문에 집에서 셀프호스팅하는 사용자에겐 진입 장벽이었음. Gitlab은 최근에 SSH 지원 패치를 한 듯함
-
-
소프트웨어 공학 수업에서 대용량 파일(미디어 등)을 Git에 넣지 않고 아티팩트 저장소(Artifactory 등)에 넣으라고 권장했었음. 그러면 스냅샷 의존성 형태로 배포할 수 있고, 빌드 시스템이 알아서 최신 버전만 가져오게 제어할 수 있음. 동료들이 로컬에 쌓인 오래된 파일도 빌드 시스템 캐시만 비우면 바로 정리됨
-
이 방식은 일종의 git 서브모듈 같은 느낌이긴 함. 만약 서브모듈로 문제가 해결됐으면 사람들이 이미 썼을 것. git 서브모듈도 얕은 클론을 지원함(관련 링크: https://stackoverflow.com/questions/2144406/…). 나는 대용량 파일 이슈는 겪어본 적 없어서, 만약 이 방법이 안 되는 이유가 무엇인지 궁금함. SO에서 나온 단점들이 그리 커 보이진 않음
-
수업에서 CI/CD 시스템 아키텍처도 가르치는지 궁금함. 요즘 신입 엔지니어들이 GitLab, Artifactory, CodeSonar, Anchore 등과 연동하는 전체 구조에 익숙하지 않음
-
이 방법도 단점이 있음. CI/CD 시스템이나 개발자에게 추가 인증 정보가 필요함. 커밋도 여러 단계로 늘어나며, 아티팩트 아이디를 먼저 알아야 하고, 이를 자동화하려고 git hook을 쓰다 보면 결국 git-lfs처럼 복잡해짐
-
-
이 글이 LFS를 부당하게 평가하고 있음. LFS는 GitHub에 종속적이지 않고 프로토콜도 오픈임. LFS의 단점은 git 확장으로서 어쩔 수 없는 부분이고, promisors도 사실상 LFS와 같은 개념임. 단, git 내부에 내장하면서 UX가 좀 더 좋아진 것임
- 한 번이라도 LFS를 쓴 저장소는 영구적으로 락인됨. 사용한 공간을 줄이려면 저장소 자체를 삭제해야 하고, 이는 공식적으로 명확히 알려주지도 않음. 우리 회사 Github 통계를 연구할 때 대용량 압축 DB 파일을 LFS에 넣었다가 이 문제를 직접 경험함
-
이게 진짜 솔루션은 아님. git LFS도 임시방편일 뿐이고, 클론할 때 필터 인자를 넣는다고 해도 근본 해결이 아님. git clone은 모든 사용자가 가장 먼저 배우는 명령어인데, 이때마다 필터를 기억해야 하고, 실수하면 시간만 오래 걸리고, 성공해도 클론한 저장소가 제대로 동작하지 않을 수도 있음. 결국 rsync처럼 최신 파일부터 효율적으로 가져오는 구조로 전환해야 근본적으로 해결됨. git은 이런 근본적 변경을 잘 하지 않음
-
크게 공감함. git은 늘 플래그 하나 추가하는 방식으로 문제를 "해결"하는데 대부분의 사용자는 이 기능을 잘 모름. 기본값 자체를 개선하면 호환성 깨지지 않고도 문제를 풀 수 있음
-
클론한 저장소가 제대로 동작하지 않을 수도 있음
실은 블롭의 히스토리만 빠지는 거임 -
rsync가 해결한 문제라는데, 구체적으로 어떤 모습이냐고 물음. 알고리즘 말고 실제 사용자가 "git clone" 할 때 로컬 파일시스템에 무엇이 생기는 건지 궁금함
-
저장소 부피의 대부분이 과거 리비전에 있다면, rsync처럼 최신 버전만 우선 받아오는 방식이 대부분의 사용자에게 가장 적합한 해결책임
-
-
Git 코어에 대용량 파일 지원이 추가되는 것이 매우 기쁨. 외부 솔루션이어도 결국 opt-in 구조는 비슷함. 최대한 명령어를 줄이고 seamless하게 만들고 싶었기에 '.gitattributes' 파일의 smudge/clean 필터에만 한정해서 API를 설계했음. 또, Atlassian과 Microsoft와 직접 협업해 벤더 락인을 없애려고 했고, 파일락킹 API도 Atlassian에서 많은 도움을 받음. LFS는 세 가지 호스트에서 호환 지원된 오픈소스로 제공됨
-
우리는 git이나 git-lfs에서 겪은 문제를 해결하려고
oxen
을 개발하고 있음. git 인터페이스를 그대로 따라가면서 대용량 파일과 수백만 개 파일이 있는 모노레포 환경에서 훨씬 더 빠르게 동작함. 오픈소스 CLI와 서버를 제공하니, 관심 있으면 피드백 부탁함
https://github.com/Oxen-AI/Oxen -
git의 저장 방식 자체도 restic이나 borg 등 최신 백업 툴처럼 파일과 디렉토리의 콘텐츠 기반 청킹(content-defined chunking)으로 오버홀할 필요가 있음
-
GitLFS의 단점 중에 인증 이슈가 빠졌는데, SSH-agent를 쓰지 않으면 한 번 push할 때도 인증을 여러 번 거쳐야 함. 직접 경험에 따르면 두세 번 이상 해야 했던 적도 있음