Git packfile: 객체를 묶고 델타로 저장하는 원리
Git packfile은 여러 객체를 하나의 압축 파일로 묶고, 유사한 객체는 차이 정보로 저장해 공간을 줄일 수 있습니다. pack 인덱스와 델타 복원 과정, 네트워크 전송용 thin pack의 차이를 공식 형식 문서에 따라 설명합니다.
발행·오류 제보: infostoa · 편집 기준
이 글의 개별 작성자와 전문 검토자 정보는 제공되지 않습니다.
Git은 커밋, 트리, 블롭 같은 객체를 처음에는 개별 파일로 저장할 수 있지만, 저장소가 커지면 관련 객체를 packfile로 묶습니다. packfile 안의 객체는 압축되며, 비슷한 버전은 기준 객체와의 차이(delta)를 저장해 중복 데이터를 줄일 수 있습니다. 객체를 찾거나 읽을 때는 pack 인덱스와 델타 복원 경로가 사용되므로, packfile은 단순히 파일을 이어 붙인 아카이브가 아닙니다.
1. 객체를 pack으로 모으는 이유
Git의 객체 모델은 내용을 식별 가능한 객체 단위로 유지합니다. loose object는 보통 객체마다 별도의 파일로 저장되므로, 변경 이력이 길거나 작은 파일이 많은 프로젝트에서는 파일 수와 중복 내용이 커질 수 있습니다. packfile은 여러 객체를 한 묶음으로 압축해 저장 공간과 파일 관리 부담을 줄이는 데 쓰입니다. 저장소가 언제 pack되는지는 명령 실행과 유지보수 정책에 따라 달라질 수 있습니다.
packfile에는 헤더, 객체 개수, 각 객체의 유형과 크기, 압축된 데이터가 들어갑니다. 모든 객체가 다른 객체를 참조하는 것은 아닙니다. 독립적으로 복원 가능한 객체는 전체 내용을 저장하고, 적절한 경우에는 다른 객체를 바탕으로 한 델타 표현을 사용합니다. pack 형식의 구조를 알면 디스크 사용량과 객체 복원 비용을 함께 이해할 수 있습니다.
2. 델타가 줄이는 것과 복원에 필요한 것
두 버전의 파일이 대부분 같다면 매번 전체 내용을 반복 저장하는 대신 한 객체를 기준으로 다른 객체를 재구성하는 명령을 저장할 수 있습니다. Git pack 형식은 기준 객체의 바이트를 복사하거나 새 바이트를 삽입하는 델타 명령을 사용합니다. 같은 pack 안의 기준 객체는 오프셋으로 참조하는 OFS_DELTA가 될 수 있고, 객체 이름으로 참조하는 REF_DELTA도 있습니다.
델타는 중복 내용을 줄이는 데 도움이 되지만, 객체를 읽을 때 기준 객체를 찾고 델타를 적용하는 일이 추가됩니다. 델타가 연쇄되면 복원 과정은 기준 객체부터 여러 차례 적용될 수 있습니다. 실제 비용은 pack 구성과 접근 패턴, 캐시에 영향을 받으므로 델타 사용이 모든 읽기에서 더 빠르다고 볼 수 없습니다. Git은 저장 공간과 접근 효율을 함께 고려해 pack을 만들고 재구성합니다.
3. pack 인덱스와 thin pack의 구분
pack 인덱스는 pack 내부 객체에 빠르게 접근할 수 있도록 객체 식별자와 pack 오프셋의 대응을 저장합니다. pack 본문을 순서대로 처음부터 읽지 않고 필요한 객체 위치를 찾는 데 쓰이며, pack과 짝을 이루는 인덱스 파일 형식도 공식 문서에 정의되어 있습니다. 손상 여부나 객체 집합을 조사할 때는 pack과 인덱스를 함께 확인하는 이유가 여기에 있습니다.
thin pack은 전송 중 이미 수신 측에 있을 것으로 기대되는 기준 객체를 참조해 데이터량을 줄이는 용도입니다. 전송용 표현과 저장소에 보관되는 완결된 pack을 혼동하면 안 됩니다. thin pack은 외부 기준 객체를 포함하지 않는 형태일 수 있으므로, 수신 측에서 필요한 객체를 보완하는 과정이 필요합니다. 디스크에 기록되는 pack은 자체적으로 유효한 형태를 갖춰야 하며, 네트워크 전송 경로가 이를 보정할 수 있습니다.
4. 전문가 관점: 저장소 진단과 유지보수
Git의 packfiles 안내서는 비슷한 버전 간 차이를 델타로 저장해 공간을 절약하는 사례를 보여 줍니다. 그러나 큰 pack 하나가 모든 저장소에서 최선인 것은 아닙니다. 객체 접근 빈도, 저장소 크기, 전송 방식, 재압축의 CPU 비용을 고려해야 합니다. pack과 인덱스 파일을 직접 수정하기보다 Git의 검증 및 유지보수 명령을 사용하고, 실제 사용량과 명령의 성능을 관찰하는 것이 안전합니다.
저장소가 예상보다 커졌다면 먼저 어떤 객체가 공간을 차지하는지 조사하고, loose 객체와 기존 pack의 분포를 살펴봅니다. 재압축이나 정리는 협업자가 기대하는 객체와 참조를 고려해 수행해야 합니다. packfile을 이해하면 “Git이 모든 버전을 통째로 복사한다”는 오해를 피할 수 있지만, 델타 압축만으로 저장 공간이나 성능이 일정하게 개선된다고 보장할 수는 없습니다.