
개요
유의적 버전 또는 시맨틱 버전(영어: Semantic Versioning, SemVer)은 소프트웨어의 버전 번호에 일정한 의미를 부여하여, 배포판 사이의 변경 범위와 하위 호환성 여부를 표현하는 버전 표기 규칙이다.[1]
기본 형식은 MAJOR.MINOR.PATCH이며, 한국어 공식 문서에서는 이를 각각 주 버전, 부 버전, 수 버전으로 번역한다.[1] 예를 들어 2.4.1이라는 버전은 주 버전이 2, 부 버전이 4, 수 버전이 1이라는 뜻이다.
유의적 버전의 목적은 단순히 버전을 보기 좋게 표시하는 것이 아니라, 버전 번호만으로도 어느 정도의 API 변경이 있었는지 알 수 있게 하는 데 있다. 일반적으로 주 버전이 바뀌면 기존 코드와 호환되지 않는 변경이 있었을 가능성이 높고, 부 버전이 바뀌면 기존 코드와 호환되는 기능 추가가 있었음을 뜻하며, 수 버전이 바뀌면 기존 코드와 호환되는 버그 수정이 있었음을 뜻한다.
다만 유의적 버전이 의미를 가지려면 해당 소프트웨어가 먼저 명확한 공개 API를 선언해야 한다.[2] 여기서 공개 API는 외부 사용자가 의존할 수 있는 함수, 클래스, 명령어, 설정 형식, 데이터 형식, 프로토콜, 문서화된 동작 등을 포함할 수 있다. 공개 API가 명확하지 않으면 어떤 변경이 호환성을 깨뜨리는 변경인지 판단하기 어렵다.
구성

