얼마 전 분산 저장소에 대한 팀 내 관심이 뜨거웠다. 때마침 실험적 시도를 할 수 있는 작은 프로젝트를 진행하게 되었는데, 프로젝트 참여자들과 논의하여 Git 도입을 시도했다. Git을 사용해보며 여러 가지 요소를 평가 중인데, 그 중 개인적으로 관심이 있는 부분은 Git이 내가 일하는 환경의 어떤 부분을 향상시켜 줄 수 있느냐이다. 좀 더 나아가 SVN을 사용하고 있는 우리 회사가 Git으로 전환해야 하는지에 대해서도 관심이 있다.

1. Git의 특징

예전에는 중앙 저장소가 있고 모든 개발자가 중앙 저장소에 자신의 작업을 커밋했다. 반면 Git은 분산 저장소를 제공한다. 따라서 중앙 저장소가 있더라도 해당 저장소를 로컬에 복사(clone)하는 순간 로컬에 나만의 저장소가 생긴다. 따라서 예전처럼 원격 저장소에 영향을 미치지 않고 로컬 내에서 브랜치를 만들고, 커밋하고, 롤백하는 일 모두 가능하다. 

만약 중앙 저장소에 내 작업을 넣고 싶으면 어떻게 할까? 예를 들어 어떤 저장소를 로컬에 복사한다. 그리고 파일 하나를 수정한다. 원격 저장소에 변경사항을 반영(push)하려하면 변경사항이 없다고 나온다. 이는 예전과는 달리 사용자와 중앙 저장소의 입장이 아닌 로컬 저장소와 원격 저장소의 입장이 되기 때문에 발생하는 일이다. 즉, 로컬 저장소에 커밋을 하지 않았기 때문에 변경이 없다고 보는 것이다. 로컬 저장소에 커밋을 한다. 그리고 다시 변경 사항을 반영해본다. 이제서야  변경사항이 원격 저장소에 적용된다. 방금 얘기한 것이 Git의 가장 기본적 흐름이다.

2. 오픈소스가 Git으로 전환하는 이유에 대한 견해

오픈소스는 소수의 커밋터(Committer)와 다수의 공헌자(Contributor)로 구성된다. 커밋터를 제외한 공헌자는 익명으로 소스를 체크아웃하고 로컬에서 작업한다. 작업이 어느정도 완료되면 패치를 만들어 커밋터에게 적용을 요청한다. 이 모델은 대부분 오픈소스에서 사용하는 개발모델이다. 그런데 문제점이 있다. 바로 공헌자는 패치를 완료하기 전까지 SCM의 이점을 전혀 못 누린다는 점이다. 저장소가 없으므로 중간에 커밋을 할 수도 없고 롤백도 할 수 없다. 당연히 브랜치도 만들 수 없다. 따라서 어떤 공헌자가 한 프로젝트에 대해 여러 패치를 동시에 작업해야 한다면 이는 기존 SVN 환경에서 쉽지 않은 일이다. 

Git을 이용하면 방금 얘기한 문제가 해결된다. 중앙 저장소에 권한이 없더라도, 로컬에서 얼마든지 SCM의 장점을 누릴 수가 있다. 작업하다 잘못되면 롤백을 할 수도 있고, 몇 개 브랜치를 만들어 여러 패치를 동시에 작업할 수도 있다. 난 이런 이유로 오픈소스진영에서는 Git을 반길 수밖에 없다고 생각한다.

3. 그럼 회사에서도 Git이 필요할까?

Git에 대해 긍정적 의견을 내비치는 사람의 근거 중 하나는 오픈소스진영이 점차 Git으로 전환하고 있다는 점이다. 오픈소스 진영은 기술적 트렌드에 민감한 편이고, 오픈소스에 먼저 적용한 기술이 시간이 흘러 대중화되는 것은 매우 자연스러운 흐름이다. 그렇다면 회사에 Git을 도입하는 것은 어떨까? 난 아래 두 가지 이유로 신중한 접근이 필요하다고 본다.

첫째 회사는 오픈소스진영과 개발상황이 다르기 때문이다. 가장 큰 차이점은 오픈소스에는 흔한 공헌자가 없다는 것이다. 팀원 모두 커밋터고, 팀은 저장소 하나를 공유하며 함께 작업한다. 따라서 수정한 것이 있으면 바로 커밋을 하면 된다. 팀원 모두 커밋터로써 SCM의 장점을 충분히 누릴 수 있다.

