티스토리 뷰

.NET 5, 6, 7

The future of .NET Standard

kaki104 2021. 1. 4. 10:00
반응형

.NET 5가 발표된 이후로 많은 분들이 .NET Standard에 대해 이것이 무엇을 의미하는지, 그리고 여전히 관련성이 있는지 물었습니다. 이 게시물에서는 .NET 5가 어떻게 코드 공유를 개선하고 .NET Standard를 대체하는지 설명하겠습니다. .NET Standard가 여전히 필요한 경우도 다룰 것입니다.

 

The future of .NET Standard | .NET Blog (microsoft.com)

 

The future of .NET Standard | .NET Blog

Since .NET 5 was announced, many of you have asked what this means for .NET Standard and whether it will still be relevant. In this post, I’m going to explain how .NET 5 improves code sharing and replaces .NET Standard. I’ll also cover the cases where

devblogs.microsoft.com

For the impatient: TL;DR

.NET 5는 Windows 데스크톱 앱, 크로스 플랫폼 모바일 앱, 콘솔 앱, 클라우드 서비스 및 웹 사이트에 사용할 수있는 일관된 기능 및 API 세트를 갖춘 단일 제품이 될 것입니다.

 

 

대상 프레임 워크 이름(TFM)을 업데이트했습니다.

  • net5.0은 모든 곳에서 실행되는 코드를 위한 것입니다. netcoreappnetstandard을 결합하고 대체합니다. 이 TFM에는 일반적으로 크로스 플랫폼에서 작동하는 기술만 포함됩니다. (이미 .NET Standard에서 했던 것과 비슷합니다).
  • net5.0-windows (및 이후 net6.0-androidnet6.0-ios). 이러한 TFM은 net5.0과 OS 별 기능을 포함하는 .NET 5의 OS 별 특징을 나타냅니다.

.NET Standard의 새 버전은 출시되지 않지만 .NET 5 및 모든 향후 버전은 .NET Standard 2.1 및 이전 버전을 계속 지원합니다. net5.0 (및 향후 버전)을 코드 공유를 위한 기반으로 생각해야합니다.

 

그리고 net5.0은 이러한 모든 새로운 TFM의 공유 기반이 됩니다. 런타임, 라이브러리 및 새로운 언어 기능이 이 버전 번호를 중심으로 조정됩니다. 예를 들어 C# 9를 사용하려면 net5.0 또는 net5.0-windows를 사용해야합니다.

What you should target

.NET 5 및 모든 향후 버전은 항상 .NET Standard 2.1 및 이전 버전을 지원합니다. .NET Standard에서 .NET 5로 대상을 변경하는 유일한 이유는 더 많은 런타임 기능, 언어 기능 또는 API에 액세스하기 위해서입니다. 따라서 .NET 5를 .NET Standard vNext로 생각할 수 있습니다.

 

새 코드는 어떻게 작성하면 좋을까요? .NET Standard 2.0으로 만들까요? 아니면 .NET 5로 바로 만들어야 할까요? 이 부분에 대해서는 다음을 아래 내용을 참고 합니다.

  • 앱 구성 요소로 개발하는 경우. 라이브러리를 사용하여 응용 프로그램을 여러 구성 요소로 나누는 경우 netX.Y를 사용하는 것이 좋습니다. 여기서 X.Y는 응용 프로그램 (또는 응용 프로그램)이 대상으로하는 .NET의 가장 낮은 수입니다. 단순성을 위해 응용 프로그램을 구성하는 모든 프로젝트가 동일한 버전의 .NET에 있기를 원할 것입니다. 이는 모든 곳에서 동일한 BCL 기능을 사용할 수 있음을 의미하기 때문입니다.
  • 재사용 가능한 라이브러리를 개발하는 경우. NuGet에서 제공 할 계획인 재사용 가능한 라이브러리를 빌드하는 경우 도달 범위와 사용 가능한 기능 세트 간의 균형을 고려하는 것이 좋습니다. .NET Standard 2.0은 .NET Framework에서 지원하는 .NET Standard의 가장 높은 버전이므로 가장 많은 범위를 제공하는 동시에 작업 할 수있는 상당히 큰 기능 세트를 제공합니다. .NET Standard 1.x는 더 이상 타겟팅하지 않는 것이 좋습니다. .NET Framework를 지원할 필요가없는 경우 .NET Standard 2.1 또는 .NET 5를 사용할 수 있습니다. 대부분의 코드는 .NET Standard 2.1을 건너 뛰고 .NET 5로 바로 이동할 수 있습니다.

