티스토리 뷰

본 글은 https://semver.org/ 을 기존 번역 https://semver.org/lang/ko/을 참고하여 보다 이해하기 쉽도록 번역한 글 입니다.
Backus–Naur Form Grammar for Valid SemVer Versions와 FAQ는 생략했습니다.


요약

버전을 MAJOR.MINOR.PATCH 숫자로 표기하고:

  1. 기존 버전과 호환되지 않게 API가 바뀌면 “MAJOR(주(主)) 버전”을 올리고,
  2. 기존 버전과 호환되면서 새로운 기능을 추가할 때는 “MINOR(부(部)) 버전”을 올리고,
  3. 기존 버전과 호환되면서 버그를 수정한 것이라면 “PATCH(수(修)) 버전”을 올린다.

MAJOR.MINOR.PATCH 형식에 정식배포 전 버전이나 빌드 메타 데이터를 위한 라벨을 덧붙이는 방법도 있다.


머리말

소프트웨어 관리의 세계에는 “의존성 지옥(dependency hell)”이라 불리는 성가신 문제가 있다. 시스템 규모가 커질수록, 그리고 더 많은 패키지를 가져다 쓸수록, 언젠가, 이 절망의 늪에 빠진 자신을 발견하기 쉽다.

의존성이 높은 시스템에서는, 새 패키지 버전을 배포하는 일이 금방 끔찍해지곤 한다. 의존성 명세(specifications)를 너무 엄격하게 관리하면, 버전에 갇히게(version lock) 될 위험이 있다(모든 종속 패키지의 새 버전을 출시하지 않고 패키지를 업그레이드 할 수 없음). 의존성을 너무 느슨하게 관리하면, 버전이 엉켜서(version promiscuity) 괴롭게 될 것이다(지나치게 나중 버전까지 호환될 거라 가정한 경우). 버전에 갇히거나(version lock) 엉켜서(version promiscuity) 쉽고 안전하게 프로젝트를 계속 진행할 수 없다면 의존성 지옥에 빠진 것이다.

이 문제의 해결책으로, 버전 번호를 어떻게 정하고 올려야 하는지를 명시하는 규칙과 요구사항을 제안한다. 이 규칙들은 기존 오픈 소스/비공개 소스 소프트웨어에 널리 활용되는 규칙을 바탕으로 했으나, 반드시 따르고자 제약을 받지는 않았다. 이 시스템이 동작하려면, 먼저 공개(public) API를 선언해야 한다. 이는 문서와 소스 코드 자체로 드러낼 수 있다. 어떤 방식이든 API가 명확해야 한다. 한번 공개 API를 정의하고 나면, 버전 번호를 올리는 방식을 통해 API가 어떻게 바뀌는지 표현한다. 버전을 X.Y.Z (MAJOR.MINOR.PATCH) 형식으로 정한다. API에 영향이 없는 버그 수정은 Patch 버전을 올리고, API가 호환되면서 바꾸거나 추가하는 경우에는 Minor 버전을 올리고, API가 호환되지 않는 변경이라면 Major 버전을 올린다.

이 체계를 “유의적 버전 또는 시맨틱 버전 관리(Semantic Versioning)”라고 부르고자 한다. 이 체계를 따르면, 버전 번호와 그 번호를 바꾸는 방법을 통해 특정 버전에서 다음 버전으로 넘어가면서 코드가 어떻게 바뀌는지를 드러낸다.


Semantic Versioning Specification (SemVer)