둘째 지속적 통합에 대한 부정적 영향을 미칠 가능성이 있기 때문이다. 여럿이서 저장소 하나를 대상으로 함께 작업하다 보면 지속적 통합이 무척 중요하다. 다시 말해 동작하는 버전을 자주 커밋하는 게 강력히 권장된다. 이를 잘 지키면 다른 동료에게 빠른 피드백을 줄 수 있고, 통합 시점(보통 QA 혹은 배포 전)에 소스가 충돌이 나 소스를 급하게 수정하는 일도 줄어든다. 그렇다면 Git은 어떨까? 난 Git은 지속적 통합이 추구하는 바에는 잘 안 맞는 것 같다고 생각한다. Git은 로컬 저장소를 제공하기 때문에 로컬에서 커밋하고 롤백하며 작업할 수 있는 좋은 토양을 제공한다. 이로 인해 자주 통합하기보다는 소스를 로컬에 오래 가지고 있는 상황이 생기지 않을까라는 우려가 든다.

4. Git에서도 지속적 통합이 가능하다?

누군가는 이렇게 얘기할 수 있다. '로컬 저장소가 제공되는 Git을 쓰자. 그리고 예전처럼 자주 커밋하자. 예전과 다를 바가 없지 않나?' 그런데 여기 약간의 걸림돌이 있다. Git은 SVN, CVS와 달리 중앙 저장소에 바로 커밋할 수 없기 때문이다. Git은 로컬 그 자체가 저장소이기 때문에 우선 로컬 저장소에 커밋을 수행한 후에 로컬 저장소를 원격 저장소에 머지(push)하는 방식으로 통합한다. SVN, CVS를 사용할 때는 단순한 파일 하나를 수정할 때 커밋을 하면 끝이었다. 하지만 Git은 로컬 저장소에 커밋하고 원격 저장소로 머지해야 한다. 즉, 두 단계가 필요한 것이다. 별것 아닌 것 같지만, 개발자가 가장 많이 수행하는 흐름이 좀 더 길어진 것이다. 물론 두 단계를 한꺼번에 수행해주는 도구를 개발하면 쉽게 해결되는 문제이다. 하지만, 도구를 쓰는 단계까지 간다면 Git을 써야 하는 이유가 많이 퇴색되는 게 아닐까?

5. 커밋터에게 로컬 저장소가 필요한가?

앞서 소개했지만, Git의 가장 큰 장점은 로컬에 나만의 저장소를 둘 수 있다는 점으로 보인다. 그런데 과연 이 특성이 현장에서 얼마나 필요할까? 예전에 가끔 로컬에서 중간 중간 커밋하고 싶다는 생각을 한 적이 있다. 하지만, 당시 내가 그런 생각을 했던 이유는 지속적 통합을 하지 않고 있었기 때문이었다. 나는 소스를 광범위하게 고치고 있었고, 다음 수정에서 무엇인가 잘못되어 예전에 작업한 부분도 없어질까 봐 두려웠다. 하지만, 지속적 통합을 실천하며 다시 이런 생각을 한적은 없었다. 항상 동작하는 버전을 자주 커밋했다. 때로 1시간에 수십회를 커밋하기도 했다. 테스트가 통과하면 바로바로 커밋하기 때문이다. 

6. Git은 머지가 편하다?