그래서 어떻게 해야할까요? 아마도 넓게 사용되는 라이브러리를 만들려면 .NET Standard 2.0 및 .NET 5를 멀티 타게팅이 되어야 할 것입니다. .NET Standard 2.0을 지원하면 도달 범위가 가장 커지고, .NET 5를 지원하면 다음과 같은 고객을 위한 최신 플랫폼 기능을 활용할 수 있습니다.

 

몇 년 후 재사용 가능한 라이브러리의 선택에는 netX.Y의 버전 번호만 포함됩니다. 이는 기본적으로 .NET용 라이브러리 빌드가 항상 작동하는 방식입니다.

 

요약:

  • netstandard2.0을 사용하여 .NET Framework와 다른 모든 플랫폼간에 코드를 공유합니다.
  • netstandard2.1을 사용하여 Mono, Xamarin 및 .NET Core 3.x간에 코드를 공유합니다.
  • 앞으로는 코드 공유를 위한 라이브러리는 net5.0을 사용하십시오.

Problems with .NET Standard

.NET Standard를 사용하면 모든 .NET 플랫폼에서 작동하는 라이브러리를 훨씬 쉽게 만들 수 있습니다. 그러나 .NET Standard에는 여전히 세 가지 문제가 있습니다.

  1. 버전 업이 느리기 때문에 최신 기능을 쉽게 사용할 수 없습니다.
  2. 버전을 .NET 구현에 매핑하려면 디코더 링이 필요합니다.
  3. 플랫폼 별 기능을 노출하므로 코드가 진정으로 이식 가능한지 여부를 정적으로 확인할 수 없습니다.

Dealing with Windows-specific APIs

net5.0을 대상으로하는 프로젝트를 만들 때 Microsoft.Win32.Registry 패키지를 참조 할 수 있습니다. 하지만 사용을 시작하면 다음과 같은 경고가 표시됩니다.

private static string GetLoggingDirectory()
{
    using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Fabrikam"))
    {
        if (key?.GetValue("LoggingDirectoryPath") is string configuredPath)
            return configuredPath;
    }

    string exePath = Process.GetCurrentProcess().MainModule.FileName;
    string folder = Path.GetDirectoryName(exePath);
    return Path.Combine(folder, "Logging");
}
CA1416: 'RegistryKey.OpenSubKey(string)' is supported on 'windows'
CA1416: 'Registry.CurrentUser' is supported on 'windows'
CA1416: 'RegistryKey.GetValue(string?)' is supported on 'windows'

이러한 경고를 해결하는 방법에는 네 가지 옵션이 있습니다.

  1. 호출을 보호. API를 호출하기 전에 OperatingSystem.IsWindows() 를 사용하여 Windows에서 실행 중인지 확인할 수 있습니다.
  2. 호출을 Windows-specific로 만듬. 경우에 따라 [SupportedOSPlatform("windows")]를 통해 호출 멤버를 특정 플랫폼으로 표시하는 것이 합리적 일 수 있습니다.
  3. 코드를 삭제. 일반적으로 Windows 사용자가 코드를 사용할 때 신뢰를 잃기 때문에 이 방법을 사용하는 것을 권장하지 않치만, 크로스플랫폼 환경에서 플랫폼 별 API를 사용하는 것이 가능하다면 사용하는 것이 좋습니다. 예를 들어 레지스트리를 사용하는 대신 XML 구성 파일을 사용할 수 있습니다.
  4. 경고를 억제. 물론 .editorconfig 또는 #pragma warning disable을 통해 속이고 경고를 억제 할 수 있습니다. 그러나 플랫폼 별 API를 사용할 때는 옵션(1), (2)를 사용하는 것을 권장합니다.

호출을 보호하려면 System.OperatingSystem 클래스에서 새 정적 메서드를 사용합니다. 예를 들면 다음과 같습니다.

