TECH 으로 돌아가기
TECH HACKER NEWS 오늘 6분 읽기 21 READS

Git 커밋 하나는 실제로 몇 바이트를 차지할까

버전 관리를 매일 쓰면서도 "커밋 하나가 디스크에서 차지하는 용량은 얼마인가"라는 질문을 던져본 개발자는 많지 않다. ratfactor.com의 한 실험 기록은 이 단순해 보이는 질문의 답이 "상황에 따라 다르다"임을 보여주면서도, 구체적인 수치를 통해 Git의 저장 구조가 왜 그렇게 효율적인지를 드러낸다. 결론부터 말하면 Git은 생각보다 훨씬 경제적으로 데이터를 쌓지만, 아주 작은 변경에는 의외로 적지 않은 고정 비용이 붙는다.

왜 "상황에 따라 다르다"인가

Git은 내부적으로 모든 데이터를 '오브젝트'라는 단위로 저장하며, 이 오브젝트는 zlib으로 압축된다. 따라서 커밋이 차지하는 실제 크기는 파일이 얼마나 잘 압축되는지, 즉 파일 안에 반복되는 내용이 얼마나 많은지에 좌우된다. 반복이 많은 텍스트나 소스 코드는 극적으로 줄어들고, 이미 압축된 바이너리는 상대적으로 덜 줄어든다. 여기에 더해 Git은 시간이 지나면 흩어진 오브젝트 파일(loose object)을 더 효율적인 팩파일(packfile)로 묶어 오브젝트들 사이의 중복까지 제거한다. 아래 실험은 모두 팩파일이 만들어지기 전의 loose object 상태만을 측정한 값이므로, 실제 저장소는 시간이 지나며 이보다 더 작아질 여지가 있다는 점을 염두에 둘 필요가 있다.

작은 커밋의 숨은 고정 비용

실험 결과는 직관과 어긋나는 지점에서 흥미롭다. 디렉터리 5개에 "foo"라는 문자열만 담은 작은 파일 250개를 커밋하자 빈 저장소 대비 약 47,640바이트가 늘었다. 더 눈에 띄는 것은 변경량이 극히 작을 때다. 파일 50개가 든 디렉터리에서 한 파일에 3바이트만 고쳐 커밋했더니 17,145바이트가, 파일 하나뿐인 저장소에서 3바이트를 고쳤을 때도 8,709바이트가 소요됐다. 수 바이트짜리 변경에 수 킬로바이트가 붙는 셈인데, 그 크기는 변경과 관련된 파일·디렉터리 트리의 규모에 비례한다. 디렉터리가 클수록 바뀐 트리를 통째로 다시 기록해야 하기 때문이다.

이 오버헤드의 정체는 Git의 데이터 모델을 들여다보면 명확해진다. 단일 파일 저장소에서 파일 내용을 'baz'로 바꿔 커밋하자 새 오브젝트가 4개 생겼다. 커밋 하나, 바뀐 디렉터리를 나열한 트리 하나, 루트 디렉터리를 가리키는 또 다른 트리 하나, 그리고 'baz'라는 실제 파일 내용 하나다. 글쓴이는 Julia Evans(b0rk)의 새 Git 데이터 모델 문서를 참고해 이 구조를 확인했고, git show 명령이 커밋뿐 아니라 해시로 지정한 어떤 오브젝트의 내용이든 보여준다는 점을 활용했다. 즉 한 줄짜리 수정도 트리 구조 전체의 스냅숏을 새로 남기기 때문에 최소 비용이 발생하는 것이다.

커질수록 드러나는 효율

반대로 덩치가 큰 파일에서는 Git의 압축이 빛을 발한다. 약 583,840바이트짜리 바이너리 파일을 커밋하자 저장 용량은 297,873바이트로, 원본의 절반가량에 그쳤다. 더 극적인 것은 텍스트였다. 약 16,415,223바이트(16.2MB)의 거대한 소스 파일을 커밋했더니 저장에 쓰인 용량은 1,622,188바이트, 즉 원본의 10분의 1 수준이었다. 반복이 많은 텍스트가 압축에 유리하다는 점을 감안해도 인상적인 수치다. 정리하면 파일 수가 적고 파일 자체가 큰 커밋에서는 .git에 쌓이는 데이터가 압축 전 원본의 50%에서 10% 사이에 머문다.

실무자가 얻을 교훈

이 실험이 주는 메시지는 두 갈래다. 첫째, Git의 저장 효율을 걱정할 필요는 거의 없다. 특히 소스 코드처럼 압축이 잘 되는 텍스트 중심 저장소라면 변경 이력이 쌓여도 디스크 부담은 완만하게 증가한다. 둘째, 그럼에도 '작은 커밋일수록 가볍다'는 가정은 트리가 큰 저장소에서는 성립하지 않는다. 한 글자를 고쳐도 해당 디렉터리 트리 오브젝트가 통째로 새로 기록되므로, 수백 개 파일이 든 디렉터리에서 잦은 미세 수정을 반복하면 loose object가 빠르게 늘어난다.

다만 이 수치들은 어디까지나 팩파일 생성 이전의 중간 상태라는 한계를 분명히 해둘 만하다. git gc나 네트워크 전송 과정에서 오브젝트가 팩으로 묶이고 델타 압축이 적용되면, 반복적인 작은 커밋이 만들어낸 오버헤드 상당 부분이 사라진다. 결국 Git이 평소에 보이는 넉넉한 저장 방식은 성능을 위한 의도적 설계이고, 장기적인 공간 최적화는 팩파일이 책임지는 2단 구조인 셈이다. 저장 용량 자체보다는 커밋 단위를 의미 있게 나누는 데 집중하는 편이 실무적으로 더 합리적이라는 점을, 이 소박한 실험이 역설적으로 뒷받침한다.

SOURCE · HACKER NEWS
원문 전체 보기 → https://ratfactor.com/cards/git-commit-size
SHARE
NEXT · CHOOSE

변화를 읽었다면,
내가 만들 수익 구조를 고릅니다.

정보를 더 모으는 데서 멈추지 않고, 광고·외주·판매·중개·구독 중 내 상황에 맞는 출발점을 정해보세요.

21가지 수익 구조 살펴보기 →
처리 중...