가끔 Git과 같은 분산저장소를 사용하면 머지가 편해진다는 얘기를 듣는다. SVN에서 소스충돌은 다른 개발자가 같은 라인을 수정해서 발생하기도 했고, 어떤 때는 SVN의 오판으로 발생하기도 했다. 소스충돌이 일어났을 때 소스를 정리하는 작업은 정말 어렵고 힘들다. 따라서 Git이 머지를 편하게 해준다면 이는 큰 매력이다. 하지만 Git홈페이지(http://git-scm.com/about)를 보면 여러 장점을 소개하지만 머지에 대한 언급은 없다. 어디서 이런 얘기가 나왔는지는 모르겠지만, 확인이 필요한 부분 같다.

7. 결론

Git이 제공하는 가장 주요한 특징은 분산 저장소이다. 많은 오픈소스에서 Git을 잘 쓰고 있는 것처럼, 분명히 분산 저장소라는 특징이 빛나는 상황이 있을 것이라 생각한다. 하지만, 이 점이 Git으로 전환할 만한 충분한 이유가 될까? 난 아직 잘 모르겠다. 지금까지 내가 이해한 수준에서는 전환비용을 감당하면서도 넘어가야 할 이유를 찾기 어렵기 때문이다. 오히려 가뜩이나 잘 되지 않는 지속적 통합을 더 악화시키지 않을까라는 우려가 있다. 하지만 Git이 SVN 보다 머지기능이 탁월하다는 것이 밝혀진다면, 이는 Git으로 전환해야 하는 좋은 근거가 되리라 생각한다.

8. 참고

1) C와 같은 개발 환경에서는 Git이 지속적 통합에 해가 된다기 보다는 오히려 여러 장점이 있다는 의견을 담은 글
http://hyukhur.tumblr.com/post/4126008077/git-for-more-continuous-building 

2) 덧글 중 benelog님의 반대 의견도 참고

3) benelog님의 Git 유랑기 



WRITTEN BY
차민창
르세상스 엔지니어가 사회를 이끌어나가는 상상을 하며!