private static string GetLoggingDirectory()
{
    if (OperatingSystem.IsWindows())
    {
        using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Fabrikam"))
        {
            if (key?.GetValue("LoggingDirectoryPath") is string configuredPath)
                return configuredPath;
        }
    }

    string exePath = Process.GetCurrentProcess().MainModule.FileName;
    string folder = Path.GetDirectoryName(exePath);
    return Path.Combine(folder, "Logging");
}
[SupportedOSPlatform("windows")]
private static string GetLoggingDirectory()
{
    using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Fabrikam"))
    {
        if (key?.GetValue("LoggingDirectoryPath") is string configuredPath)
            return configuredPath;
    }

    string exePath = Process.GetCurrentProcess().MainModule.FileName;
    string folder = Path.GetDirectoryName(exePath);
    return Path.Combine(folder, "Logging");
}

두 경우 모두 레지스트리 사용에 대한 경고가 사라집니다.

 

주요 차이점은 두 번째 예에서 분석기는 이제 위의 메서드가 Windows 관련 API로 간주되기 때문에 GetLoggingDirectory() 호출시 이에 대한 경고를 발행한다는 것입니다. 즉, 플랫폼 확인 요구 사항을 호출자에게 전달합니다.

 

[SupportedOSPlatform] 특성은 멤버, 형식 또는 어셈블리 수준에 적용 할 수 있습니다. 이 속성은 BCL 자체에서도 사용됩니다. 예를 들어 어셈블리 Microsoft.Win32.Registry에는이 특성이 적용되어 분석기가 처음에 레지스트리가 Windows 관련 API임을 인식하는 방법입니다.

 

net5.0-windows를 대상으로하는 경우 이 특성이 어셈블리에 자동으로 적용됩니다. 즉, net5.0-windows를 이용한 애플리케이션이나 라이브러리에서 Windows 관련 API를 사용하면 전체 어셈블리가 Windows 관련 것으로 간주되므로 경고가 생성되지 않습니다.

 

Dealing with APIs that are unsupported in Blazor WebAssembly

Blazor WebAssembly 프로젝트는 사용할 수있는 API를 제한하는 browser sandbox 내에서 실행됩니다. 예를 들어 스레드 및 프로세스 생성은 모두 플랫폼 API이지만, 이러한 API를 Blazor WebAssembly에서 작동하도록 만들 수 없습니다. 즉, PlatformNotSupportedException이 발생합니다. 이러한 API를 [UnsupportedOSPlatform ("browser")]로 표시했습니다.

 

GetLoggingDirectory() 메서드를 Blazor WebAssembly 애플리케이션에 복사하여 붙여 넣는다 고 가정 해 보겠습니다.

private static string GetLoggingDirectory()
{
    //...

    string exePath = Process.GetCurrentProcess().MainModule.FileName;
    string folder = Path.GetDirectoryName(exePath);
    return Path.Combine(folder, "Logging");
}

다음과 같은 경고가 표시됩니다.

CA1416 'Process.GetCurrentProcess()' is unsupported on 'browser'
CA1416 'Process.MainModule' is unsupported on 'browser'

이러한 경고를 처리하기 위하여 기본적인 Windows 관련 API와 동일한 옵션이 있습니다.

 

호출 보호 방법

OperatingSystem.IsBrowser()를 이용하기

private static string GetLoggingDirectory()
{
    //...

    if (!OperatingSystem.IsBrowser())
    {
        string exePath = Process.GetCurrentProcess().MainModule.FileName;
        string folder = Path.GetDirectoryName(exePath);
        return Path.Combine(folder, "Logging");
    }
    else
    {
        return string.Empty;
    }
}

[UnsupportedOSPlatform("browser")]를 이용하기

[UnsupportedOSPlatform("browser")]
private static string GetLoggingDirectory()
{
    //...

    string exePath = Process.GetCurrentProcess().MainModule.FileName;
    string folder = Path.GetDirectoryName(exePath);
    return Path.Combine(folder, "Logging");
}

browser sandbox는 상당히 제한적이므로 모든 클래스 라이브러리 및 NuGet 패키지가 Blazor WebAssembly에서 작동 할 것으로 예상해서는 안됩니다. 또한 대부분의 라이브러리는 Blazor WebAssembly에서의 실행을 지원하지 않을 것으로 예상됩니다.

 

