2009년 1월 7일 수요일

하루에 몇 번 커밋하세요?

한 개발자가 하루에서 수도 없이 커밋(Commit)을 하고 있다면 소스코드관리시스템을 백업서버로 쓰고 있을 가능성이 높습니다.
사실 이러한 경우를 매우 자주 봤습니다.

혹시 코딩을 하다가 점심 먹으러 간다고 한번 커밋하고 중간 중간에 수시로 커밋을 하고 있으면 이건 좋은 방법은 아닙니다.
혹시 이런 방법으로 소스코드관리시스템(SVN, CVS, VSS, ClearCase 등)을 사용하고 계신지 확인해보십시오. 본인이 아니라도 이렇게 백업용도로 사용하고 있는 동료나 후배가 없는지 확인해보십시오.

커밋을 하면 소스코드의 Revision이 바뀌게 되는데, 각각의 Revision은 의미를 가지게 됩니다. 
그 의미가 "점심 먹으러 나가면서 임시로 저장" 이렇게 되면 곤란합니다.

각 Revision의 정보는 우리회사 개발의 역사로서 영원히 남게 되는데 그런 쓰레기 정보를 남기면 안되죠.
누군가는 각 Revision에서 바뀐 내용을 알기 위해서 Diff를 해볼 것이고, 이를 이용해서 Merge도 할 수 있고, 원 소스코드 작성자에게 내용을 물으러 올 수도 있습니다.

그래서 커밋(Commit)은 아무 때나 아무렇게나 하면 안됩니다. 각 회사마다 소스코드관리시스템을 사용하는 규칙이 필요하고, 이를 지켜야 합니다.
소스코드를 수정하기 위해서는 항상 버그ID(Issue ID)가 필요하며 그에 따른 수정 내용은 한번에 커밋을 하는 것이 바람직합니다. 그리고 커밋을 할 때는 회사의 규칙에 맞는 형식으로 Message를 남겨주어야 합니다. 이때 버그ID와 수정 내용 및 Peer Review(Desk check 정책을 사용할 경우)를 한 사람은 꼭 기록하는 것이 좋습니다.

이렇게 쌓인 소스코드관리시스템의 History와 마구잡이로 규칙없이 사용한 History는 나중에 그 가치와 활용도가 확연히 차이가 나며 개발 생산성에 많은 영향을 주게 됩니다. 

사소해 보이지만 쌓이면 정말 큰 차이가 나는 중요한 개발 규칙 중 하나입니다.