트랙백  1 , 댓글  15개가 달렸습니다.
  1. Git 장점 중
    손쉬운 branch 전환이 빠진 것 같아.
    미투에서도 그 얘기 나왔었는데
    http://nvie.com/posts/a-successful-git-branching-model/
    여기 참고
    • 링크 고마워. 지금 늦게 들어와서 우선 아래 덧글 달았는데. 곧 읽어보고 의견 줄게. 아니면 좀 요약해주면 더 좋고. 요즘 왠지 영어문서 읽기가 너무 고통스러워서.
    • 응, 얘기한 대로 로컬에서 브랜치를 따고 전환하는 게 SVN에 비해 자유롭다 보니 장점이 있는 것 같네. 특히 Hotfix같은 브랜치는 로컬에서만 금새 따서 작업하고 삭제해버리니 의미가 있는 것 같고.

      그런데 문서 읽다보니 브랜치 관리 방법에 더 관심이 가네. 예를 들어 우리는 Hotfix 브랜치 따로 따는 팀이 있나? 보통 릴리즈 브랜치에다가 바로 작업해서 내보내던데 말이야. 문서에서 얻은 부분 있으면 좀 자세히 공유해주면 좋겠는데?

      P.S 읽는 건 누워서 아이패드로 읽고 아이패드는 로그인 하기 귀찮아서 다시 일어나서 노트북으로 덧글 다는 중 ㅋ
    • 아참 한가지 더...

      GIT 이 아니라 Git 이라고 공식 문서에 써있던데? ㅎㅎ

      위에 다 수정해죠~
  2. GIT이 CI와 안 맞다는 부분은 제 생각과 다른데요,

    제 경험으로는 CI를 설치하고도 무용지물이 되는 대부분의 상황은 개발자들이 commit을 자주 안 하고 local에 가지고 있는 때보다는 실패하는 build를 방치하는 경우였던 것 같습니다. 그런데 왜 실패하는 것을 방치하는지 보면, 너무 자주 실패하고, 내가 실패한 것 고쳐봤자 다른 이유 때문에 계속 fail이 나니 내 것도 고칠 이유도 없어지는 경우였었습니다. 깨진 창문이죠.

    그런데 왜 그렇게 자주 실패하게 되느냐를 보면, commit을 하기 전에 local에서 update와 builld를 안 돌려보고 그냥 commit을 해서 CI를 보고서야 fail 난 것을 알게 되니 그런 것 같습니다. polling 주기와 build time 때문에 대부분 5분 뒤에야 결과를 알게 되고, 그것도 메일로 오니까 메일을 계속 확인하고 고쳐야 하는데, 프로젝트 사람 수가 많을 수록 메일도 너무 많이 오고, 결국 너무 많은 신호는 Noise가 되어서 그걸 무시하게 되죠. svn의 경우 commit이 간단한 것처럼 말씀하셨는데, commit == 통합인 svn에서는 진정한 통합을 하려면 svn update->mvn test -> commit의 단계를 모두 거쳐야지 다수가 진행하는 프로젝트에서는 깨진 창문이 생기지 않습니다. 5명 이상이 참가하면서 활발히 commit을 하는 신규 개발 프로젝트에서 그런 절차 없이 build가 자주 안 깨지게 하는 것은 정말 어렵습니다. 그러다보면 거의 개발자들은 update와 test없이 자주 commit을 하고 자주 fail을 내어서 CI의 신호가 noise가 되게 쉽게 하던지, 아니면 아예 자주 commit을 안하게 되는 경우가 많아집니다. 자주 commit을 하면서 svn update, mvn test를 다 돌려보기는 어려우니까요. DVCS에서는 기록작업인 commit과 통합인 push를 분리해서, commit은 기록의 의미로서 자주 자주 하고, 통합작업인 'push' 전에 git pull, mvn test를 하면 된다고 생각합니다.

    기록과 통합의 반드시 일치하지는 않고, 기록으로서의 commit은 자주 할 수록 이력추적, rollback 등에 유리합니다. 통합은 자주하면 좋지만 안 깨지는 상태를 유지하기 위해서는 통합의 확인비용이 있기 때문에 매번 버전관리에 기록할때마다 통합을 하는 것이 반드시 이득은 아닐수도 있습니다. 통합은 commit 만이 아니고, update, 전체 test를 포함한 행위이고, CI에서 확인 전에도 local에서도 최선의 실패예방 작업을 해야지 보다 의미있는 신호를 CI에서 받을 수 있습니다. 많은 사람이 참여할 프로젝트일수록 commit과 통합이 같은 개념이 된다면 commit을 자주하지 못하거나 통합의 실패를 무시하게 됩니다. 통합은 자주하면 좋지만 기록인commit는 통합보다 더 자주할 수록 좋다고 생각하구요.

    그리고 SVN에서는 장기 branch을 merge한 뒤에 commit해도 svn에서는 단 한줄의 이력밖에 안 남는다는 단점이 있는데, 그 점도 큰 단점이라고 생각합니다.

    외국의 사례가 전부는 아니겠지만, 조엘의 글을 보면 오픈소스가 아니라도 DVCS가 의미가 있다고 생각하는듯합니다.
    암튼 merge에 대해서는 충분한 시나리오 검증을 해보지는 못했지만, commit과 publish의 논리적 구분을 하는 것만으로도 DVCS에 CI에도 긍정적인 부분이 있지 않을까 생각을 해봤습니다.
    • 먼저 좋은 의견 주셔서 감사드려요. 회사에서도 그렇지만 항상 누군가에 의견을 읽고 이렇게 방대한 양의 의견을 주시는 것에 대해서는 본받고 싶은 마음이 큽니다. 특히 제가 잘 못하는 부분이라서요.

      덧글을 읽어보니 아마 경험적인 부분에서 갖게 된 시각의 차이가 있는 것 같아요. 이 때문에 의견이 갈리는 것 같고요. 저도 경험과 생각을 좀 더 자세히 얘기해볼게요.

      저는 예전 팀에 있을 때 거의 20~30명이 넘는 사람들과 함께 작업을 했지만, 말씀하신 대로 Noise라고 느낄 정도로 커밋 빌드가 깨진 경험을 하진 못했어요. 물론 CI를 도입하는 초기에는 빌드가 자주 깨지고 신경을 안 쓰는 사람이 많았습니다. 하지만, 팀 내 몇몇 뜻 있는 사람이 자발적으로 먼저 고치고 전체 메일로 공지하는 등의 활동을 한 후에는 그런 일이 현저히 줄어들었습니다. 결과적으로 커빗 빌드가 깨지는 일도 그렇게 많지 않았고, 2009년 크리스마스 이브 때는 커밋 빌드가 깨져 장애가 날 만한 잘못된 수정을 발견하기도 했었어요. 이는 커밋 빌드의 실패를 최소한 Noise라고 느끼지는 않았다는 당시의 상황을 잘 증명해주는 사례라고 생각하고요. 저는 그래서 SVN상에서 지속적 통합이 말씀하신 만큼 어렵다라는 생각은 잘 하지 못했던 것 같아요. 이 부분은 경험에 한계 때문에 그럴 수도 있는 부분이라 생각하고요.

      DVCS에서 기록과 통합을 분리하는 부분 말씀주셨는데요. 제가 우려하는 부분이 사실 바로 그 부분이에요. 로컬 저장소에 기록하는 동안 통합이 늦어질까봐 우려가 됩니다. TDD에서의 보폭처럼 같은 이유로 저는 통합도 작은 보폭이 무척 중요하다고 생각해요. 왜냐하면 보통 보폭이 크면 클수록 문제가 생겼을 때 치뤄야 할 대가가 커지기 때문이에요. 그래서 어떤 수정이라도 잘게 나눈 후 '동작하는 버전'으로 조금씩 작업해서 자주 커밋/통합하는 게 가장 좋다고 생각해요. 이게 실제로 가능하냐라는 의문이 생길 수 있는데요. 제가 이 생각을 2009년에 처음한 후에 제가 진행하는 프로젝트에 스스로 실천을 해보았어요. 결론은 그렇게 어렵지 않았어요. 물론 제가 당시에 시험했던 프로젝트가 리팩토링 프로젝트라 일반적 프로젝트와는 다르긴 했어요. 하지만, 기능 추가를 할 때라도 여전히 미리 조금씩 통합할 수 있는 부분이 분명히 존재하리라 예상해요.

      또한 개발자들이 여하간의 이유로 커밋을 두려워 하게 되는 경우는 자주 있을 수 있다고 생각합니다. 하지만 저는 이 문제를 DVCS로 풀어야 할 문제인가에 대해서는 강한 의문이 듭니다. 근본적 해결이 아니라 뭔가 잘못된 것과 타협하는 느낌이랄까요? 저는 이 문제는 이해와 합의 등을 통해 행동을 변화시킴으로써 풀어야 할 문제라고 생각해요. 예전에 팀내 메일로 오갔던 조엘의 번역글에서 조엘이 커밋을 자주 안 하는 개발자 때문에 DVCS가 좋았다고 했는데, 저는 위 이유로 이에 대해서는 공감을 전혀 하지 못했고요.

      '통합을 자주하는 것이 항상 이득이지 않다'라는 말씀은 저도 가끔 생각이 드는 부분인데요. 사실 충분히 생각의 정리가 안 된 관계로 우선은 지속적 통합이 좋다라는 전제를 가지고 사고를 하고 있는 상황입니다. 만약 통합을 자주하는 것이 항상 이득이지 않다면 DVCS가 강점을 보일만한 부분인 것 같아요. 머지 후 이력 문제 또한 공감하고 이견이 없습니다.

      방금 말씀드린 대로 저는 지속적 통합이라는 전제를 그대로 받아들이고 있는 상황인데요. 이 전제가 보편성이 많이 떨어져 상황에 따라 매우 유연하게 적용되어야 한다면 저는 이 글의 내용을 비롯하여 생각의 전환이 많이 필요할 것 같아요. 답글을 쓰다보니 제가 너무 지속적 통합에 매달렸나라는 의문이 들기도 합니다.
    • \민달\
      민달의 지속적인 통합에 대한 너무 좋은 기억들이 Git 의 장점이 가려지는 현상이 나타난 것 아닐까?
      특히 C 개발 하시는 분들에게 Git 의 장점이 더 다가오는 것 같아...
      빌드가 깨져서 머지를 못한다니~ 뭐 그런 얘기를 종종 들게 되거든...
  3. 조만간 트랙팩 달 방법 찾아서 다 연결할께~
    텀블러는 몇가지 기능 지원이 안되는게 있어서..
  4. Git 공부 좀 하다보니
    네가 궁금해 하던 머지와 관련된 부분이 있는 것 같아서
    남겨

    http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#using-bisect
  5. 비밀댓글입니다
  6. 좋은 글 감사합니다.
    저희 조직도 svn에서 git으로 전환을 고민중이었는데(그냥 요즘 쓴다니까), 안해도 무방하다는 결론을 얻었습니다.
    소수의 아키텍트가 기본 구조를 꽉 쥐고 관장하는 이상 svn의 빠른 커밋과 충돌날리 없는 수준으로 클래스와 파일들을 배치하는 것이 충분히 효율적이라는 생각을 했습니다.
    오히려 svn의 단순한 구조가 신입이 들어와도 업무를 이해시키기가 빠르더군요. 걍 커밋은 업로드고~다운로드는 업데이트라고 생각하면 되~라고 하면 되니까요.
    무엇보다도 VisualStudio같은 IDE의 플러그인이나, TortoiseSVN같은 Gui기반 툴은 막 시작된 Git 계열보다는 SVN이 훨씬 안정적이고 쓰기 편하게 다듬어져있지요.
    • YJ님 의견 감사합니다. 말씀하신 맥락과 적용 사례에 공감합니다.

      말씀대로 Context에 따라서 판단하고 적용여부를 결정하는 것이 좋다고 생각합니다. 조직의 특성과 개발패턴에 따라 Git이 필요할수도 필요하지 않을수도 있겠죠.
  7. 좋은글 잘 봤습니다. :-)
    다른 관점의 생각을 약간 정리했다가 @YJ 님 댓글에 대한 댓글을 보니.... 안달아도 되겠구나 싶네요.
    조직의 특성과 개발 패턴에 따라 장단점은 있다는 것에 공감합니다.
    • Rhio.Kim님 의견 감사드립니다.

      위 글은 좀 오래 된 글인데요, Git을 거의 은총알처럼 신봉하는 분위기 때문에 한번 생각을 정리해봤던 부분입니다.

      저도 아직 Git을 긴밀한 협업환경에서 써보지 못해서 그런지 몰라도 아직까지 글에 썼던 생각이 크게 바뀌지는 않았네요.

      나중에 Git을 더 많이 써보게 되고 경험이 쌓이면 다시 정리해보려 생각중입니다.
  8. 굉장히 오래된 글인데 지나가다가 한번 글 남겨 봅니다 ㅎㅎ Git을 적용하려다가 "아... 거 봐, 별로지?" 하면서 그만두시는 분들이 나올까봐 염려되어서요.

    ## 1. GitHub or GitLab을 꼭 사용해 보세요.

    Git의 진가를 경험하시려면 github, gitlab 등의 remote repository를 지원하는 서비스에서 issue와 연결되는 feature branch, merge request 등의 기능을 사용해 보아야 한다고 생각해요.

    Issue와 branch를 연결할 수 있고, master 외의 branch는 누구든 만들어서 push할 수 있기 때문에 작업중이던 내용을 상세한 description과 함께 backup하는 효과를 기대할 수 있습니다.

    Merge request를 통해 source code의 특정 line에 대해 discussion할 수 있고, 이는 당사자 뿐 아니라 참여하고 있는 멤버들 모두의 기술 수준 향상에 큰 도움이 됩니다.

    Merge request의 경우, local에 소스를 오래 가지고 있지 말고, 빨리 commit해서 올리는 것을 추천하고 있습니다.
    이를 별도로 Review request라고 부르기도 하고요.
    이렇게 해야 관리자가 작업 방향을 보고 미리 조언해 줄 수 있어서 돌아가는 일을 줄일 수 있기 때문입니다.
    로컬에 commit이 오래 남아있는 일은 이와같은 workflow를 통해서 피할 수 있습니다.

    ## 2. 좋은 git client를 사용해 보세요.

    GitKraken을 추천합니다. 빠르고 직관적인 client가 있으면 접근성이 훨씬 좋아집니다.

    http://jmyl.gitlab.io/post/gitkraken/ 를 참고하세요.

    ## 3. SVN과 용어를 혼동하지 않도록 해야 합니다.

    사용하는 용어가 유사합니다만, 실은 매우 다릅니다.
    아예 "잊어버리고" 생각하시는게 도움이 됩니다.

    제가 현업에 실제 사용하고 있는 입장에서, git 없이 어떻게 개발했나 싶은 생각입니다.
    무엇보다 SVN을 사용할 때 보다 branching하고 branch를 오가며 일 하는 일이 훨씬 많아집니다.
    이를 통해 각각의 작업을 context changing하며 작업하고, 자연스레 백업이 이루어집니다.
    리뷰를 통해 팀원들이 성장하는 것도 부가적인효과고요.

    결론: git을 강추합니다... ㅎㅎ
secret