이것이 net5.0을 대상으로하는 일반 클래스 라이브러리에 Blazor WebAssembly에서 지원하지 않는 API에 대한 경고가 표시되지 않는 이유입니다. 프로젝트 파일에 <SupportedPlatform> 항목을 추가하여 Blazor WebAssembly에서 프로젝트를 지원할 것임을 명시적으로 나타내야합니다.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>
  
  <ItemGroup>
    <SupportedPlatform Include="browser" />
  </ItemGroup>
  
</Project>

.NET 5 as the combination of .NET Standard & .NET Core

.NET 5 및 후속 버전은 데스크톱 앱, 모바일 앱, 클라우드 서비스, 웹 사이트 및 .NET이 미래에 실행될 모든 환경을 지원하는 단일 코드 기반이 될 것입니다.

 

"잠깐만요, 이것은 훌륭하게 들리지만 누군가가 완전히 새로운 구현을 만들고 싶다면 어떨까요?"라고 생각할 수 있습니다. 그것도 괜찮습니다. 그러나 사실상 아무도 처음부터 시작하지 않습니다. 대부분의 경우 현재 코드베이스 (dotnet / runtime)의 포크가 될 것입니다. 예를 들어 Tizen (스마트 어플라이언스 용 삼성 플랫폼)은 최소한의 변경 사항과 삼성 전용 앱 모델이 맨 위에있는 .NET Core를 사용합니다.

 

Forking은 병합 관계를 유지하여 유지 관리자가 변경 사항의 영향을받지 않는 영역에서 BCL 혁신의 이점을 누리면서 dotnet/runtime repo에서 새로운 변경 사항을 계속 가져올 수 있도록합니다. 이는 Linux 배포판이 작동하는 방식과 매우 유사합니다.

 

물론 현재 BCL이없는 최소 런타임과 같이 매우 다른 "종류"의 .NET을 생성하려는 경우가 있습니다. 그러나 이는 어쨌든 기존 .NET 라이브러리 에코 시스템을 활용할 수 없다는 것을 의미합니다. 즉, .NET Standard도 구현하지 않았을 것입니다. 우리는 일반적으로 이 방향을 추구하는데 관심이 없지만 .NET Standard와 .NET Core의 수렴은 이를 방지하지도 않고 더 어렵게 만들지도 않습니다.

.NET versioning

라이브러리 개발자는 .NET 5가 언제까지 지원 될지 궁금 할 것입니다. 앞으로 매년 11 월에 .NET을 출시 할 예정이며 격년은 LTS (장기 지원) 릴리스입니다.

 

.NET 5는 2020년 11월에 출시되고 .NET 6는 2021년 11월에 LTS로 출시 될 예정입니다. 업데이트를 보다 쉽게 ​​계획하고 (앱 개발자 인 경우) 지원되는 .NET 버전에 대한 수요를 예측할 수 있도록 이 고정 된 일정을 만들었습니다 (라이브러리 개발자 인 경우).

 

.NET Core를 나란히 설치할 수있는 기능 덕분에 LTS 버전이 가장 많이 사용되는 새 버전이 상당히 빠르게 채택됩니다. 실제로 .NET Core 3.1은 가장 빠르게 채택 된 .NET 버전이었습니다.

우리가 출시 할 때마다 모든 프레임 워크 이름을 함께 제공해야합니다. 예를 들어 다음과 같을 수 있습니다.

.NET 5 .NET 6 .NET 7
net5.0 net6.0 net7.0
  net6.0-android net7.0-android
  net6.0-ios net7.0-ios
net5.0-windows net6.0-windows net7.0-windows
net5.0-someoldos    

즉, 일반적으로 BCL에서 수행 한 혁신이 무엇이든간에 실행되는 플랫폼에 관계없이 모든 앱 모델에서 사용할 수있을 것이라고 기대할 수 있습니다. 또한 최신 net 프레임워크용으로 제공된 라이브러리는 최신 버전을 실행하는 한 모든 앱 모델에서 항상 사용할 수 있습니다.

 

