Git LFS 대용량 파일 공유하기
1) 파일 공유하기
여러 명이서 업무를 하며 혹은 과제를 하며 대용량 파일을 공유할 필요가 있습니다. 파일을 특정 경로에 올려두고, 누구나 사용할 수 있게 하는 것입니다. 특정 공유 폴더에 파일을 올려두거나 구글/MS 드라이브와 같이 클라우드형 파일 공유 시스템을 사용해서 공유할 수 있습니다.
하지만 이런 방식에는 큰 문제가 있습니다.
특정 공유 폴더에 파일을 올려두게 되면 접근 권한이 있는 사람들이 실수로 위치를 옮기거나 삭제할 수 도 있습니다. 그리고 버전을 관리하려면 폴더를 추가로 만들어서 관리할 수밖에 없습니다.
이론적으로는 이런 방식도 충분히 가능합니다. 하지만 현실 세계에서 업무나 과제를 하며 파일이 수백, 수천개로 늘어나면 엄격하게 관리를 하는 것은 불가능하고 최신 버전을 찾기가 어렵습니다. 그리고 파일 위치를 찾지 못해서 경로를 물어보다가 시간을 보내기 일쑤입니다.
그래서 이러한 일을 방지하기 위해서 Git을 이용해서 형상관리하고, 원격 저장소(Github)에서 데이터를 보관하면 훨씬 더 편리해집니다. 버전을 관리하고, 변경을 확인하고, 링크로 저장소를 공유할 수 있습니다. 하지만 Git 기반 원격 저장소의 가장 큰 문제는 파일별 용량 제한이 있습니다. 대표적으로 Github은 파일당 100MB 제한을 두고 있습니다.
이러한 이유는 각 저장소 사이즈를 작게는 1GB 크게는 5GB 정도로 유지하는것을 권장하고 있습니다. 작은 저장소가 더 빠르게 clone 받을 수 있고, 유지보수 하기에 용이하기 때문입니다.
We recommend repositories remain small, ideally less than 1 GB, and less than 5 GB is strongly recommended. Smaller repositories are faster to clone and easier to work with and maintain.
실제로 기업용 환경에서 큰 사이즈의 monolith 저장소를 clone 받으면 수십분이 소요되는 경우도 빈번합니다. 그리고 그렇게 큰 프로젝트는 로컬에서 빌드를 하더라도 굉장히 느리고 테스트하기 어렵습니다.
그리고 큰 사이즈의 파일이 지속적으로 쌓이기 때문에 용량이 중첩되어 증가한다는 문제가 있는데요. 1GB 파일의 A버전을 저장소 올리고, 다른 형상을 저장하기 위해서 B버전을 올립니다. 사용자 입장에서는 하나의 파일을 변경하는 것이지만 저장소에서는 형상 관리를 위해서 이전 버전들까지 모두 들고 있습니다. 즉 총 2GB가 쌓이고, 변경될수록 증가하는 문제가 있습니다.
그러면 이러한 문제를 어떻게 해결해야 할까요?
2) LFS(Large File Storage)
Github은 LFS를 통해서 큰 사이즈 파일 저장을 관리합니다. 그리고 LFS는 Git extension 입니다. Git LFS는 큰 사이즈 파일을 어떻게 관리하고 있을까요?
실제로 큰 사이즈의 파일을 저장소로 올리지 않고, 파일을 참조하는 pointer file만 저장소에 올립니다. 그리고 원본 파일은 별도의 LFS storage에 저장합니다. Github은 계정 종류에 따라서 LFS 저장소에 올릴 수 있는 파일별 사이즈를 2~5GB로 제한하고 있습니다.
Pointer file의 예시는 아래와 같습니다.
version https://git-lfs.github.com/spec/v1
oid sha256:4cac19622fc3ada9c0fdeadb33f88f367b541f38b89102a3f1261ac81fd5bcb5
size 84977953
각 명령어별로 어떻게 동작하는지 확인해봅니다.
먼저 Git lfs를 설치합니다.
# Window, Linux
git lfs install
# Mac OS
brew install git-lfs
테스트를 위해서 test.txt 파일을 생성합니다.
.txt 확장자 파일들을 LFS가 추적하여 관리하도록 합니다. Git add 명령어를 사용하면 staging area에 파일이 기록되는데요. 일반적으로는 원본 파일이 기록되지만 LFS 추적되고 있는 파일의 경우 pointer file이 staging area에 올라가게 됩니다. 그리고 원본 파일은 Git LFS cache 경로에 저장됩니다.
# *.txt 확장자 파일들을 lfs로 관리한다
$ git lfs track *.txt
$ git add test.txt
# LFS 추적 패턴이 정의된 gitattributes 파일도 추가한다
$ git add .gitattributes
지금까지 추가한 파일들이 잘 추적되고 있는지 확인해 봅니다.
# 현재 저장소에서 추적하고 있는 모든 패턴을 보여준다
$ git lfs track
# 추적하고 있는 pointer file 보여준다
git lfs pointer --file test.txt
이후에는 동일하게 git push 하면 됩니다. Pointer file은 main repository로 올라가고, 원본 파일은 LFS storage에 저장합니다.
3) 모든 경우에 LFS를 사용하면 될까요?
Pointer file만 저장소에 유지하고, 원본 파일은 별도의 저장소에 유지한다는 것을 들었을 때 매우 효율적으로 보입니다. 그렇다면 모든 파일을 LFS로 관리하면 괜찮을까요?
LFS를 사용하는 데에는 몇 가지 비용이 필요합니다.
- Pointer file 저장소 유지
- Origin file을 LFS 저장소에서 가져오기 위한 HTTP call
- LFS 저장소 관리
- .gitattributes 파일의 filter를 git 사용마다 확인
모든 기술의 선택은 비용을 지불하고서라도 얻는 효과가 가치 있는지 판단해야 합니다.
작은 파일을 관리하는 것은 이미 충분히 빠릅니다. 이미 충분히 빠른 것을 비용을 지불할 필요가 없습니다. 오히려 불필요한 동작으로 인해서 더 느려질 수 있기 때문에 사용할 필요가 없습니다.
즉 아래와 같은 상황에서 사용할 수 있습니다.
- 추가 operation 있더라도 LFS로 관리되어야 할 만큼 큰 파일인지
- 큰 파일은 아니지만 형상이 변경되면서 중첩되어 저장소의 용량을 차지할 수 있는 가능성이 있는지