F-Lab
🚀
깊이 있는 개발자 커뮤니티, 데브클럽에 함께 하세요

Semantic Versioning : 소프트웨어 버전 관리의 정석

writer_thumbnail

F-Lab : 상위 1% 개발자들의 멘토링

오픈 소스 프로젝트에서 새 버전을 발표할 때, 마침표로 구분된 숫자들로 버전을 표기하는것을 한번쯤 보았을것입니다. 각각의 숫자들은 어떤 의미를 가지고 있는 것일까요? 

 

그 숫자들은 Semantic Versioning, 또는 SemVer 라고 불리는 규칙들에 따라서 관리됩니다. Semantic Versioning 은 코드의 버전을 명시적으로 표시하고, 이를 통해 변경 내용의 의미를 명확하게 전달하는 규칙입니다. Semantic Versioning에서 버전은 주 버전과 부 버전, 패치 버전의 세 영역으로 구성되며 각각은 다음과 같은 의미를 갖습니다.

 

‘0.1.2’

  • 주 버전(Major)
    • 가장 앞의 숫자('0')입니다. 
    • 하위 호환되지 않는 API 변경이 있을 때 증가합니다.
  • 부 버전(Minor)
    • 중간에 위치한 숫자('1')입니다. 
    • 하위 호환되는 기능 추가가 있을 때 증가합니다.
  • 패치 버전(Patch)
    • 가장 마지막의 숫자('2')입니다. 
    • 하위 호환되는 버그 수정이 있을 때 증가합니다.

 

이 규칙을 따르면서 버전을 관리하면 소프트웨어 사용자들이 쉽게 업데이트의 영향을 파악할 수 있습니다. 

 

Semantic Versioning 이 만들어진 이유

하지만 이러한 규칙들이 왜 만들어지고 사용되는것일까요? 코드를 작성하고 관리하는 과정에서 버전 관리는 사용자 경험 관점에서 매우 중요합니다. 소프트웨어의 규모와 복잡도가 이전에 비해 증가하면서 생긴 중요한 변화 중 하나는 다른 소프트웨어나 패키지에 대한 의존성도 큰 폭으로 증가했다는 것입니다. 새로운 기능이나 보안 취약점을 없애기 위해서는 의존성이 있는 소프트웨어와 패키지를 업데이트해야 합니다.

 

하지만, 모든 업데이트는 이전 버전과의 호환성, 패키지 간의 호환성 등을 깰 위험성을 내포합니다. 의존성 그래프가 복잡해 질수록 업데이트 전에 이런 위험을 평가하는 일이 어려워집니다. 결국 코드베이스가 "의존성 지옥🔥"에 빠지게 되고 패키지 업데이트의 비용이 너무 올라간 나머지 업데이트를 포기하고 이전 버전을 내부에서 유지보수하는 것이 더 합리적인 상태에 놓이게 되기도 합니다.

 

이러한 문제는 팀과 제품 규모를 막론하고 흔하게 마주치게 되는 문제입니다. 가령 ‘아마존(Amazon.com)’의 결제 시스템을 책임지는 팀 중에는 아주 오래된 c 표준으로 작성된 소프트웨어에 대한 의존성을 적절한 시점에 제거하지 못하여, 2020년 언저리까지 해당 소프트웨어를 컴파일하기 위한 툴체인의 포크 버전을 유지보수했습니다. 그러한 의사결정에는 여러가지 이유가 있었겠지만, 여기에서는 크고 뛰어난 조직에서도 이러한 문제를 해결하는데 어려움을 겪는다는 예시로 받아들이면 좋겠습니다.

 

"의존성 지옥" 문제가 너무 흔하게 일어나기 때문에 사람들은 소속된 조직과 회사를 넘어서서 개발자 생태계 내에서 해결책을 찾기로 했습니다. 그 해결책이 Semantic Versioning🥕 입니다. Semantic Versioning 은 위에서 소개했듯이 버전간의 차이가 하위 호환성을 깨트리는지, 변경사항이 단순한 버그 수정인지 새로운 기능을 포함하는지를 설명해 줍니다. Semantic Versioning을 따르는 소프트웨어나 패키지를 이용할때는 새로운 버전으로의 업데이트가 어떤 영향을 줄수 있을지 코드를 확인하지 않고도 예상 가능합니다. 이는 매 업데이트의 비용이 줄어드는 효과를 낳고 더 자주 소프트웨어나 패키지 업데이트를 할 수 있는 환경을 만드는데 중요한 역할을 합니다.

 