이하 반드시(MUST), 할 수 없다(MUST NOT), 해야한다(SHOULD), 할 수 있다(MAY) 등의 표현은 RFC 2119에 기술된대로 해석한다.

  1. 시맨틱 버전 관리를 쓰는 소프트웨어는 반드시 공개 API를 선언한다. 이 API는 코드 자체로 선언하거나 문서로 엄격히 명시해야 한다. 어떤 방식으로든, 정확하고 이해하기 쉬워야 한다.

  2. 보통 버전 번호는 반드시 X.Y.Z의 형태로 하고, X, Y, Z는 각각 음이 아닌 정수이고, 절대로 0이 앞에 붙어서는 안 된다. X는 MAJOR 버전 번호이고, Y는 MINOR 버전 번호이며, Z는 PATCH 버전 번호이다. 각각은 반드시 증가하는 수여야 한다. 예: 1.9.0 -> 1.10.0 -> 1.11.0.

  3. 특정 버전으로 패키지를 배포하고 나면, 그 버전의 내용은 절대 변경하지 말아야 한다. 변경분이 있다면 반드시 새로운 버전으로 배포하도록 한다.

  4. MAJOR버전 0(0.y.z)은 초기 개발을 위해서 쓴다. 아무 때나 마음대로 바꿀 수 있다. 이 공개 API는 안정판으로 보지 않는 게 좋다.

  5. 1.0.0 버전은 공개 API를 정의한다. 이후의 버전 번호는 이때 배포한 공개 API에서 어떻게 바뀌는지에 따라 결정된다.

  6. PATCH버전 Z (x.y.Z | x > 0)는 반드시 이전 버전 API와 호환되는 버그 수정의 경우에만 올린다. 버그 수정은 잘못된 동작을 수정하는 내부 변경으로 정의한다.

  7. 공개 API에 기존과 호환되는 새로운 기능을 도입할 때는 반드시 MINOR 버전 Y(x.Y.z | x > 0)를 올린다. 공개 API의 일부 기능을 앞으로 사용되지 않을 것(deprecated)으로 표시한 경우에도 반드시 올리도록 한다. 내부 비공개(private) 코드에 새로운 기능이 대폭 추가되거나 개선사항이 있을 때도 올릴 수 있다. MINOR 버전을 올릴 때 PATCH 버전의 변화를 포함할 수도 있다. MINOR 버전이 올라가면 PATCH 버전은 반드시 0에서 다시 시작한다.

  8. 공개 API에 기존과 호환되지 않는 변화가 있을 때는 반드시 MAJOR 버전 X(X.y.z | X > 0)를 올린다. MINOR 버전이나 PATCH 버전급 변화를 포함할 수 있다. MAJOR 버전 번호를 올릴 때는 반드시 MINOR 버전과 PATCH 버전을 0으로 초기화 한다.

  9. PATCH 버전 바로 뒤에 붙임표(-)를 붙이고 마침표(.)로 구분된 식별자를 더해서 정식 배포를 앞둔 (pre-release) 버전을 표기할 수있다. 식별자는 반드시 아스키(ASCII) 문자, 숫자, 붙임표로만 구성한다[0-9A-Za-z-]. 식별자는 비워 둘 수 없다. 숫자 식별자의 경우 절대 0으로 시작하지 않아야 한다. 정식배포 전 버전(Pre-release versions)은 관련한 보통 버전보다 우선순위가 낮다. 정식배포 전 버전은 아직 불안정하며 연관된 일반 버전에 대해 호환성 요구사항이 충족되지 않을 수도 있다. 예: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92.

  10. 빌드 메타 데이터는 PATCH 버전이나 정식배포 전 버전 바로 뒤에 더하기 부호와 일련의 점으로 구분 된 식별자를 추가하여 표시 할 수 있다. 식별자는 반드시 아스키 문자와 숫자와 붙임표(하이픈)로만 구성한다 [0-9A-Za-z-]. 식별자는 비워 둘 수 없습니다. 버전 우선 순위를 결정할 때는 빌드 메타 데이터를 반드시 무시해야 합니다. 그러므로, 빌드 메타 데이터만 다른 두 버전의 우선순위는 같다. 예: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85.

  11. 우선순위는 버전의 순서를 정렬할 때 서로를 어떻게 비교할지를 나타낸다. 우선순위는 반드시 MAJOR, MINOR, PATCH 버전, 그리고 정식배포 전 버전의 식별자를 나누어 계산하도록 한다 (빌드 메타 데이터는 우선순위에 영향을 주지 않는다). 우선순위는 다음의 순서로 차례로 비교하면서, 차이가 나는 부분이 나타나면 결정된다: MAJOR, MINOR, PATCH는 숫자로 비교한다. 예: 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1. MAJOR, MINOR, PATCH 버전이 같을 경우, 정식배포 전 버전이 표기된 경우의 우선순위가 더 낮다. 예: 1.0.0-alpha < 1.0.0. MAJOR, MINOR, PATCH 버전이 같은 두 배포 전 버전 간의 우선순위는 반드시 마침표로 구분된 식별자를 각각 차례로 비교하면서 차이점을 찾는다: 숫자로만 구성된 식별자는 수의 크기로 비교하고 알파벳이나 붙임표가 포함된 경우에는 아스키 문자열을 사전 순으로 비교하도록 한다. 숫자로만 구성된 식별자는 어떤 경우에도 문자와 붙임표가 있는 식별자보다 낮은 우선순위로 여긴다. 앞선 식별자가 모두 같은 배포 전 버전의 경우에는 필드 수가 많은 쪽이 더 높은 우선순위를 가진다. 예: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0.