이 모델은 .NET Standard 버전 관리와 관련된 복잡성을 제거합니다. 출시 할 때마다 모든 플랫폼이 새 버전을 즉시 완벽하게 지원할 것이라고 가정 할 수 있기 때문입니다. 그리고 우리는 접두사 명명 규칙을 사용하여 이 약속을 강화합니다.

 

새 버전의 .NET은 다른 플랫폼에 대한 지원을 추가 할 수 있습니다. 예를 들어 .NET 6과 함께 Android 및 iOS에 대한 지원을 추가 할 것입니다. 반대로 더 이상 관련이없는 플랫폼 지원을 중지 할 수 있습니다. 이는 .NET 6에 존재하지 않는 net5.0-someoldos 대상 프레임 워크를 가장하여 설명합니다. 플랫폼을 삭제할 계획은 없지만 모델이 지원합니다. 그것은 큰 문제가 될 것이며 예상치 못한 일이며 오래 전에 발표 될 것입니다. 이는 .NET Standard와 동일한 모델입니다. 예를 들어 .NET Standard의 최신 버전에 구현된 새 버전의 Windows Phone이 없는 것과 같은 이치입니다.

Why there is no TFM for WebAssembly

원래 net5.0-wasm과 같은 WebAssembly용 TFM을 추가하는 것을 고려했습니다. 그러나, 우리는 다음과 같은 이유로 반대하기로 결정했습니다.

  • WebAssembly는 운영체제 보다는 명령어 세트 (예 : x86 또는 x64)와 비슷합니다. 그리고 일반적으로 서로 다른 아키텍처간에 서로 다른 API를 제공하지 않습니다.
  • 브라우저 샌드박스에서 WebAssembly의 실행 모델은 주요 차별화 요소이지만, 이를 런타임 검사로만 모델링하는 것이 더 합리적이라고 결정했습니다. Windows 및 Linux를 확인하는 방법과 유사하게 OperatingSystem 유형을 사용할 수 있습니다. 이것은 명령어 세트에 관한 것이 아니기 때문에이 메서드를 IsWebAssembly()가 아닌 IsBrowser()라고합니다.
  • browserbrowser-wasm이라고하는 WebAssembly의 런타임 식별자 (RID)가 있습니다. 이를 통해 패키지 작성자는 브라우저에서 WebAssembly를 대상으로 할 때 다른 바이너리를 배포 할 수 있습니다. 이는 사전에 웹 어셈블리로 컴파일해야하는 네이티브 코드에 특히 유용합니다.

위에서 설명한대로 System.Diagnostics.Process와 같이 브라우저 샌드 박스에서 지원되지 않는 API를 표시했습니다. 브라우저 앱 내에서 이러한 API를 사용하는 경우이 API가 지원되지 않는다는 경고가 표시됩니다.

Summary

net5.0은 모든 곳에서 실행되는 코드를 개발할 수 있습니다. netcoreappnetstandard 이름을 결합하고 대체합니다. 또한 net5.0-windows (및 이후에는 net6.0-androidnet6.0-ios)와 같은 플랫폼 별 프레임 워크도 있습니다.

 

표준과 구현간에 차이가 없기 때문에 .NET Standard보다 훨씬 빠르게 새로운 기능을 활용할 수 있습니다. 그리고 명명 규칙으로 인해 .NET Standard 버전 표를 참조하지 않고도 누가 주어진 라이브러리를 사용할 수 있는지 쉽게 알 수 있습니다.

 

.NET Standard 2.1은 .NET Standard의 마지막 버전이지만 .NET 5 및 모든 향후 버전은 .NET Standard 2.1 및 이전 버전을 계속 지원합니다. net5.0 (및 향후 버전)을 코드 공유를위한 기반으로 생각해야합니다.

 

PS

이제 공유 라이브러리는 모두 .net5.0으로 만들어야겠군요 ㅎㅎㅎ 어떻게 보면 속편하네요 버전 때문에 걸리적거렸는데

이제 직접 사용해 봐야 어떤지 알것 같습니다. 다만 net5.0-windows는 있는데 안드로이드와 ios는 6.0부터 나오니 아직은 .net standard를 사용해야하나? 확인해 보아야 할 것 같습니다;;;

 

 

 

 

 

 

반응형
댓글