Semantic Versioning 을 적용하는 방법

Semantic Versioning 을 적용하는 것은 상대적으로 간단합니다. 코드를 변경할 때마다 버전 번호를 적절히 업데이트하면 됩니다. 예를 들어, 새로운 기능을 추가하거나 주요 변경을 수행하는 경우에는 주 버전을 증가시키고, 하위 호환성이 유지되는 개선이나 기능 추가가 있을 때에는 부 버전을 증가 시킵니다. 패치 버전은 하위 호환성을 유지하면서 버그 수정을 한 경우에만 증가 시킵니다. 주 버전이 증가된 경우에는 부 버전과 패치 버전을, 부 버전이 증가된 경우에는 패치 버전만 0으로 되돌립니다. 구체적인 규칙들이 더 궁금한 경우에는 공식 웹사이트를 참고할 수 있습니다.

 

‘0.0.0’ → ‘1.0.0’

  • 주 버전 증가
    • 새로운 기능을 추가하거나 주요 변경을 수행하는 경우

‘0.0.0’ → ‘0.1.0’

  • 부 버전 증가
    • 하위 호환성이 유지되는 개선이나 기능 추가가 있을 때

‘0.0.0’ → ‘0.0.1’

  • 패치 버전 증가
    • 하위 호환성을 유지하면서 버그 수정을 한 경우

 


 

‘0.1.1’ → ‘1.0.0’

  • 주 버전이 증가하면
    • 부 버전과 패치 버전을 0으로 되돌린다.

‘1.0.1’ → ‘1.1.0’

  • 부 버전이 증가하면
    • 패치 버전을 0으로 되돌린다.

 

Semantic Versioning 을 자동으로 관리하는 방법 - ‘Commitizen

위와 같이 Semantic Versioning 은 코드 변경 내용을 명확하게 전달하고 버전 간의 호환성을 보장하는 데에 효과적인 도구입니다. 그러나 버전 번호를 수동으로 관리하는 것은 번거로울 수 있습니다. 

 

또 많은 사람이 협업하는 프로젝트의 경우 모두가 Semantic Versioning 의 규칙을 숙지하고 있지 않으면 실수로 인해서 잘못된 의미를 전달할수도 있습니다. Commitizen 과 같은 도구를 사용하여서 Semantic Versioning 을 자동화하는 방식으로 문제를 해결할 수 있습니다. Commitizen 은 일련의 규칙을 따르는 커밋 메시지 작성을 돕고 커밋 메시지를 이용해서 Semantic Versioning 을 수행하도록 도와주는 도구입니다. 이를 통해 개발자는 코드 변경을 수행할 때 Semantic Versioning 규칙에 따라 버전을 자동으로 관리할 수 있습니다.

 

Commitzen 은 pip 와 같은 패키지 매니저를 이용해서 쉽게 설치할 수 있습니다. 공식 웹사이트를 통해서 더 상세한 설치 방법을 확인할 수 있습니다. Commitzen 은 init, commit, bump, check, changelog 의 다섯가지 커맨드를 제공합니다. 각각의 사용처는 아래와 같습니다.

 

init

  • 현재 디렉토리에서 commitzen 프로젝트를 초기화하기 위해서 사용됩니다. 대화형 인터페이스에서 선택한 설정 파일이 생성됩니다.

 

commit

  • 정해진 규칙에 따라서 커밋 메시지를 작성하는 대화형 인터페이스를 제공합니다.

 

bump

  • 커밋 메시지들을 확인해서 새로운 Semantic Version 을 git tag 의 형태로 생성합니다.

 

check

  • 커밋 메시지들이 정해진 규칙을 따르는지 검사합니다.

 

changelog

  • 커밋 메시지들을 확인해서 변경사항을 요약해주는 changelog 를 생성합니다.

 