시맨틱 버전 관리(Semantic Versioning)를 해야 하는 이유

시맨틱 버전 관리는 혁신적인 아이디어가 아니다. 사실, 이미 이와 비슷한 방식을 정해서 쓰고 있었을 수 있다. 문제는 이와 “비슷한” 방식으로는 충분치 않다는 점이다. 어떠한 형태로 정식 명세(formal specification)를 정해서 따르지 않는다면, 버전 번호는 의존성 관리에서 무의미하다. 이상의 아이디어에 이름을 정하고 명시적인 정의를 내림으로써, 소프트웨어 사용자에게 제작자의 의도를 전달하기 쉬워진다. 의도가 명확해야만, (너무 지나치지는 않은) 융통성 있는 의존성 명세(dependency specifications)를 만들 수 있다.

시맨틱 버전 관리로 어떻게 의존성 지옥을 벗어날 수 있는지 간단한 예를 들어보자. “Firetruck”이라는 라이브러리가 있다고 하자. 이 라이브러리는 시맨틱 버전이 붙은 “Ladder”라는 패키지(a Semantically Versioned package named “Ladder)에 의존한다. Firetruck을 만들었을 때, Ladder는 버전 3.1.0이었다. Firetruck이 3.1.0에 처음으로 추가된 기능을 사용했기 때문에, Ladder의 의존성을 3.1.0 이상, 4.0.0 미만으로 지정할 수 있다. 이제, Ladder의 3.1.1 버전과 3.2.0 버전이 공개된다면, 패키지 관리 시스템에 그 버전을 넣을 수 있고 기존 소프트웨어와 호환될 것이라고 알 수 있다.

물론, 책임감 있는 개발자로서 패키지가 업그레이드된 부분이 홍보된 대로 잘 동작하는지 검증하고자 할 것이다. 실상은 좋지 않다, 그렇기 때문에 조심해서 관리하는 것 외에는 달리 도리가 없다. 시맨틱 버전을 사용함으로써 의존하는 패키지들의 새 버전들과 씨름하지 않고, 시간 낭비와 소란 없이 패키지를 공개하고 업그레이드할 수 있다.

만약 이상의 내용이 그럴싸하다면, 시맨틱 버전을 쓰기 시작하기 위해서 할 일은, 그렇게 하고자 마음먹고 규칙을 따르기만 하면 된다. 여러분의 README 파일에 이 웹사이트의 링크를 추가해서 다른 사람들도 유용하게 쓸 수 있게 하자.


About

The Semantic Versioning specification is authored by Tom Preston-Werner, inventor of Gravatar and cofounder of GitHub.

If you'd like to leave feedback, please open an issue on GitHub.

License

Creative Commons - CC BY 3.0

'VCS' 카테고리의 다른 글

마크다운(Markdown) 사용법 정리  (0) 2019.06.09
댓글
반응형
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함