안녕하세요, 슬로우플랫폼에서 CTO를 맡고 있는 Tony라고 합니다.
슬로우플랫폼은 시니어를 위한 스마트에이징 스타트업입니다.
이제 겨우 2달밖에 되지 않는 초기단계지만 비전을 가지고 목표를 향해 열심히 개발을 진행하고 있습니다.
준비기간이 충분하진 않았지만 얼마전 첫번째 테크데이 세미나를 진행하였고 해당 세미나 내용을 정리하여 첫번째 기술블로그 포스팅을 올립니다.
우선 대표적인 3가지 Git Workflow에 대해 간단히 알아보고 시작합니다.
3가지 Workflow의 내용은 이미 많은 분들이 포스팅한 내용들이 있어서 많은 부분 참조를 하였고 원본링크는 References에 기록되어 있습니다.
하나의 소스코드로 여러명의 개발자들이 협업을 하게 되면서 소스코드의 버전 관리 시스템의 중요성이 매우 높아졌다. 과거에는 SVN, CVS 같은 소프트웨어들도 많이 사용되었지만 최근에는 거의 git으로 통일되어 가는 듯 하다. (그럼에도 아직까지 파일 서버에서 소스코드를 업로드하는 원시적인 방법을 사용하는 프로젝트도 많다.)
SVN과 CVS에 비해 git이 갖는 큰 장점은 효율적인 브랜치(Branch) 관리가 가능하다는 점이다. 소스코드의 일부분을 수정하기 위해 브랜치를 생성하고 작업한 다음 원래 소스코드에 손쉽게 수정사항을 병합(Merge)할 수 있다.
소스코드를 관리하는데 브랜치 기능을 적극적으로 사용할 수 있는게 git의 장점이라고 언급했다. 브랜치 기능도 효율적으로 사용하지 못하면 혼란이 더 가중될 가능성이 있다. Vincent Driessen은 효과적으로 git 브랜치 전략을 사용하는 것에 대한 제안을 했다. (링크 : https://nvie.com/posts/a-successful-git-branching-model/)
자세한 내용은 원문을 읽어보기 바란다. 약간 요약을 하자면
Author : Vincent Driessen
이런 형태로 소스코드를 관리해 나가자는 내용이다.
Vincent Driessen의 브랜칭 모델에는 5개의 브랜치가 사용된다.
각각에 대해서 설명을 해보자면
정식 배포되는 안정적인 버전의 소스코드가 이곳에 관리된다. master 브랜치의 HEAD는 소프트웨어의 최신 배포판의 소스코드 버전이 들어있다. master 브랜치에는 지난 배포판 버전의 소스코드를 따라가기 위해 태그(tag)들이 추가되어 있다. 이 태그를 이용해 각 릴리즈 버전의 소스코드를 빠르게 확인할 수 있다.
master 브랜치에는 배포해도 될 만큼 안정성이 충분히 검증된 코드들만이 병합되어야 한다.
develop 브랜치에는 소스코드들이 끊임 없이 추가된다. 버그들을 수정하기 위한 코드와 새로운 기능을 추가하기 위한 코드, 성능을 개선하기 위한 코드들이 검증이 완료되고 PR 요청을 거치게 되면 이 곳으로 병합된다.
개발자는 feature 브랜치에서 소스코드 수정을 한 다음 develop 브랜치로 PR 요청을 하게 된다. 또 다른 리뷰어가 기능들을 검토한다음 최종적으로 develop 브랜치에 병합된다. 새로운 기능을 위한 feature 브랜치는 develop 브랜치의 HEAD에서 생성된다.
새로운 기능 개발이나 버그 수정을 위한 일련의 코드 수정이 이뤄지는 브랜치다. 이 브랜치에서 개발자 혼자 작업을 할 수도 있고, 특정 기능 개발을 위한 여러명의 개발자들이 공동으로 작업할 수도 있다.
feature 브랜치에서 작업된 내용은 최종적으로 PR을 거쳐 develop 브랜치에 병합(Merge)된다.
git으로 관리되는 소프트웨어는 정기적으로 성능 개선, 기능추가, 버그 수정을 반영하면서 릴리즈 된다. release 브랜치는 릴리즈를 하기 위한 목적으로 생성되는 브랜치다.
release 브랜치는 develop 브랜치를 기반으로 생성된다. 다음 릴리즈에 포함되어야 하는 기능셋과 버그픽스들이 확정된 다음 생성된다. 릴리즈 브랜치가 생성된 다음 QA 테스트가 릴리즈 브랜치를 기준으로 진행된다. 이 과정에서 발견된 버그 수정 사항들이 릴리즈 브랜치와 develop 브랜치에 적용되며, 그 밖에 메이저 기능들이 중간에 추가되지는 않는다.
테스트 이후 릴리즈 브랜치의 코드가 안정적이라고 판단되면, master 브랜치에 병합되고 릴리즈에 해당하는 태그가 생성된다. 릴리즈 브랜치가 생성된 이후 반영된 수정사항들은 develop 브랜치에도 반영된다.
여기까지 본 작업은 PR, QA 테스트 등의 작업들이 필요하다. 안정성을 높이기 위한 작업이지만 긴급한 대응에는 장애물이 될 수 있다. hotfix는 정기적인 릴리즈 이외에 긴급하게 수행되어야 할 버그 수정을 반영하기 위해 생성되는 브랜치다. 다음 릴리즈 프로세스를 기다릴 수 없을 정도로 긴급한 패치가 바로 반영되어야 하는 경우 이 브랜치를 사용한다.
hotfix 브랜치는 master 브랜치를 기반으로 생성된다. 생성된 hotfix 브랜치에 긴급한 패치들이 반영된다. 이후 hotfix 브랜치는 master 브랜치에 병합되고 태그 생성이 된다. 마찬가지로 수정 사항은 develop 브랜치로도 병합되어 긴급 수정 사항이 이후 릴리즈에도 반영되도록 한다.
GitHub-Flow란 Git-Flow가 복잡하기에 이를 좀 더 간소화시킨 방식으로 Scott chacon이 Github에서 좀 더 편리하게 사용하기 위해 만든 브랜칭 전략이다.
자동화 개념이 포함되어 있으며 Master(Main) Brnach에 대한 role만 정확하다면 나머지 Branch들에는 관여를 하지 않는다. 그리고 Pull Request 기능의 사용을 권장한다.
사용법 및 특징을 정리해보면
Master Branch의 어느것이든 배포가 가능하다.
새로운 일을 시작하기 위해 Branch를 Master에서 딴다면 이름은 어떤 작업인지 명확하게 명시한다.
Local Branch에 수시로 커밋하고 이 내용을 원격 Branch에 수시로 Push한다.
피드백이나 도움이 필요할 때 혹은 자신의 Branch가 merge할 준비가 되었다면, PR을 생성하여 공유한다.
PR 리뷰 후에는 다른 사람의 동의를 얻고 Master에 Merge한다.
Master Branch로 Merge나 Push가 이루어지면 즉시 배포해야한다.
Gitlab Flow 영문 가이드를 ChatGPT를 이용하여 한글로 번역하여 문체가 조금 다르게 느껴질 수 있다..
Git은 다양한 브랜칭 전략과 워크플로우를 허용합니다. 이 때문에 많은 조직에서 너무 복잡하거나, 명확하게 정의되지 않았거나, 이슈 추적 시스템과 통합되지 않은 워크플로우를 사용하게 됩니다. 따라서 저희는 명확하게 정의된 모범 사례로 GitLab 플로우를 제안합니다. 이는 기능 중심 개발과 기능 브랜치를 이슈 트래킹과 결합한 것입니다.
다른 버전 관리 시스템에서 Git을 사용하는 조직은 생산적인 워크플로우를 개발하는 데 어려움을 겪는 경우가 많습니다. 이 문서에서는 Git 워크플로우와 이슈 트래킹 시스템을 통합하는 GitLab 플로우에 대해 설명합니다. 이 솔루션은 투명하고 효과적인 Git 작업 방식을 제공합니다.
Git으로 전환할 때 동료와 커밋을 공유하려면 세 단계가 필요하다는 사실에 익숙해져야 합니다. 대부분의 버전 관리 시스템에는 작업 복사본에서 공유 서버로 커밋하는 한 단계만 있습니다. Git에서는 작업 복사본의 파일을 스테이징 영역에 추가합니다. 그런 다음 로컬 리포지토리에 커밋합니다. 세 번째 단계는 공유 원격 리포지토리로 푸시하는 것입니다. 이 세 단계에 익숙해졌다면 다음 과제는 브랜칭 모델입니다.
Git을 처음 사용하는 많은 조직은 작업 방식에 대한 규칙이 없기 때문에 리포지토리가 금방 지저분해질 수 있습니다. 가장 큰 문제는 변경 사항의 일부를 포함하는 장기 실행 브랜치가 많이 생긴다는 것입니다. 사람들은 어느 브랜치에 최신 코드가 있는지, 어느 브랜치를 프로덕션에 배포할지 파악하는 데 어려움을 겪습니다. 이 문제에 대한 대응책으로 Git Flow 및 GitHub Flow과 같은 표준화된 패턴을 채택하는 경우가 많습니다. 아직 개선의 여지가 있다고 생각합니다. 이 문서에서는 GitLab Flow이라고 부르는 일련의 관행에 대해 설명합니다.
GitLab에서 어떻게 작동하는지에 대한 동영상 소개는 GitLab Flow을 참조하세요.
GitHub 플로우는 기능 브랜치를 병합할 때마다 프로덕션에 배포할 수 있다고 가정합니다. SaaS 애플리케이션과 같은 일부 경우에는 이것이 가능하지만, 다음과 같이 이것이 불가능한 경우도 있습니다:
이러한 경우 배포된 코드를 반영하는 프로덕션 브랜치를 만들 수 있습니다. 'main'을 프로덕션 브랜치에 병합하여 새 버전을 배포할 수 있습니다. 프로덕션에 어떤 코드가 있는지 확인해야 하는 경우 프로덕션 브랜치를 확인하면 됩니다.
대략적인 배포 시간은 버전 관리 시스템에서 병합 커밋으로 볼 수 있습니다. 프로덕션 브랜치를 자동으로 배포하는 경우 이 시간은 매우 정확합니다. 더 정확한 시간이 필요한 경우 배포 스크립트에서 각 배포에 태그를 생성하도록 할 수 있습니다. 이 Flow는 Git Flow에서 발생하는 릴리스, 태그 지정 및 병합의 오버헤드를 방지합니다.
main 브랜치에 자동으로 업데이트되는 환경을 만드는 것이 좋습니다. 단, 이 경우 이 환경의 이름은 브랜치 이름과 다를 수 있습니다. 스테이징 환경, 사전 프로덕션 환경, 프로덕션 환경이 있다고 가정해 보겠습니다.
이 경우 main 브랜치를 스테이징에 배포합니다. pre-production에 배포하려면 main 브랜치에서 pre-production 브랜치로 병합 요청을 생성합니다. pre-production 브랜치를 production 브랜치에 병합하여 라이브로 전환합니다. 커밋이 다운스트림으로만 흐르는 이 워크플로에서는 모든 환경에서 모든 것을 테스트할 수 있습니다. 핫픽스가 포함된 커밋을 선택해야 하는 경우, 기능 브랜치에서 개발하고 병합 요청을 통해 '메인'으로 병합하는 것이 일반적입니다. 이 경우 아직 피처 브랜치를 삭제하지 마세요. 메인 브랜치가 자동 테스트를 통과하면 다른 브랜치에 기능 브랜치를 병합합니다. 수동 테스트가 더 필요하여 이것이 불가능하다면 피처 브랜치에서 다운스트림 브랜치로 병합 요청을 보낼 수 있습니다.
외부에 소프트웨어를 릴리스해야 하는 경우에만 release 브랜치로 작업하면 됩니다. 이 경우 각 브랜치에는 2-3-stable
또는 2-4-stable
과 같은 마이너 버전이 포함됩니다. 메인 브랜치를 시작점으로 하여 안정 브랜치를 만들고 가능한 한 늦게 브랜치를 생성하세요.
이렇게 하면 여러 브랜치에 버그 수정을 적용해야 하는 기간을 최소화할 수 있습니다. 릴리스 브랜치를 발표한 후에는 심각한 버그 수정 사항만 브랜치에 추가하세요. 가능하면 먼저 이러한 버그 수정을 main에 병합한 다음 릴리스 브랜치에 체리피킹하세요. release 브랜치에 병합하는 것부터 시작하면 main에 체리픽하는 것을 잊어버릴 수 있고, 이후 릴리스에서 동일한 버그가 발생할 수 있습니다. main으로 병합한 다음 release에 체리피킹하는 것을 "업스트림 우선" 정책이라고 하며, Google 및 Red Hat에서도 실행하고 있습니다. release 브랜치에 버그 수정을 포함할 때마다 새 태그를 설정하여 패치 버전을 늘리세요(시맨틱 버전 관리를 준수하기 위해). 일부 프로젝트에는 최신 release 브랜치와 동일한 커밋을 가리키는 stable 브랜치도 있습니다. 이 Flow에서는 production 브랜치(또는 Git Flow의 release 브랜치)를 갖는 것이 일반적이지 않습니다.
앞에서 3가지의 대표적인 Git Workflow를 살펴보았습니다. 각각의 workflow는 장단점을 가지고 있고 조직의 특성 혹은 사용하는 Git 환경에 따라 적절하게 사용할 필요가 있습니다.
따라서 팀슬로우의 조직 및 개발 환경에 맞게 적절히 변형하여 사용하고자 합니다.
팀슬로우에서는 Github 대신 Self-hosted Gitlab 환경을 사용하는 것을 고려하여 팀슬로우만의 Git Workflow를 정의해보았습니다.
우선 Github와 Gitlab의 Merge 방식의 차이를 알고 진행하면 좋을 것 같습니다.
** Github와 달리 Fork Repository가 존재하지 않기 때문에 조금 더 단순화된 구조를 가져갈 수 있습니다.
Vincent Driessen의 Git Flow 브랜칭 모델에는 5개의 브랜치가 사용되지만 팀슬로우에서는 release, hotfix를 제외한 3개의 브랜치만 사용할 계획입니다.
각각의 브랜치에 대한 설명은 Git flow를 참고하시고 releas, hotfix 브랜치를 사용하지 않는 이유는 CI/CD를 통해 Integration을 유지하기 때문에 굳이 필요하지 않다고 판단했기 때문입니다.
또한 최근 저자가 몇년간 실제로 운용을 했었던 방식으로 충분히 검증이 되었기 때문입니다.
팀슬로우 브랜칭 전략을 반영하여 다시 그림으로 표현하면 다음과 같습니다.
feature branch의 경우 공동작업이 필요 여부에 따라 push 시점이 다를 수 있습니다.
브랜칭 전략 못지 않게 중요한 것 중 하나가 Commit Convention입니다.
다음은 저자가 이전에 사용했었던 Udacity Git Commit Message Style 입니다.
메세지의 구조는 다음과 같습니다.
type: Subject
body
footer
type : 말 그대로 message type이고 type의 종류는 밑의 그림과 같습니다.
subject : 이 커밋이 하는 일을 설명. 50글자를 넘기지 않는게 원칙.
body : body는 그 스타일 가이드에 밑의 글처럼 적혀있고 72글자를 넘기지 않는게 원칙.Use the body to explain the what and why of a commit, not the how.
footer (optional) : issue traker id를 입력하는 것이 좋다고 합니다. 팀슬로우에서는 레드마인으로 이슈 관리를 할 예정이라 레드마인 일감 번호를 작성하도록 할 예정입니다.
스타일 가이드에서 주어진 예시는 다음과 같습니다
feat: Summarize changes in around 50 characters or less
More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of the commit and the rest of the text as the body. The
blank line separating the summary from the body is critical (unless
you omit the body entirely); various tools like `log`, `shortlog`
and `rebase` can get confused if you run the two together.
Explain the problem that this commit is solving. Focus on why you
are making this change as opposed to how (the code explains that).
Are there side effects or other unintuitive consequences of this
change? Here's the place to explain them.
Further paragraphs come after blank lines.
- Bullet points are okay, too
- Typically a hyphen or asterisk is used for the bullet, preceded
by a single space, with blank lines in between, but conventions
vary here
If you use an issue tracker, put references to them at the bottom,
like this:
Resolves: #123
See also: #456, #789
팀슬로우에서도 해당 가이드를 바탕으로 약간의 변형을 거쳐 사용할 예정입이다.
Git Workflow 만큼이나 중요한 것 중 하나가 커밋 전략입니다.
커밋 전략은 여러 개발자들이 동시에 작업하는 대규모 프로젝트에서 더욱 중요합니다.
코드 베이스를 효과적으로 관리하기 위해서는 commit을 일관되게 작성하는 것이 필수적입니다.
또한 각 commit은 한 가지 목적을 가져야 하며, 작은 변경 사항에 대한 commit을 지향해야 합니다.
이를 통해 코드 변경 이력을 명확하게 추적할 수 있고, 문제가 발생했을 때 디버깅이나 롤백이 쉬워집니다.
이러한 원칙은 코드 변경의 투명성을 확보하고, 협업하는 동료들과의 의사소통을 강화 할 수 있습니다.
여러가지 수정사항을 한가지 커밋에 다 넣어버리거나 수정사항과 관계 없이 특정시간 예를 들어 '점심시간' 혹은 '퇴근시간'등 특정 시점에 커밋을 만드는 것은 대표적인 나쁜 예로 볼 수 있습니다.
팀슬로우의 Git Workflow를 정리하다보니 CI/CD에 대한 이해가 필요하여 간단히 CI/CD에 대해서도 내용을 추가합니다.
CI(Continuous Integration)란 지속적인 통합이라는 의미한다.
지속적인 통합이란 코드 변경 사항이 리모트 Repository에 통합되기 전에 빌드 및 테스트가 완료되어 통합된다는 의미합니다.
CI의 핵심 목표는 SW의 오류를 신속히 찾아 해결하여 SW의 품질을 개선하고 새로운 업데이트의 검증 및 릴리즈 시간을 줄이는 것에 있습니다.
CD는 Continuous Delivery 혹은 Continuous Deployment라는 의미를 가집니다.
둘다 Production을 위한 프로세스를 의미 합니다만 최종 단계에서 차이를 가집니다.
Continuous Delivery는 Production 바로 이전단계까지만 수행 후 최종 Production은 수동으로 하는 개념이고 Continuous Deployment는 자동으로 Production 레벨까지 릴리즈가 되는 것을 의미합니다.
실무에서는 케이스에 따라 두가지를 적절히 사용하게 되지만 일반적으로 Continuous Delivery가 더 많이 사용됩니다.
잘 보고 갑니다