Commitzen 과 같은 도구를 이용하면 팀 내부에서 일관된 방식으로 의미 있는 커밋 메시지를 작성함으로써 변경 사항을 쉽게 파악하고 협업 난이도를 낮출 수 있습니다. 또 버전 관리 규칙을 개인의 주관이 아닌 명시적인 규칙을 따르는 도구를 이용해서 관리함으로써 실수를 줄이고 팀 차원에서 프로젝트가 Semantic Versioning 의 규칙들을 준수한다는 것을 보장할 수 있습니다. Commitzen 에서 제공하는 커맨드들을 개발 과정에서 사용하도록 팀 내부 규칙을 만들수도 있고 pre-commit 이나 git hook 등을 이용해서 규칙들을 자동화해서 개개인이 실수할 여지를 더 줄일수도 있습니다.

 

마무리

이 글에서는 Semantic Versioning 이 왜 제안되었고 어떠한 문제를 해결할 수 있는지, 그리고 Commitzen 과 같은 도구를 이용해서 Semantic Versioning 의 규칙을 잘 따를 수 있는지 알아봤습니다. 필자는 이것들이 간단하고 도입하기 쉬운 도구들이지만 동시에 적용했을때 들인 노력 이상의 값어치를 하는 도구들이라고 생각합니다. 프로젝트가 성장하는 과정에서 반드시 겪게 되는 버전 관리 문제를 이 블로그 글을 참고해서 해결하실 수 있기를 바라겠습니다.

 

ⓒ F-Lab & Company

이 컨텐츠는 F-Lab의 고유 자산으로 상업적인 목적의 복사 및 배포를 금합니다.

조회수

멘토링 코스 선택하기

  • 코스 이미지
    Java Backend

    아키텍처 설계와 대용량 트래픽 처리 능력을 깊이 있게 기르는 백앤드 개발자 성장 과정

  • 코스 이미지
    Node.js Backend

    아키텍처 설계와 대용량 트래픽 처리 능력을 깊이 있게 기르는 백앤드 개발자 성장 과정

  • 코스 이미지
    Python Backend

    대규모 서비스를 지탱할 수 있는 대체 불가능한 백엔드, 데이터 엔지니어, ML엔지니어의 길을 탐구하는 성장 과정

  • 코스 이미지
    Frontend

    기술과 브라우저를 Deep-Dive 하며 성능과 아키텍처, UX에 능한 개발자로 성장하는 과정

  • 코스 이미지
    iOS

    언어와 프레임워크, 모바일 환경에 대한 탄탄한 이해도를 갖추는 iOS 개발자 성장 과정

  • 코스 이미지
    Android

    아키텍처 설계 능력과 성능 튜닝 능력을 향상시키는 안드로이드 Deep-Dive 과정

  • 코스 이미지
    Flutter

    네이티브와 의존성 관리까지 깊이 있는 크로스 플랫폼 개발자로 성장하는 과정

  • 코스 이미지
    React Native

    네이티브와 의존성 관리까지 깊이 있는 크로스 플랫폼 개발자로 성장하는 과정

  • 코스 이미지
    Devops

    대규모 서비스를 지탱할 수 있는 데브옵스 엔지니어로 성장하는 과정

  • 코스 이미지
    ML Engineering

    머신러닝과 엔지니어링 자체에 대한 탄탄한 이해도를 갖추는 머신러닝 엔지니어 성장 과정

  • 코스 이미지
    Data Engineering

    확장성 있는 데이터 처리 및 수급이 가능하도록 시스템을 설계 하고 운영할 수 있는 능력을 갖추는 데이터 엔지니어 성장 과정

  • 코스 이미지
    Game Server

    대규모 라이브 게임을 운영할 수 있는 처리 능력과 아키텍처 설계 능력을 갖추는 게임 서버 개발자 성장 과정

  • 코스 이미지
    Game Client

    대규모 라이브 게임 그래픽 처리 성능과 게임 자체 성능을 높힐 수 있는 능력을 갖추는 게임 클라이언트 개발자 성장 과정

F-Lab
소개채용멘토 지원
facebook
linkedIn
youtube
instagram
logo
(주)에프랩앤컴퍼니 | 사업자등록번호 : 534-85-01979 | 대표자명 : 박중수 | 전화번호 : 1600-8776 | 제휴 문의 : info@f-lab.kr | 주소 : 서울특별시 강남구 테헤란로63길 12, 438호 | copyright © F-Lab & Company 2024