의미론적 버전 관리 (또는 짧게 SemVer)는 세 부분으로 구성된 버전 번호를 규정하는 소프트웨어 버전 관리 체계로, <major>.<minor>.<patch>
형식을 사용하며 예를 들어 1.0.2
와 같습니다. 선택 사항으로 사전 출시 접미사를 -<prerelease>
형식으로 추가할 수 있으며, 예를 들어 1.0.2-beta
와 같습니다.
SemVer는 오늘날 가장 널리 사용되는 버전 관리 체계 중 하나입니다. 예를 들어, Nuget와 npm은 이를 추천하고 지원하며, VS Code는 이를 사용합니다.
GitHub Releases 기능을 사용하여 출 版을 게시하는 대부분의 GitHub 레포에서는 최신 출 版.badge에 SemVer 버전 번호를 볼 수 있으며, 아래 스크린샷에서도 확인할 수 있습니다:
ASP.NET Core API 프로젝트를 빌드할 때 자주 SemVer 버전 번호를 설정하고, 그것을 실행 시간에 읽거나 보고해야 합니다.
예를 들어, 버전을 1.0.2-beta
로 설정하여 최소 API를 구축하면, 이는 API가 노출한 /version
엔드포인트에서 보고됩니다. 아래의 Hoppscotch 스크린샷에서 확인할 수 있습니다(이는 브라우저에서 실행되는 Postman과 유사한 도구입니다):
배포된 서비스(웹 애플리케이션 및 API 등)에서 보고된 버전이 정확한지 확인하는 것은 내 CD 파이프라인의 중요한 부분이며, 배포가 성공했는지 여부를 결정하는 데 사용하는 연기 테스트 중 하나입니다.
.NET 어셈블리에 SemVer 버전 번호를 설정할 때의 한 가지 약간의 복잡성은 .NET이 원래 네 부분의 버전 번호를 사용했던 점입니다. 예를 들어, 1.0.3.212
과 같은 번호로, 어셈블리는 여전히 이를 가지고 있습니다(어셈블리는 .NET 바이트코드로 컴파일된 코드 단위를 의미하며, 대표적인 것으로는 dll과 exe가 있습니다).
또 다른 것은 .NET이 단일 어셈블리에 여러 가지 약간 다른 버전 번호를 가지고 있다는 점입니다.
이篇文章에서는 이러한 이상한 점을 피해가고 빌드 중에 .NET 어셈블리에 SemVer 버전 번호를 찍는 방법을 보여드리겠습니다. 즉, 컴파일된 .exe 또는 .dll에 찍고, 실행 시 이를 읽는 방법을 설명합니다.
목차
세미버전 번호의 구조
예를 들어 1.0.2
나 1.0.2-beta
와 같은 세미버전 번호를 고려해보면, 이는 <major>
.<minor>
.<patch>
–<prerelease>
형식을 가집니다.
이러한 다양한 구성 요소는 다음과 같은 의미를 가집니다:
버전 번호의 <major>
부분은 새로운 배포가 기존(최신) 배포를 깨뜨릴 경우에만 증가합니다.
UI 앱의 경우, 클라이언트는 인간 클라이언트를 의미할 수 있습니다. 따라서 새로운 배포가 사용자의 기존 자산(예: 워크플로 정의)을 깨뜨릴 경우, 주 버전 번호를 증가시켜야 합니다. 이 경우, 이전 배포가 1.0.2
였다면, 새로운 배포는 2.0.0
가 되어야 하며(버전 번호의 모든 하위 구성 요소가 리셋됩니다).
라이브러리의 경우, 예를 들어 Nuget이나 NPM에서 제공되는 라이브러리 패키지인 경우, 클라이언트는 다른 코드입니다. 따라서 새로운 배포가 기존 클라이언트 코드를 깨뜨릴 경우, 즉 자신의 이전 버전과 비 호환되는 경우, 다시 <major>
부분이 증가합니다.
<minor>
는 새로운 기능이 추가되었지만 새로운 버전이 여전히 하위 호환 가능하다면 증가합니다. 따라서 1.0.2
에서 1.1.0
으로 갑니다.
<patch>
는 새로운 배포가 깨뜨림이 없고 새로운 기능이 추가되지 않았음에도 불구하고 새로운 배포가 필요한 경우 증가합니다. 예를 들어, 버그 수정이 배포되는 경우 이와 같은 일이 일어날 수 있습니다.
-<prerelease>
접미사는 선택 사항입니다. 일반적으로 소프트웨어가 알파와 베타와 같은 사전 배포 테스트 단계에서 사용할 수 있도록 해야 할 때 세 가지 부분의 버전 번호에 추가됩니다. 예를 들어, 소프트웨어의 1.0.2
버전을 일반 배포하기 전에 베타 테스터에게 1.0.2-beta
로 제공할 수 있습니다.
초안 요소는 거의 당신의 선택에 따라 어떤 문자열이 될 수 있으며, 유일한 요구는 알파벳이나 숫자로 구성된 알파벳 숫자 식별자인지 여부입니다. 예를 들어, beta
또는 12
또는 alpha2
(알파벳이나 숫자 이외의 문자는 없음) 또는 점(.
)으로 구분된 여러 알파벳 숫자 식별자, 예를 들어 development.version
과 같습니다.
.NET 어셈블리의 많은 버전 번호
Andrew Lock의 .NET 버전 관리에 대한 기사에 설명된 바와 같이, .NET 어셈블리는 하나가 아니라 여러 가지 다른 버전 번호를 가지고 있습니다:
-
어셈블리 버전: 이는 네 부분으로 구성된 버전 번호로, 예를 들어
1.0.2.0
입니다. 런타임이 연결된 어셈블리를 로드할 때 사용됩니다. -
파일 버전: 이는 Windows 파일 탐색기에서 어셈블리를 오른쪽 클릭하고 속성을 선택할 때 보고되는 .dll 파일의 버전 번호입니다.
-
정보 버전: 또 다른 버전 번호로, FileVersion처럼 Windows에서 어셈블리를 오른쪽 클릭하고 속성을 선택하면 속성 대화 상자에서 볼 수 있습니다. 이 버전 번호는 AssemblyVersion와 FileVersion이 제약된 정수와 점만 포함할 수 있는 것과 달리 문자열을 포함할 수 있습니다.
-
패키지 버전: 프로젝트가 Nuget 패키지라면, 이는 어셈블리가 포함된 패키지의 버전 번호입니다.
이러한 모든 버전 번호는 컴파일 중 어셈블리에 메타데이터로 발생됩니다. JetBrains dotPeek (무료) 또는 Red gate Reflector (무료 아님)과 같은 도구로 어셈블리를 검사하면 볼 수 있습니다.
FileVersion와 InformationalVersion은 Windows 파일 탐색기에서 어셈블리 파일을 오른쪽 클릭하고 속성을 선택할 때 나타나는 속성 대화 상자의 상세 탭에서도 볼 수 있습니다:
위 스크린샷에서, “제품 버전”은 InformationalVersion의 캡션으로, ” 파일 버전”은 FileVersion의 캡션입니다.
위에서 설명한 네 가지 버전 번호 중에서는 첫 세 가지만 모든 어셈블리에 적용됩니다(어셈블리가 Nuget 패키지의 일부인지 여부와 관계없이).
그 중에서도 AssemblyVersion는 세 자리 수만 있는 SemVer 버전(선택 사항인 사전 출시 접미사 포함)을 설정하려고 할 때 항상 네 번째 자리에 0
을 추가합니다. 예를 들어 빌드 중 1.0.2-beta
의 SemVer 버전을 설정하고 실행 시 어셈블리 내에서 AssemblyVersion 값을 읽으면 1.0.2.0
이 됩니다.
FileVersion도 위 스크린샷에서와 같이 동일하게 작동합니다.
InformationalVersion은 빌드 중 설정한 서버 버전으로 정확하게 설정되는 유일한 버전 번호로, 위 스크린샷에서 보여줍니다.
따라서, 어셈블리의 SemVer 버전을 실행 시 읽어야 할 버전은 InformationalVersion입니다.
SemVer 버전 번호 설정 방법
빌드 중 어셈블리에 SemVer 버전 번호를 설정하려면 두 가지 작업을 수행해야 합니다.
첫째, 프로젝트의 csproj
파일의 <PropertyGroup>
요소 내에 <IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
요소를 추가합니다:
<PropertyGroup>
...
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
</PropertyGroup>
이 문제에서 설명된 이 문제에 따르면, InformationalVersion은 우리가 지정한 SemVer 버전 번호로 정확히 설정되며, 끝에 +<해시 코드>
가 추가되지 않습니다.
두 번째로, 버전 번호를 dotnet build
명령어에 전달되는 Version
프로퍼티의 값으로 전달하세요. 예를 들어:
dotnet build --configuration Release -p Version=1.0.2-beta
이렇게 하면 컴파일된 어셈블리(.exe 또는 .dll 파일)의 InformationalVersion을 1.0.2-beta
로 설정합니다.
fortuitously, 이는 AssemblyVersion와 FileVersion(마지막에 0
가 추가되는 1.0.2
)도 설정하지만, 우리는 이 두 가지에 관심이 없습니다.
명령 줄에서 Version
인수를 전달하는 대신, csproj 파일의 <PropertyGroup>
요소에 <Version>1.0.2-beta</Version>
MS Build 프로퍼티를 설정할 수 있습니다. 그러나 dotnet build
에 Version
매개변수의 값을 전달하는 것이 더 간단합니다. csproj 파일을 버전 번호가 증가할 때마다 수정할 필요가 없기 때문입니다. 이는 CI 파이프라인에서 유용합니다. 또한, 기본적으로 csproj 파일에는 버전 관련 프로퍼티가 없습니다.
어셈블리의 SemVer 버전을 실행 시간에 읽는 방법
실행 시간에 InformationalVersion을 읽는 코드는 다음과 같습니다:
string? version = Assembly.GetEntryAssembly()?.
GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.
InformationalVersion;
제 미니멀 API에서, 위의 소개 섹션에서 보여드린 것처럼 /version
엔드포인트를 추가하려면, 위의 스니пп트를 Program.cs
에 배치한 후, 다음 스니пп트를 즉시 추가합니다. builder.Build()
가 호출되기 이전에 전체가 나타나야 함에 유의하세요: 호출됩니다:
//이 익명 타입의 객체는 핸들러에 의해 반환될 때
//JSON으로 시리얼라이즈되어 응답 본문에 나타납니다
//when returned by a handler
var objVersion = new { Version = version ?? "" };
//다른 코드
//var app = builder.Build()
builder.Build()
가 호출된 후, /version
엔드포인트의 핸들러를 생성합니다:
app.MapGet("/version", () => objVersion);
이제 API 프로젝트를 실행하고 /version
엔드포인트를 호출하면, HTTP 응답 본문에서 JSON 객체로 버전 번호를 반환받습니다:
{
"version": "1.0.2-beta"
}
이는 소개에서 Hoppscotch 스크린샷이 보여준 것입니다:
결론
이 글은 .NET 어셈블리, 라이브러리, 또는 앱에 SemVer 버전 번호를 설정하는 방법을 보여드렸습니다:
또한 실행 시간에 버전 번호를 읽는 방법도 보여드렸습니다.
Source:
https://www.freecodecamp.org/news/set-semantic-versioning-for-net/