유의적 버전은 기본적으로 주 버전, 부 버전, 수 버전의 세 부분으로 구성된다. 여기에 필요에 따라 선행 배포 버전과 빌드 메타데이터를 덧붙일 수 있다.
| 구성 요소 | 형식상의 위치 | 의미 | 증가 또는 사용 조건 |
|---|---|---|---|
| 주 버전 | MAJOR | 기존 공개 API와 호환되지 않는 변경 | 하위 호환성을 깨뜨리는 변경이 공개 API에 포함될 때 증가 |
| 부 버전 | MINOR | 기존 공개 API와 호환되는 기능 추가 | 하위 호환성을 유지하면서 기능을 추가하거나 공개 API 일부를 폐기 예정으로 표시할 때 증가 |
| 수 버전 | PATCH | 기존 공개 API와 호환되는 버그 수정 | 잘못된 동작을 고치되 공개 API 호환성을 유지할 때 증가 |
| 선행 배포 버전 | -alpha, -beta.1, -rc.1 등 | 정식 배포 전 버전 | 아직 안정판이 아니거나 호환성 요구사항이 완전히 보장되지 않을 수 있음을 나타낼 때 사용 |
| 빌드 메타데이터 | +build.1, +exp.sha 등 | 빌드 식별 정보 | 빌드 번호, 커밋 해시, 빌드 날짜 등 버전 우선순위에 영향을 주지 않는 정보를 표시할 때 사용 |
형식
유의적 버전의 일반적인 형식은 다음과 같다.
MAJOR.MINOR.PATCH
MAJOR.MINOR.PATCH-PRERELEASE
MAJOR.MINOR.PATCH+BUILD
MAJOR.MINOR.PATCH-PRERELEASE+BUILD예시는 다음과 같다.
| 버전 | 설명 |
|---|---|
| 1.0.0 | 가장 기본적인 정식 버전 형식 |
| 1.2.3 | 주 버전 1, 부 버전 2, 수 버전 3 |
| 2.0.0 | 주 버전이 증가한 버전으로, 기존 공개 API와 호환되지 않는 변경이 포함되었을 수 있음 |
| 1.4.0 | 부 버전이 증가한 버전으로, 기존 공개 API와 호환되는 기능 추가가 있었음을 뜻함 |
| 1.4.1 | 수 버전이 증가한 버전으로, 기존 공개 API와 호환되는 버그 수정이 있었음을 뜻함 |
| 2.3.7-beta.3 | 2.3.7 정식 배포 이전의 세 번째 베타 계열 선행 배포 버전 |
| 1.0.0+20130313144700 | 빌드 메타데이터가 포함된 버전 |
| 1.0.0-alpha+001 | 선행 배포 버전과 빌드 메타데이터가 모두 포함된 버전 |
버전 증가 규칙
주 버전
주 버전(영어: major version)은 기존 공개 API와 호환되지 않는 변경이 발생했을 때 증가한다. 예를 들어 함수 이름이 바뀌거나, 기존 매개변수의 의미가 달라지거나, 기존에 동작하던 사용 방식이 더 이상 지원되지 않는다면 주 버전을 올리는 것이 원칙이다.
주 버전이 증가하면 부 버전과 수 버전은 0으로 초기화한다. 예를 들어 1.8.5에서 호환되지 않는 변경이 발생했다면 다음 버전은 일반적으로 2.0.0이 된다.
파이썬의 파이썬 2와 파이썬 3의 관계는 주 버전 변화가 호환성에 큰 영향을 줄 수 있음을 보여 주는 대표적인 사례로 자주 언급된다. 파이썬 2에서 작성된 코드가 파이썬 3에서 그대로 동작하지 않는 경우가 많았기 때문에, 사용자는 주 버전 변화에 맞추어 코드를 수정해야 했다.
부 버전
부 버전(영어: minor version)은 기존 공개 API와 하위 호환성을 유지하면서 새로운 기능을 추가할 때 증가한다. 또한 공개 API의 일부를 앞으로 제거할 예정으로 표시하는 경우에도 부 버전을 올리는 것이 원칙이다.[1]
부 버전이 증가하면 수 버전은 0으로 초기화한다. 예를 들어 1.4.3에서 하위 호환성을 유지하는 기능이 추가되었다면 다음 버전은 일반적으로 1.5.0이 된다.
부 버전 증가가 반드시 아무 위험도 없다는 뜻은 아니다. 새 기능이 기존 코드와 호환되도록 설계되었더라도, 실제 사용 환경에서는 의존성, 설정, 보안 정책, 폐기 예정 기능 등의 영향으로 추가 확인이 필요할 수 있다.
수 버전
수 버전(영어: patch version)은 기존 공개 API와 하위 호환성을 유지하면서 버그를 수정할 때 증가한다. 예를 들어 1.5.0에서 내부 오류를 수정했지만 공개 API의 사용 방식은 그대로 유지된다면 다음 버전은 일반적으로 1.5.1이 된다.
수 버전만 증가한 경우에는 보통 기존 코드를 수정할 필요가 없다. 다만 기존 코드가 버그에 의존하고 있었거나, 수정된 동작이 실제 운영 환경의 결과에 영향을 주는 경우에는 예외적으로 코드나 설정을 조정해야 할 수 있다.
초기 개발 버전과 1.0.0
주 버전이 0인 0.y.z 형식은 초기 개발 단계를 나타낸다. 이 단계에서는 공개 API가 안정적이라고 간주되지 않으며, 언제든 호환되지 않는 변경이 발생할 수 있다.[1]
1.0.0은 공개 API가 정의된 첫 안정판으로 볼 수 있다. 이후 버전 번호는 1.0.0에서 정의한 공개 API가 어떻게 바뀌는지에 따라 증가한다.
| 버전 범위 | 일반적인 의미 |
|---|---|
| 0.y.z | 초기 개발 단계. 공개 API가 안정적이라고 보기 어려움 |
| 1.0.0 | 공개 API가 정의된 첫 안정판 |
| 1.x.y 이상 | 정의된 공개 API를 기준으로 호환성 규칙을 적용하는 단계 |
선행 배포 버전
선행 배포 버전(영어: pre-release version)은 정식 배포 이전의 알파, 베타, 릴리스 후보 등을 표시할 때 사용한다. 수 버전 뒤에 붙임표(-)를 붙이고, 마침표(.)로 구분된 식별자를 덧붙인다.
예시는 다음과 같다.
| 선행 배포 버전 | 일반적인 의미 |
|---|---|
| 1.0.0-alpha | 초기 시험용 알파 버전 |
| 1.0.0-alpha.1 | 첫 번째 알파 계열 세부 버전 |
| 1.0.0-beta | 베타 버전 |
| 1.0.0-beta.2 | 두 번째 베타 계열 세부 버전 |
| 1.0.0-rc.1 | 첫 번째 릴리스 후보 버전 |
선행 배포 버전은 같은 주·부·수 버전의 정식 버전보다 우선순위가 낮다. 예를 들어 2.3.7-beta.3은 2.3.7보다 낮은 버전으로 취급된다.
빌드 메타데이터
빌드 메타데이터(영어: build metadata)는 더하기(+) 기호 뒤에 덧붙이는 부가 정보이다. 빌드 번호, 빌드 날짜, 커밋 해시, 빌드 환경 등을 표시하는 데 사용할 수 있다.
예시는 다음과 같다.
| 버전 | 설명 |
|---|---|
| 1.0.0+001 | 빌드 번호가 포함된 버전 |
| 1.0.0+20130313144700 | 빌드 시각 또는 날짜 형식의 메타데이터가 포함된 버전 |
| 1.0.0-beta+exp.sha.5114f85 | 선행 배포 버전과 빌드 메타데이터가 함께 포함된 버전 |
빌드 메타데이터는 버전 우선순위 비교에서 무시된다. 따라서 주·부·수 버전과 선행 배포 버전이 같고 빌드 메타데이터만 다른 경우, 두 버전의 우선순위는 같다.
버전 우선순위
유의적 버전에서는 버전의 우선순위를 비교할 때 주 버전, 부 버전, 수 버전, 선행 배포 버전 순서로 비교한다. 빌드 메타데이터는 우선순위 비교에 영향을 주지 않는다.
| 비교 예시 | 결과 | 이유 |
|---|---|---|
| 1.0.0 < 2.0.0 | 참 | 주 버전 2가 주 버전 1보다 크기 때문 |
| 2.0.0 < 2.1.0 | 참 | 부 버전 1이 부 버전 0보다 크기 때문 |
| 2.1.0 < 2.1.1 | 참 | 수 버전 1이 수 버전 0보다 크기 때문 |
| 1.0.0-alpha < 1.0.0 | 참 | 선행 배포 버전은 같은 버전의 정식 버전보다 낮기 때문 |
| 1.0.0-alpha < 1.0.0-alpha.1 | 참 | 앞선 식별자가 같을 때 더 많은 선행 배포 식별자를 가진 쪽이 더 높게 비교될 수 있기 때문 |
| 1.0.0+001 = 1.0.0+20130313144700 | 우선순위상 같음 | 빌드 메타데이터는 우선순위 비교에서 무시되기 때문 |
공식 명세에서 제시하는 선행 배포 버전의 우선순위 예시는 다음과 같다.[2]
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장점
유의적 버전의 장점은 다음과 같다.
한계와 주의점
유의적 버전은 모든 문제를 자동으로 해결하는 규칙은 아니다. 다음과 같은 점에 주의해야 한다.
- 공개 API가 명확하게 정의되어 있지 않으면 버전 번호의 의미가 약해진다.
- 개발자가 규칙을 잘못 적용하면 버전 번호와 실제 변경 내용이 일치하지 않을 수 있다.
- 응용 프로그램의 사용자 인터페이스 변경, 데이터 파일 형식 변경, 운영 환경 변경 등은 API 변경과 다르게 판단될 수 있다.
- 보안 문제나 긴급 패치의 경우, 기존 정책과 별도의 배포 판단이 필요할 수 있다.
- 생태계마다 버전 범위 해석 방식이 다를 수 있으므로, 실제 의존성 지정 방식은 사용하는 패키지 관리자 문서를 함께 확인해야 한다.
예시
하위 호환되는 버그 수정
기존 버전이 1.2.3이고, 공개 API는 그대로 유지하면서 내부 버그만 수정했다면 다음 버전은 일반적으로 다음과 같이 증가한다.
1.2.3 -> 1.2.4하위 호환되는 기능 추가
기존 버전이 1.2.3이고, 기존 API와 호환되는 새 기능을 추가했다면 다음 버전은 일반적으로 다음과 같이 증가한다.
1.2.3 -> 1.3.0하위 호환되지 않는 변경
기존 버전이 1.2.3이고, 공개 API의 사용 방식이 바뀌어 기존 코드가 수정 없이 동작하지 않을 수 있다면 다음 버전은 일반적으로 다음과 같이 증가한다.
1.2.3 -> 2.0.0정식 배포 전 버전
2.0.0 정식 배포 전 테스트 버전을 배포하려면 다음과 같은 형식을 사용할 수 있다.
2.0.0-alpha
2.0.0-beta.1
2.0.0-rc.1같이 보기
외부 링크
각주
- ↑ 1.0 1.1 1.2 1.3 유의적 버전 2.0.0, Semantic Versioning 공식 한국어 문서.
- ↑ 2.0 2.1 Semantic Versioning 2.0.0, Semantic Versioning 공식 문서.