댓글 24개:

  1. 커밋은 자주하는 것이 좋죠. 로컬에 있는 소스는 부패하기 쉬운 코드입니다.

    답글삭제
  2. allting님 안녕하세요.
    저와 다른 의견이지만 의견을 주셔서 감사합니다.
    자주 커밋을 하면 PC가 망가져도 소스코드를 지킬 수 있는 장점이 있는 반면 제가 위에서 나열한 단점도 있겠습니다. GIT같은 분산형 SCM을 써서 일부 보완을 하기도 합니다.
    제가 사람들에게 강조하는 것은 항상 원칙이죠. 원칙에서 좀 벗어나도 지금의 환경에서는 문제가 없을 수 있어도 조직이 아주 커지는 등의 환경이 바뀌면 문제가 있을 수 있기 때문이죠. 그래서 원리와 원칙을 이해하고 있으면 여러 상황에도 가장 효과적인 방법을 제시할 수 있겠죠.
    감사합니다.

    답글삭제
  3. 저도 위에 댓글 다신 allting님과 같은 생각입니다.
    소스 관리의 목적에는 물론 그 히스토리를 보존하겠다는 의미도 있겠지만,
    공동작업시의 소스의 동기화도 무시할 수 없는 의미가 있기 때문이지요.

    아무래도 혼자서 커밋안하고 소스를 점유하고 있으면,
    동기화라는 측면에서 그만큼 리스크를 안고 가는 거라고 해석할 수도 있고,
    동료에게도 피해가 가게 마련입니다.

    실무적인 측면을 좀 더 강조해서 조심스레 반대의견을 적어 봅니다.

    답글삭제
  4. 자주하는 것이 나쁜 것이 아니라 의미없는 커밋이 잘못된 것 같습니다. Task가 작은 단위라도 하나 하나가 의미가 있다면 문제가 없다고 봅니다. 루돌님께서 말씀하신 소스의 동기화도 팀내부의 룰에 따라 의미있는 Task 단위로 운영된면 된다면 조금 늦게 공유되더라도 더 효율적이라고 생각합니다. 테스트 되지 않은 Task는 때로는 구현되지 못한 것 보다 더 못하고 비효율적인 것을 양산할때가 많은 것 같습니다. 이와 함께 CI를 운영한다면 더 효율적일 것이라 생각합니다.

    답글삭제
  5. 개발 완료 80%가 되면 일단 서버에 올립니다. 그전엔 귀찮아서 잘 않하게 되죠.

    답글삭제
  6. 루돌님 안녕하세요.
    좋은 의견 감사합니다. 루돌님이 말씀하시는 것을 충분히 이해하지만 좀더 부연 설명을 하는 것이 좋겠네요. 루돌님은 어떤 SCM을 사용하시나요?
    좋은 토론거리를 찾은 것 같아서 좋습니다.

    1. 예를 들어서 버그ID 123번을 할당 받은 다음에 이를 수정하는데 10분이 걸렸으면 소스코드를 가져와서 10분동안 수정하고 확인 후 커밋을 하면 됩니다. 이런 경우는 커밋하는데 10분 밖에 걸리지 않습니다.

    2. 다른 경우 150번 버그를 수정하는데 여러 소스코드를 수정해야 하고 하루 종일 걸렸으면 이를 다 수정한 후데 커밋을 해야죠. 중간 중간에 백업을 목적으로 커밋을 하는 사람이 많은데 중간에 수정하다 만 소스는 커밋을 해도 공동작업에 별로 도움이 되지 않습니다.

    3. 그러면 이런 경우는 어떨가요? 하루에 5개의 버그를 수정해야 하는데, 이를 모두 수정한 다음에 한번에 커밋을 하는 경우는 바람직하지 않죠. 각 Revision은 하나의 Issue해결과 일치 시키는 것이 좋죠.

    2번의 경우 하나의 파일을 2명이 수정하는 경우가 생기는데 SVN은 자동으로 Merge를 해주고, Conflict가 일어날 경우 3-way merge툴을 이용하면 편리하게 Merge가 됩니다. 그리고 2번에서 백업용도로 커밋하는 경우 완전히 테스트되지 않은 코드가 커밋이 되어서 Broken Tree가 발생하면 여러사람에게 민폐를 끼칠 수도 있게 됩니다.
    과거 VSS를 사용할 때는 Lock정책을 이용했기 때문에 한사람이 코드를 통째로 수백개씩 Lock을 걸어서 Lock 풀어달라고 하기 일쑤였는데, SVN을 사용하면서 그 방식이 달라졌습니다.
    VSS또는 Lock방식의 소스코드관리리스템을 사용하고 있다면 루돌님이 말씀하신 문제가 발생합니다. 하지만 SVN은 내가 어떤 파일을 수정하고 있어도 다른 사람은 그 사실을 알 수가 없죠. 비로소 내가 Commit을 해야 알게 되죠.

    다음에는 VSS와 SVN을 비교하면서 소스코드관리 방법이 어떻게 달라졌는지 자세히 글을 쓰는 것도 좋겠네요.

    답글삭제
  7. 정의의소님 안녕하세요.
    제가 답변을 다는 사이에 의견을 주셨네요. 제 답변 내용과 같은 내용도 포함되어 있네요. :)
    좋은 의견 감사합니다.

    답글삭제
  8. 묘재님 안녕하세요.
    제가 묘재님 개발 환경을 정확하게 모르니 정확하게 의견을 달기가 어렵네요. ^^
    그렇게 하신다면 혹시 주로 혼자나 소수의 인원이 개발을 하시나요? SCM의 History는 알파이전에는 별 의미가 없으니 그렇게 하셔도 문제는 없지만 소스 공유라던지 안전한 보관 문제로 어떻게 하는 것이 가장 좋은지는 생각해 볼 문제 입니다.

    답글삭제
  9. 이 글을 읽고 나니, 이클립스의 Mylyn 이란 프로젝트가 왜 생겼는지 알겠네요. Mylyn은 태스크 관리도 있지만 버전관리와도 통합이 되어 있어서 커밋시에 자동으로 관련된 버그나 태스크를 로그에 포함시켜 줍니다.

    답글삭제
  10. 지속적인 통합(CI)을 이용할 경우 잦은 커밋이 도움이 된다라고 알고 있지만 그렇다고 임시저장성까지 포함하지는 않다고 생각합니다. 오픈소스프로젝트의 소스저장소를 보면 정말 자세하게도 업무단위를 작은 조각으로 나누고 모든 커밋에 최소한 comment가 있더군요. 커멘트도 없이 무조건 저장용으로 쓰는것 과는 많은 차이가 있는 것 같습니다.
    그렇다고 커밋을 너무 미루면 소위 빅뱅통합의 악몽이 재현될 수도 있을 것 같고 커밋을 자주 할 수 있도록 업무단위를 나누는게 좋을 것 같은 생각이 듭니다.

    답글삭제
  11. 챠우차우님 안녕하세요.
    저도 같은 의견입니다. 업무 단위는 최대 1,2일 이하로 나누어서 최소한 하루, 이틀에 끝낼 수 있도록 해야 하고, 버그를 수정하는 경우는 이보다 훨씬 작은 일이 될 수 있겠죠.
    여러가지 수정을 한 것을 미뤄놨다가 한꺼번에 커밋을 하는 것도 나쁜 방법이죠.
    단위의 업무가 끝날 때마다 해당 버그ID와 같이 커밋을 하는 것이 깔끔하죠.

    답글삭제
  12. yeoupooh님 안녕하세요.
    그렇습니다. 이러한 일련의 개발 프로세스를 좀더 편리하게 하기 위한 여러가지 프로젝트들이 있었고, 지금도 계속 만들어내고 있습니다.

    답글삭제
  13. 제가 수행하는 프로젝트의 경우, 되도록 의미 있는 changeset 을 한꺼 번에 commit 하라는 규칙을 정해 놓고 있고, 적어도 컴파일이 되는지 확인한 후 commit 하라고 하고 있습니다.(솔직히 의미 있는 changeset 을 검증할 만한 방법이 없기 때문에 실효성 있는 규칙인지는 잘 모르겠습니다) 덧붙여 issue&defect management 와의 연동을 위해 로그 메시지에 ticket ID(또는 버그 ID)를 입력하는 경우에는 message 가 아주 짧더라도 정상 commit 되도록 pre-commit hook 을 사용하고 있습니다.

    SCM에서 commit 단위를 정하는 것은 쉽지 않은 일이라 생각합니다. 프로젝트에서 채용하고 있는 프로세스 및 S/W Infra와도 밀접한 관련이 있는 것 같구요.

    Ray님께서 그 동안 쓴 글들의 행간에 숨어 있는 가정을 생각하면 위 글이 잘 이해되지만 이 글만 읽으신 분들은 약간 오해할 수도 있을 것 같습니다.

    답글삭제
  14. 김윤수님 안녕하세요.
    소프트웨어 개발에서 기계적으로 되는 부분은 그렇게 많지 않죠. 그럼에도 하지만 원칙과 규칙을 가지고 있는 것은 상당히 중요하죠. 의미있는 changeset을 한꺼번에 commit하라는 규칙은 원칙이지만 100% 지키는 것은 불가능하죠. 예외 상황은 얼마든지 만들어낼 수 있고 애매한 경우도 있죠.
    그리고 이것을 잘 지켰는지 검증해서 패널티를 준다는 것은 별로 좋은 방법이 아니죠.

    모든 글에는 잘 썼던 못 썼던 반대 의견이 있을 수도 있고 오해도 있을 수 있는데, 그리 나쁜 현상이라고 보지 않고 꺼려하지도 않습니다. 오히려 여러 사람의 의견을 들을 수 있는 좋은 기회라고 생각합니다.
    감사합니다.

    답글삭제
  15. Trac 과 같은 이슈 트래커들의 경우 커밋 로그에 Trac 용 문법을 같이 지원하죠. 이를테면 커밋로그에 'fixed #432' 라 쓰면 Trac 의 timeline 에서 커밋로그 출력할 때 티켓 #432 번 하이퍼링크가 뜨죠. 이러한, 툴들에서 지원하는 편리함에 익숙해지면 위에서 언급하신 규칙과 아주 자연스럽게 맞아떨어집니다. 규칙도 간단하면서 같이 일하는사람이 편하죠.
    단, 매일매일 점진적 디자인개선(리팩토링)을 하고 싶을 경우 리팩토링 행위 자체가 버그는 아닌지라 고민을 하게 됩니다. (매번 리팩토링 작업을 티켓으로 올리기엔 여러 모로 문제가 있으므로) 그래서 '커밋된 코드들은 빌드와 테스트들을 깨뜨리지 않아야 한다' 같은 규칙 및 별도 커밋로그 룰을 추가해주어 해결하는게 좋습니다.

    답글삭제
  16. [1002]님 안녕하세요.
    항상 원칙을 먼저 이해하고 응용을 하는 것이 중요합니다. 버그의 범위를 어떻게 보느냐는 의견이 서로 다르겠지만, 저는 소프트웨어 변경을 가져오는 모든 이슈를 버그로 간주합니다. 즉, 새로운 기능의 추가조차도 버그로 간주를 합니다. 그래서 리팩토링 같은 경우도 모두 이슈를 등록합니다.
    이슈를 등록하지 않은 경우는 알파 베이스라인을 설정하기 전의 개발 단계정도 입니다.
    위에서 언급한 '커밋된 코드들은 빌드와 테스트들을 깨뜨리지 않아야 한다'는 것은 소스코드 관리의 가장 중요한 기본원칙으로 누구나 지켜야 합니다. 원칙을 지키시는 개발 방법을 사용하고 계시는 군요.

    답글삭제
  17. 좋은 지적입니다.
    무심한 행동을 돌아볼 수 있게 해주는 글이었습니다.
    커밋의 원칙을 따르되, 백업의 안전성 보장해주는 임시 리비전 같은 것이 지원되면 좋을 듯 하네요.
    아쉽게도 기존 도구가 지원하지 않으니, 외부 도구를 생각하게 됩니다.
    주기적으로 백업하는 아크로에디트의 김성동님의 ScheduleZipper, 파일을 저장할 때마다 백업하는 FileHamster 같은 도구가 있습니다.

    답글삭제
  18. 한인철님 안녕하세요.
    반갑습니다. 로컬작업의 백업이나 History관리 방법은 많으니 적절히 선택하면 좋을 것 같습니다. GIT를 이용해서 자신의 PC에서는 별도로 버전관리를 하면서 Main SVN과 주기적으로 Merge하는 방법도 있고, SVN에 Working 브랜치를 만들어서 관리하는 회사도 있습니다. 개발팀의 규모와 프로젝트의 성격 등을 고려해서 방법을 선택하면 됩니다. 하지만 항상 소스코드 관리의 원칙은 명심을 해야 할 것 같습니다.

    답글삭제
  19. 안녕하셔요?
    버전관리를 적용하려고 서브버전으로 공부하는 중입니다.
    작은 회사지만, 표준을 정하는 것이라 생각할 것이 많군요.
    여기에 올리는 것이 적합한지 모르겠지만, 몇 가지 조언을 부탁드립니다.

    1. 참조문서
    요구명세서, 회의록, 참고문서등 개발에 관련된 참조문서들을 저장소에 저장해야 할까요?
    체크아웃 한번으로 모든 자료를 얻을 수 있다는 장점은 충분히 이해합니다.
    하지만 단점도 있다고 생각됩니다.
    우선 체크아웃하는 크기 문제이고, 여러 브랜치로 작업하는 경우에는 불필요하게 중복해서 체크아웃해야 하는 것도 불만입니다.
    이런 문서를 어떻게 관리하는 것이 좋을까요?

    2. 중간파일
    라이브러리 같은 중간 파일을 효율적으로 이용하려면 어떻게 하는 것이 좋을까요?
    빌드시간 등의 문제로 인해, 소스에서 라이브러리를 빌드하는 것 보다, 빌드된 라이브러리를 이용하는 것이 효율적일 경우도 있을 겁니다.
    그렇다고, 소스와 결과물인 라이브러리를 모두 커밋하는 것은 좋은 방법이 아닐 것 같은데요.

    3. 릴리즈의 실행파일
    즉시 실행시켜 볼 수 있도록 릴리즈의 실행파일을 보관해 두려면, 어떤 방법이 있을까요?
    최종 결과물인 실행파일은 커밋할 필요가 없죠.
    그런데, 과거 릴리즈를 새로 빌드하는 것이 어려운 경우도 있을 겁니다.
    어렵더라도, 원칙대로 보관하지 않는 것이 좋을까요?
    버전관리와 별도로 보관하는 것이 좋을까요?

    결국, 무엇을 저장할 것인가, 효율적인 방법은 무엇인가 하는 문제입니다.
    비슷비슷하지만, 조금씩 관점이 달라서 나누어 문의드립니다.
    고견 부탁드립니다.
    감사합니다.

    답글삭제
  20. 한인철님 안녕하세요.
    장문의 글을 올려주셨군요. ^^ 3가지 모두 제가 쓴 책인 "소프트웨어개발의 모든 것"에서 중요하게 설명한 내용들입니다. 정답을 말씀드리면 정확한 답은 상황을 봐야 합니다. 하지만 일반적인 범주라고 생각하면 Baseline에 들어가는 것이 무엇인가에 대한 질문입니다. 원칙을 설명드리면 Baseline에는 개발문서와 소스코드, 빌드 스크립트, 외부 라이브러리의 바이너리등이 들어갑니다. 좀더 자세한 것은 책을 참조하세요. 그리고 각 질문의 표준 답안은 다음과 같습니다.

    1. 참조문서 - 요구명세서은 필수적으로 Baseline에 포함이 됩니다. 회의록과 참조문서는 원칙은 Baseline에 포함이 안됩니다만 프로젝트에 따라서 포함을 시킬 수도 있습니다. 상황에 따라서 생각해 봐야 합니다.

    2. 중간파일 - *.obj, *.lib, *.o 파일들은 원칙적으로 SVN에 저장하지 않습니다. 빌드시간 절약이 그렇게 큰 장점은 아닙니다. 단 우리가 빌드해서 만들어 낼 수 없는 바이너리 파일은 저장을 해야 합니다.

    3. 릴리즈의 실행파일 - 과거 릴리즈를 새로 빌드하는 경우가 어렵다고 하는 말씀하시는 것을 보내 Baseline 설정을 제대로 하지 않으신 겁니다. Baseline만 제대로 설정하면 언제든지 바이너리를 만들어 낼 수 있으므로 바이너리는 보관하지 않습니다. 최근 바이너리들은 별도의 서버에 얼마동안 보관해도 됩니다.

    한인철님의 상황을 정확하게 모르고 Detail한 답을 드리는 것으 자칫 위험할 수 있지만 그렇다고 무조건 그때그때 다르다라고 말하는 것은 또 아닌 것 같아서 일반적인 경우와 원칙 위주로 말씀드렸습니다. 좀더 상황에 맞는 답을 듣고 싶으시면 Email을 주시거나 전화(019-313-3929)로 연락을 주셔도 됩니다. 감사합니다.

    답글삭제
  21. 안녕하세요, 전규현님.
    Commit 관련해서 질문이 있습니다. Commit 할때 반드시 이슈 ID를 적으라고 했는데, 만약 어떤 어플리케이션을 새로 만드는 과정이라면 어떤식으로 Commit 메시지를 적어야할까요? 버그가 생기면야 이슈ID를 적는데, 새로 만드는 과정이면? 어느날 갑자기 1.0이 됐을때 한 번 커밋하는것은 그것대로 문제가 아닐까요? 궁금해서 물어봅니다. 답변 부탁드리겠습니다~ : )

    답글삭제
  22. 안녕하세요. wisedog님
    신제품을 개발하는 중이라면 이슈관리시스템에 개발할 내용을 적지는 않습니다. 따라서 이슈가 없죠. 그럴 때는 이슈ID를 적지 않아도 됩니다. 어떤 회사는 시제품 개발때도 대표 이슈를 등록해서 그 ID를 적는 경우도 있습니다. 어떻게 하셔도 상관은 없습니다.

    답글삭제
  23. 한가지 궁금점이 있습니다.
    커밋 전에 Peer Review를 한다고 하셨는데,
    경험 상 커밋 전에 동료를 따로 불러서 리뷰하기는 어려워 보이는데..
    혹시 사용하시는 방법 등이 있으신가요?

    제 경우 커밋 후에 시스템이 이를 알리면 시니어 멤버가 리뷰 하는 형태였거든요.
    물론 이것이 올바른 방법은 아닌 것은 알지만
    커밋 전에 시니어 멤버를 따로 부르는 것도 어려워 보여서요.

    좋은 방법이 있을 지 문의 드려봅니다 ^^

    답글삭제
  24. 안녕하세요. Winetalks님

    커밋후에 리뷰를 하는 것은 완전하지 않은 소스코드를 등록하는 것이므로 원칙에서는 어긋납니다.
    커밋 전 간단히 리뷰하는 방법은 Peer desk check이라고 합니다. 그리고 꼭 시니어 멤버가 리뷰를 할 필요는 없습니다.
    이를 도와주는 시스템이 있어서 좀더 편리하게 리뷰할 수는 있지만 꼭 시스템이 필요한 것은 아닙니다.
    SCM에 따라서 임시로 Commit을 해서 리뷰후 Commit을 확정하는 시스템도 있습니다.
    좀더 확대를 하면 분산SCM에서는 자신의 Repository에는 자유롭게 Commit을 하고 중앙 Repository와 Sync할 때 리뷰하는 방법도 있습니다.
    결론은 시스템이 문제가 아니고 꼭 시니어 멤버가 아니더라도 리뷰를 적절하게 하는 것이 중요합니다.

    답글삭제