콘텐츠
깃(Git)으로 형상관리
요즘 계속 깃(Git) 관련 포스팅을 작성하고 있습니다.
Git 은 개발 한 프로젝트 소스 코드, 문서등 관련 된 파일을 버전 관리, 공유, 백업 등의 역할을 수행해 주는 형상 관리 도구 입니다.
그 중 오늘은 Git 의 장점이자 가장 큰 특징인 브랜치(branch)를 다른 대표적인 형상관리 도구 SVN 과 비교하며 정리하는 시간을 가지려 합니다.
브랜치(branch) 란?
브랜치(branch)는 Git 에만 존재하는 개념은 아닙니다. 동작과 사용 방법엔 차이가 있을 수 있지만 SVN 과 같은 다른 형상 관리 도구에도 사용되는 기능 입니다.
브랜치는 단어의 뜻과 같이 나무에 가지가 뻗어 나가듯 메인 소스 코드를 여러 공간에서 독립적으로 개발을 한 후 통합하는 방식으로 동시에 개발을 진행할 수 있게 해주는 개념 입니다.
쉽게 말하자면 여러 소스 코드를 다른 공간에서 개발하고 최종적으로 통합하는 기능 입니다.
깃(Git)은 다른 도구들 보다 브랜치 기능이 효율적이다 평가 받고 있습니다.
깃(Git)의 가장 큰 특징 브랜치(branch)
깃(Git)의 가장 큰 특징으로 브랜치(branch)가 소개되는 이유는 다른 형상 관리 도구 보다 효율적이기 때문입니다.
다른 형상 관리 도구들의 경우 메인 소스 코드를 건드리지 않고 개발할 수 있도록 생성 된 새로운 브랜치 공간에 파일을 그대로 복사하거나 파일의 변경 점을 기록하였습니다.
Git 의 경우는 브랜치가 생성되면 포인터가 생성되고 기존의 ‘스냅샷(Snapshot)’에 연결 됩니다.
시작점이 되는 스냅샷을 기반으로 하여 새로운 커밋을 추가하면 이어 새로운 스냅샷을 만들게 되어 브랜치 마다 독립적인 개발 히스토리를 가지게 됩니다.
그리고 최종적으로 중심이 되는 메인 브랜치에 합칠 때 중요한 정보가 됩니다.
스냅샷(Snapshot)
스냅샷은 파일 시스템의 상태를 저장하는 개념을 의미 합니다.
다른 대표적인 형상관리 도구 SVN은 변경 사항을 저장소에 반영하는 커밋(Commit) 이 이루어 질 때 파일의 ‘변경 된 부분만’ 차이점(델타, delta) 혹은 패치(patch)로 저장 합니다.
Git 에서 변경 이루어지면 ‘변경된 파일의 상태(내용과 여러 메타 데이터)’를 캡처 한 후 스냅샷으로 저장하게 됩니다.
그리고 변경되지 않은 파일은 새로운 데이터를 저장하지 않고 그 파일의 마지막 변경 시점의 스냅샷을 재사용 합니다.
그래서 최초 시점의 커밋이 이루어 지면 프로젝트의 모든 내용이 스냅샷에 기록되어 있고 이후엔 변경이 이루어진 파일들의 내용으로만 스냅샷이 생성 됩니다.
이로 인해 커밋마다 그 시점의 파일 전체를 기록하지 않아도 됩니다.
예시
이를 예로 들어 설명해 보겠습니다. 만약 A, B, C 의 파일이 있는 상태로 최초의 커밋이 이루어 집니다. 그럼 스냅샷은 이 세 내용을 전부 포함하고 이를 스냅샷1로 표현하겠습니다.
그 후 A만 변경하고 커밋이 이루어 지면 생성 된 스냅샷2는 변경된 파일의 내용을 포함하고 B, C는 스냅샷 1를 참조하는 정보만 지니고 있습니다.
파일 복사(Copy)와 의 차이
그러면 변경 된 파일 정보로 스냅샷을 만들면 파일을 복사하는 거랑 뭐가 다르지? 할 수 있지만 파일 관리를 효율적으로 수행하기 위해 다음과 같은 최적화가 수행 됩니다.
- 스냅샷은 파일의 내용 + 형상 관리를 위한 정보를 함께 저장합니다.
- 파일의 해시를 계산하여 파일을 고유하게 식별, 중복 저장을 하지 않습니다.
- 파일, 객체를 팩 파일로 묶고 델타 압축하여 전체적인 파일 크기를 줄입니다.
스냅샷(Snapshot) vs 델타(Delta)
둘 다 변경 사항을 저장하지만 스냅샷은 변경이 이루어진 파일의 상태를 형상 관리를 위한 정보로 그대로 가지고 있는 것이고 델타는 변경된 내역만 저장합니다.
A 란 파일이 12345 에서 1234567 로 변경되면 스냅샷은 1234567 전부를, 델타는 변경된 부분인 67만이 저장됩니다.
그리고 스냅샷은 어느 시점이든 그 파일의 상태가 저장 되어 있어 언제든지 원하는 시점의 파일을 사용할 수 있습니다.
하지만 델타 경우는 변경 된 내용이 최초부터 누적되어 기록되고 있으므로 변경 사항이 많아 지면 때때로 문제를 일으키거나 성능을 저하 시킵니다.
새로운 브랜치(branch) 생성
SVN의 경우
위에 내용에 이어 SVN 는 새로운 브랜치가 생성될 때 새로운 디렉터리를 만들고 복사(Copy) 가 이루어 집니다. 즉, 특정 시점의 소스 코드를 새로운 디렉터리에 복사하여 개발 한다는 의미죠.
하지만 이는 실제로 파일이 복사 되는 것은 아닙니다. 처음에는 참조만 생성(cheap copy 혹은 lazy copying)하고 이후 변경 사항이 발생하면 변경된 파일을 새로 기록하게 됩니다.
그래서 SVN도 실제 파일을 복사해 개발을 수행 하는 것에 비해 저장 공간을 효율적으로 사용하고 성능을 최적화, 작업의 빠른 처리 속도를 제공 할 수 있게 됩니다.
깃(Git)의 경우
그런데 Git 은 브랜치를 새로 생성하게 되면 실제로 공간(디렉터리)가 생성되는 것이 아니라 포인터를 생성 합니다.
그리고 이 포인터는 원하는 커밋을 가리키게 됩니다. 마치 이름표를 붙이는 것처럼요.
보통 이 경우 가장 최신 커밋인 즉 HEAD가 가리키는 커밋이 됩니다.
그 후 새로 만들어진 브랜치에서 개발을 진행 후 커밋 하면 변경 사항을 캡쳐해 새로운 스냅샷을 기록합니다.
그 후 개발이 끝나면 이 스냅샷 들은 이후 메인 브랜치에 병합(merge)됩니다.
분산형 버전 관리 시스템
여기서 추가적으로 깃(Git)은 분산형 버전 관리 시스템 입니다. 먼저 개발자가 자신의 PC 에 깃을 설치하여 로컬 저장소(local repository) 를 생성, 프로그램을 개발, 반영(Commit) 하며 형상 관리를 합니다.
그 후 회사가 소유한 Git 서버 혹은 웹 호스팅 서비스인 GitHub 등의 원격 저장소(remote repository)에 파일 반영(push)하는 과정으로 개발 됩니다.
중앙 관리 시스템인 SVN은 Git 과 달리 처음부터 서버에 연결하여 여러 클라이언트가 서버에 파일을 커밋(Commit) 합니다.
깃(Git)의 방식이 뛰어나다 평가 받는 이유
위에 SVN 과 비교하며 깃(Git)의 브랜치(branch) 방식에 대해 정리해 보았습니다. 그런데 왜 Git 의 브랜치가 뛰어나다는 평가를 받는 것일까요?
효율적이고 빠르다.
여러 이유가 있겠지만 그 중에서도 한 가지를 꼽자면 Git 은 브랜치(branch)를 생성하는 과정은 포인터의 이동일 뿐이고 형상관리 하는 과정이 모두 스냅샷(Snapshot)으로 이루어진다는 점 입니다.
SVN 시스템의 경우 초기엔 변경 사항만 기록 되므로 같은 변경 사항이라면 델타(Delta)의 용량이 스냅샷에 비해 적고 공간도 덜 차지해 보일 것 입니다.
하지만 시간이 지날수록 서로 크게 차이 나는 버전의 파일 내용 비교 시 이를 추적하는 과정이 더욱 복잡해질 우려가 있습니다.이에 여러 브랜치가 병합될 때도 서로 다른 변경 사항들만 기록 되어 있어 연산이 매우 복잡하게 돌아가게 됩니다.
그런데 깃은 그렇지 않습니다. 깃은 특정 시점의 파일을 확인하고 이를 사용하려 해도 그 당시의 파일 전체의 상태를 기록한 스냅샷을 사용합니다.
그래서 브랜치 간의 전환도 간단히 HEAD 포인터의 이동만 이루어지는 것이며 특정 시점의 파일 복구와 같은 형상 관리 작업이 다른 도구에 비해 매우 빠르고 효율적 입니다.
저장소 방식의 차이
또한, 기본 저장소 방식에 의한 차이도 있습니다. SVN 은 모든 작업을 중앙 서버와 연결 되어 사용하므로 서버의 성능, 네트워크 등에 부하가 생길 수 있죠. 서버에 문제가 생기면 형상 관리에 문제가 생길 수 있다는 점도 단점 입니다.
깃의 경우는 그렇지 않죠. 깃은 서버에 필요할 때만 접근하면 되고 로컬 저장소의 파일을 이용해서 개발이 이루어 지기 때문입니다.
오늘은 개발 도구 초보가 깃(Git)의 브랜치(branch)에 대해 정리해 보았습니다. 열심히 해본다고 정리해 보았는데 왜 좋은 건지를 다른 도구와 비교해 보니 알겠는 점도 있고 알쏭달쏭한 부분도 있는 것 같습니다. 😯