검수요청.png검수요청.png

분산버전관리

위키원
이동: 둘러보기, 검색

분산버전관리(Distributed revision control 또는 Decentralized Version Control, DVCS)는 소프트웨어 버전 관리를 위한 시스템이다. 이 시스템은 각 개발자가 중앙 서버에 접속하지 않은 상태에서도 코드 작업을 할 수 있는 것이 특징이다.

개요[편집]

중앙 집중형 버전 관리 시스템의 저장소(repository)가 서버에만 있는 것과 달리 분산버전관리 시스템에서 저장소는 모든 클라이언트가 저장소가 될 수 있다. 예를 들어 TFS에서 get latest version을 통해 저장소에서 프로젝트를 가져오면, 저장소에서 사용자의 컴퓨터에 최신의 코드를 받아오게 된다. 이 말은 소스 코드는 물론 그동안의 변경 이력까지 모든 정보를 가져와 로컬 컴퓨터 또한 완전한 저장소가 된다는 뜻이다. 이렇게 됨으로써 한번 저장소를 받아온 이후에 개발 작업에서는 서버와는 별개로 자신의 로컬에서 진행하게 되고, 로컬이니 당연히 빠른 속도로 변경할 수 있는 것이다. 만약 main.cs 파일의 지난 히스토리와 diff 하고 싶을 경우 TFS는 서버와의 통신을 통해 diff 하지만 분산버전관리 시스템은 로컬에 있는 저장소에서 변경 이력을 찾아 정의해 준다.[1]

특징[편집]

구성도
분산버전관리구성도(Distributed revision control, 또는 Distributed Version Control (Systems) (DVCS)
장점

중앙 서버의 문제가 있어도 클라이언트 PC의 소스를 통한 원상 복구가 가능하다. 여러 명이 동시에 작업하는 병렬 개발이 가능하며, 프로젝트를 모두 복사해와 로컬 환경에서 마음껏 테스트할 수 있다.[2]

단점

SVN과 깃을 써오던 입장에서는 이 분산형 시스템에서 단점을 찾아보기 어렵다. 따라서 프로젝트를 항상 통으로 가져오기 때문에 용량에 압박이 있다.[2]

작업 모델[편집]

분산 모델은 일반적으로 부분적으로는 독립 개발자들과 더불어 리눅스 커널 프로젝트 같은 대형 프로젝트에 더 적합한 편인데, 그 이유는 개발자들이 독립적으로 작업한 다음에 변경사항을 병합(또는 거절) 할 수 있기 때문이다. 이 분산 모델은 사용자 지정 소스 코드 기여 워크플로우의 유연한 채택을 가능케 한다.[3]

브랜치 저장소[편집]

모든 프로젝트는 공식 저장소로 간주되는 중앙 저장소가 있으며 이는 프로젝트 유지보수자들에 의해 관리된다. 개발자들은 이 저장소를 복제하여 동일한 로컬 코드베이스 사본을 만들 수 있다. 중앙 저장소의 소스 코드 변경사항은 주기적으로 로컬 저장소와 동기화된다.[3]

풀 리퀘스트[편집]

분산버전관리 시스템을 사용하는 소스 코드 저장소의 기여는 풀 리퀘스트(pull request), 즉 머지 리퀘스트라는 방식을 통해 이루어지는 것이 보통이다. 프로젝트 관리자가 소스 코드 변경사항을 풀하는 기여자 요청이므로 "풀 리퀘스트"라는 이름이 붙게 되었다. 유지보수 자는 기여가 소스 베이스의 일부가 되게 하기 위해 풀 리퀘스트를 병합해야 한다. 개발자는 새 변경사항을 유지 보수장에게 알리기 위해 풀 리퀘스트를 생성한다. 댓글 스레드가 개별 풀 리퀘스트에 연결된다. 이를 통해 코드 변경에 대한 집중화된 토론이 가능해진다. 제출된 풀 리퀘스트들은 저장소 접근이 가능한 누구나 볼 수 있다. 풀 리퀘스트는 유지보수 자들에 의해 수락되거나 거절될 수 있다. 풀 리퀘스트가 검토되고 승인되면 저장소에 병합된다. 확립된 워크플로우에 따라 코드는 공식 릴리스에 포함되기 전에 테스트할 필요가 있을 수 있다. 그러므로 일부 프로젝트들은 테스트 되지 않은 풀 리퀘스트를 병합하기 위한 특수한 브랜치가 포함되어 있다. 그 밖의 프로젝트들은 모든 풀 리퀘스트에 대한 자동화된 테스트 스위트를 수행하며 이는 Travis CI 등의 CI 도구를 사용함으로써 이루어지며, 새로운 코드에 적절한 테스트 커버리지가 있는지를 리뷰어가 검사한다.[3]

비교[편집]

사람들은 하나의 프로젝트에 대해 여러 개의 스냅샷을 만들고 저장한다. 저장한 장소는 해당 프로젝트를 수정한 사람의 컴퓨터, 로컬이다. 만약에 이 컴퓨터가 침수되어서 저장한 내용을 되찾을 수 없다면 해당 프로젝트는 그냥 날라가게 된다. 그래서 사람들은 서버를 사용한다. 개인 컴퓨터가 고장나서 사용하지 못하게 되면 서버에서 다시 다운받을 수 있기 때문이다. 게다가 여러 사람들이 서버에 각자의 프로젝트를 올리고 다른 사람들이 다운받아 볼 수 있게 할 수도 있다. 그런데 이 방식은 서버에서 문제가 생기면 모든 사용자가 프로젝트를 날리게 된다. 로컬에 다운받아 놓은 정보는 살아남겠지만 프로젝트 전체를 되돌릴 방식은 없다. 이를 해결하기 위해서 분산이라는 방식을 사용하기 시작했다. 중앙집중식과 달리 분산방식에서는 서버가 아닌 저장소라는 단어를 사용한다. 중요한 서버가 아니라 여러 사람들이 진행한 내용을 그저 저장해놓은 장소라는 의미만 가지는 것이다. 개인들은 자신이 작업한 내용을 저장소에 저장한다. 이가 가능한 이유는 프로젝트가 아무리 커도 각각의 스냅샷은 몇 기가바이트가 되지 않기 때문이다. 그리고 다른 사용자가 저장소에서 프로젝트를 다운받을 때는 모든 스냅샷에 대한 정보를 한 번에 다운받는다. 만약 저장소가 공격을 받아도 거의 대부분의 프로젝트를 되찾을 수 있다는 장점이 있다. 당연히 모든 스냅샷을 다운받은 모든 사람이 체크아웃을 할 수 있다는 것도 큰 장점이다. 또한 모든 정보를 로컬에서 다 가지고 있어 cmd에서 명령어를 입력할 때 서버가 필요하지 않다. 네트워크에 연결되어 있지 않아도 원하는 스냅샷으로 체크아웃 할 수 있다는 것은 큰 장점이다. 분산버전관리시스템 이전에는 로컬버전관리 시스템과 중앙집중식 버전관리 시스템으로 버전을 관리했다.[4]

로컬버전관리[편집]

많은 사람들은 버전을 관리하기 위해 디렉토리로 파일을 복사하는 방법을 쓴다. 이 방법은 간단하여 자주 사용되지만 작업하던 디렉토리를 지워버리거나 실수로 파일을 잘못 고칠 수도 있고, 잘못 복사할 수도 있어 문제가 생기기 쉽다. 이런 이유로 프로그래머들은 로컬버전관리를 만들었다. 로컬버전관리는 아주 간단한 데이터베이스를 사용하여 파일의 변경 정보를 관리한다. 많이 쓰는 로컬버전관리 도구 중에 RCS(revision control system)라고 불리는 것이 있는데, 오늘날까지도 아직 많은 회사가 사용하고 있다. RCS는 기본적으로 파일에서 변경하는 부분, 패치셋(patch set)을 관리한다. 이 패치셋은 특별한 형식의 파일로 저장한다. 그리고 일련의 패치셋을 적용해서 모든 파일을 특정 시점으로 되돌릴 수 있다.[5]

중앙집중식 버전관리[편집]

프로젝트를 진행하다보면 다른 개발자와 함께 작업해야 하는 경우가 많다. 이럴 때 생기는 문제를 해결하기 위해 중앙집중식 버전관리가 개발됐다. CVS, 서브버전, 퍼포스 같은 시스템은 파일을 관리하는 서버가 별도로 있고 클라이언트가 중앙 서버에서 파일을 받아 사용한다. 수년 동안 이러한 시스템들이 많은 사랑을 받았다. 중앙집중식 버전관리 환경은 로컬 버전관리에 비해 장점이 많다. 모두 누가 무엇을 하고 있는지 알 수 있기 때문이다. 따라서 관리자는 누가 무엇을 할지 꼼꼼하게 관리할 수 있다. 모든 클라이언트의 로컬 데이터베이스를 관리하는 것보다 버전관리 하나를 관리하기가 훨씬 쉽다. 그러나 중앙집중식 버전관리 환경은 몇 가지 치명적인 결점이 있다. 가장 대표적인 것이 중앙 서버에 발생한 문제이다. 만약 서버가 한 시간 동안 다운되면 그동안 아무도 다른 사람과 협업할 수 없고 사람들이 하는 일을 백업할 방법도 없다. 그리고 중앙 데이터베이스가 있는 하드디스크에 문제가 생기면 프로젝트의 모든 히스토리를 잃는다. 물론 사람마다 하나씩 가진 스냅샷은 괜찮ㄴ다. 로컬 버전관리 시스템에도 이와 비슷한 결점이 있고 이런 문제가 발생하면 모든 것을 잃는다.

주요 제품 및 비교[편집]

버전관리시스템은 통합개발환경(IDE)과 개발자가 가장 자주 접하는 도구이다. 버전관리 시스템의 경우에는 통합개발환경과는 달리 개발자에게 주어진 선택의 자유가 그렇게 많지 않다. 그 이유는 조직 내의 모든 구성원이 동일한 버전관리 시스템을 사용해야 하기 때문이다. 하지만 아이러니하게도 개발자가 열심히 일할수록 종래의 버전관리 시스템은 많은 문제를 일으킨다. 애자일(Agile) 개발 방법론을 적용하여 기능 단위의 변경이 동시에 병렬적으로 일어나는 환경에서는 자주 충돌이 발생한다. 브랜치를 병합하는 과정에서 역시 많은 충돌이 발생하고 병합에 들어가는 비용이 높아 종래의 의도대로 브랜치와 병합 기능을 사용하는 경우는 드물다. 이런 환경에서 분산 버전관리 시스템이 점점 부각되기 시작했다. 특히 비트키퍼(Bitkeeper)나 플라스틱 SCM(Plastic SCM) 등과 같은 상용 분산버전관리 시스템을 대체할 수 있는 깃(Git)나 머큐리얼(Mercurial) 등의 공개 도구가 등장하고, 리눅스 커널 등과 같은 대규모의 프로젝트에서도 사용되기 시작하면서 빠른 속도로 확산되기 시작했다. 특히 분산버전관리은 이력(History)에 대한 개념을 달리하면서 강력한 브랜치, 병합 등이 대표적인 장점이 되었다. 무엇보다 가장 큰 장점은 분산 환경에 기반하고 있으므로, 로컬 저장소(Repository)만으로 잘 동작하고, 짧은 역사를 만회하기 위해 기존 버전관리 시스템과의 협업을 다양하게 지원한다는 점이다. 이러한 점은 개발자가 개발 환경에서 많은 비용을 들이지 않고 가벼운 마음으로 시도해 볼 수 있도록 한다. 분산버전관리 시스템에는 공개 도구와 상용 도구가 있는데, 이 중에서 가장 많이 쓰이는 시스템은 공개 도구인 깃(Git)과 상용 도구인 머큐리얼(Mercurial)이다.[6]

깃과 머큐리얼은 거의 비슷한 철학을 가지고 있다. 이는 아마도 분산버전관리 시스템이 가지는 특성 때문일 것이라고 생각할 수 있다. 가볍고, 규모 확장이 쉬운 버전관리 시스템에 비해 이 특성은 분산버전관리 시스템에서 분산이라는 특징을 그대로 나타낸다. 특히 변경에 대한 이력을 시간에 의존적인 선형 구조로 나타내는 것이 아니라, 복수의 부모 변경과 복수의 자식 변경을 표시하는 그래프로 나타낸다. 두 제품에서 차이가 있다면, 깃은 태생부터 수많은 병렬 브랜치를 전제로 하여 설계되었다는 점이다. 머큐리얼은 그런 장점이 없는 대신에 배우고 사용하기 쉽도록 많은 노력을 들였다. 이는 깃과 머큐리얼 사이의 선택에서 가장 중요한 차이점이다.

실행 환경[편집]

깃은 C 언어와 bsh(Bourne Shell), 을 이용하여 전체가 작성되어 있으며, 머큐리얼은 거의 전체가 파이썬으로 작성되었다. 바꿔 말하자면 깃은 머큐리얼에 비해 상당히 리눅스 친화적인 성격을 가진다. 그렇기 때문에 윈도우 환경에서 은 에뮬레이션 환경이 필요하며, 상대적으로 머큐리얼이 깃에 비해서 윈도우 환경에서 더 나은 성능을 보여 준다. 하지만 동시에 깃은 셸 스크립트(shell script)를 사용할 수 있다면, C 언어를 사용하지 않아도 명령을 확장할 수 있다는 장점이 있다. 그에 반해서 머큐리얼은 파이썬으로 된 코드(Core Code)나 명령어(Command) 구성을 이해하지 못하면 확장 명령을 만들기가 깃에 비해서는 어렵다는 특징이 있다.[6]

사용성[편집]

사용성 측면에서 머큐리얼은 이미 패키지 안에 모든 도구가 각각 고도로 완성된 상태로 들어 있다. 물론 확장을 할 수는 있지만, 확장 명령을 만들기가 쉽지 않다. 대신 필요하다 싶은 기능은 대부분 이미 번들 확장(Extension)에 포함되어 있다. 반면에 깃은 필수적인 기능 세트를 콤팩트하고 세련된 형태로 갖췄다. 그래서 핵심적인 부분만을 봤을 때, 기능의 종류도 적고 기본적인 기능만 제공된다고 생각할 수 있다. 하지만 셸 스크립트를 사용해 기본적인 명령을 확장하거나 연결해서 새로운 명령을 만들어 자신의 손에 딱 맞는 형태의 도구를 생성할 수 있다. 그래서 때로는 머큐리얼과 동등하거나 더 나은 사용성을 얻을 수 있다. 머큐리얼은 또한 잘 정리된 별칭이 미리 만들어져 있으며, 대부분의 경우에 설정 없이 혹은 사용자 이름을 설정하는 정도만으로 바로 시작할 수 있는 환경을 제공한다. 그에 반해 깃은 일반적인 설정을 전혀 제공하지 않으므로, 머큐리얼에 비해 조금 더 많은 설정이 필요할 수 있다.[6]

구성[편집]

깃과 머큐리얼의 차이는 구현 언어 외에도 구현 방식에서도 드러나는데, 대표적인 구현 방식상의 차이는 저장소의 구조와 브랜치에 있다. 먼저 Git의 저장소는 스냅샷 기반이다. 모든 변경이나 파일을 포함하는 대상은 오브젝트로 표현되며, 오브젝트의 종류에는 커밋(Commit), 트리(Tree), 블롭(BLOB), 태그(Tag)가 있다. 블롭은 리프 노드로 실제 관리되는 파일이 여기에 들어간다. 그 외의 오브젝트는 다른 오브젝트를 참조하는 형식으로 아래와 같은 트리 구조를 만든다. 여기서 블롭에서의 관리 대상은 특정 시점의 파일 전체 내용이다. 그래서 깃의 저장소는 크기가 빠른 속도로 증가하는데, 이를 해결하기 위해 gc 명령을 제공한다. gc 명령을 수행하면서 접근 불가능한 브랜치는 삭제하고, 오래된 변경 집합(Changeset)은 diff 형태의 파일을 압축한 형태로 저장하여 저장소 효율을 높인다. 반면에 머큐리얼은 각 파일별 변경분만 추적한다. 저장소에는 실제 관리 대상이 되는 파일의 트리 구조와 동일한 형태의 .i를 확장자로 하는 변경 기록용 파일이 있으며, 그 파일에는 해당 파일이 가리키고 있는 파일의 변경 이력이 바이너리(binary) 형태로 저장되어 있다. 그로 인해 저장소는 변경분에 비례해서 증가하게 되며, 일반적으로 깃에 비해 완만한 속도로 저장소의 크기가 증가한다. 그래서 별도의 저장소에 대한 관리 작업이 필요하지 않다는 장점이 있다. 대신 패치(patch)의 생성이나 변경 이력의 추적에는 깃에 비해서 용이하나, 스냅샷의 생성이나 업데이트, 커밋 작업에는 대부분의 경우 Git에 비해서 높은 비용을 요구한다.[6]

병합 및 변경이력[편집]

병합과 브랜치는 분산버전관리 시스템이 SVN등의 기존 버전관리 시스템에 비해서 더 나은 가장 큰 장점 중 하나다. 분산 환경을 전제로 하고 개발된 시스템이므로 기본적으로 모든 변경 이력은 DAG(Directed Acyclic Graph)로 나타나며, 그로 인해 SVN의 단순 스냅샷 기반의 쓰리웨이(3-Way) 병합에 비해 영리한 병합 작업이 가능하다. 그것은 각 변경 집합이 부모 변경 집합에 대한 참조를 가지고 있기 때문인데, 이로 인해 충돌이 발생할 가능성이 현저하게 떨어지게 된다. 다만 구현상의 차이라기 보다는 동작상에 차이가 있다. 깃은 정말 대규모의 브랜치를 고려하므로 n웨이(n-Way0 병합을 지원한다. 반면에 머큐리얼의 경우 기본적으로 깃과는 다른 익명 브랜치를 기본 사양으로 하므로, 투웨이(2-Way) 병합을 기본으로 하여, N개의 병합 대상 브랜치가 있다면 N-1의 병합을 실행하게 된다. 전반적으로 머큐리얼이 제공하는 변경 이력 그래프는 깃에 비해 좁은 폭을 지니고 SVN의 이력 관리와 상당히 유사한 면모를 보인다. 그로 인한 대표적인 차이점이 머큐리얼은 로컬 저장소에 있는 변경 이력에 대해 SVN의 리비전(Revision) 번호와 같은 리비전 번호를 제공한다. 다만 이 변경 이력이 복제된 다른 저장소에서도 유지된다는 것을 보장하지 못하므로, 식별자로서 사용하는 것은 의미가 없다. 그래서 이 차이점은 초기 적응에는 도움이 될 수 있지만, 최종적으로는 머큐리얼에 대한 오해를 불러 일으키는 원인이 되기도 한다. 분산버전관리 시스템의 브랜치는 기본적으로는 저장소의 복제를 기반으로 동작한다. 하지만 깃과 머큐리얼은 둘 다 태깅(Tagging)을 기본으로 하는 브랜치 기법을 제공한다. 분기된 특정 커밋에 태그를 붙이면, 해당 태그가 브랜치의 이름처럼 동작한다. 거의 동일하지만 큰 차이 중 하나는 저장소를 원격 저장소에 반영하거나 혹은 그 반대의 작업을 할 때, 브랜치에 대한 동작이다. 머큐리얼의 경우에는 모든 브랜치를 한 번에 반영한다. 그에 반해 깃은 현재 작업 중인 브랜치만 반영한다.[6]

성능[편집]

깃 같은 경우 프로젝트의 규모에 비례하여 저장소의 규모가 상당히 빠른 속도로 증가하며, 대조적으로 머큐리얼은 완만하게 선형적으로 증가하게 된다. 대신 스냅샷 기반이므로 대규모의 프로젝트에서도 일정한 성능을 유지하며, 대체로 머큐리얼보다 빠르다. 반면 머큐리얼의 경우 차이점 기반이며 디스크 I/O가 적으므로, 대량의 읽기/쓰기가 발생하는 상황에서도 비교적 안정적이다. 그러나 프로젝트 규모가 커지고, 변경 이력이 쌓일 수록 패치를 병합하는 비용이 증가한다. 또 머큐리얼의 저장소는 Append 기반으로 동작함에 따라, 디스크에 오류가 있을 때에 저장소가 영향을 적게 받는다는 점도 머큐리얼의 장점이 된다.[6]

각주[편집]

  1. 전호진, 〈분산버전관리 시스템 git 소개〉, 《깃허브》, 2015-06-10
  2. 2.0 2.1 고코더, 〈깃(git) - 분산버전관리 시스템이란? (DVCS)〉, 《티스토리》, 2019-12-03
  3. 3.0 3.1 3.2 분산버전관리 〉, 《위키백과》
  4. hwanseok_dev, 〈쉽게 정리한 Git 사용법 : 분산 버전 관리 시스템DVCS〉, 《티스토리》, 2019-02-18
  5. 1.1 시작하기 - 버전 관리란?〉, 《개인 블로그》
  6. 6.0 6.1 6.2 6.3 6.4 6.5 정지웅, 〈Git vs. Mercurial〉, 《네이버 D2》, 2011-12-23

참고자료[편집]

같이 보기[편집]


  검수요청.png검수요청.png 이 분산버전관리 문서는 소프트웨어에 관한 글로서 검토가 필요합니다. 위키 문서는 누구든지 자유롭게 편집할 수 있습니다. [편집]을 눌러 문서 내용을 검토·수정해 주세요.