.NET7(닷넷7) 정식 릴리즈!! > 시티즌 인사이트

본문 바로가기

시티즌 커뮤니티

시티즌 인사이트

IT&개발 정보 .NET7(닷넷7) 정식 릴리즈!!

페이지 정보

작성자 얼룩깨모 작성일 22-11-16 14:51 조회 130회 댓글 0건

본문

.NET 7 다운로드



.NET6 가 나온지도 얼마 안되거 같은데, 벌써 .NET7 (Short Term Support (STS))이 출시되었습니다.

.NET6 대비 향상된 성능과 더 유연하고 다양한 개발 환경을 제공하고 있습니다. 


아직 서비스가 만료된 .NET Framework를 사용하고 계시거나, .NET CORE / 3 / 5와 같이 구 버전을 사용하시는 경우, .NET7으로의 업그레이드를 고민해보세요. ^^

 


아래 내용은 Microsoft 의 .NET 7 블로그를 한국어로 번역한 내용입니다.

* 원본 내용은 아래 링크를 참조해 주세요.

(https://devblogs.microsoft.com/dotnet/announcing-dotnet-7/)


지금 .NET 7을 다운로드하십시오! 


.NET 7은 C# 11 / F# 7 , .NET MAUI , ASP.NET Core/Blazor , 웹 API, WinForms , WPF 등을 위한 향상된 성능 과 새로운 기능을 앱에 제공합니다 

.NET 7을 사용하면 .NET 7 프로젝트를 쉽게 컨테이너화하고, GitHub 작업에서 CI/CD 워크플로를 설정하고, 클라우드 네이티브 관찰 가능성을 달성할 수 있습니다.


이 .NET 7 릴리스를 형성하는 데 도움이 된 수많은 기여에 대한 오픈 소스 .NET 커뮤니티 에 감사드립니다 . .NET 7 릴리스 전반에 걸쳐 8900명이 넘는 기여자가 28,000개의 기여를 했습니다 ! 

.NET은 330,000개 이상의 패키지를 포함 하는 광범위한 .NET 패키지 에코시스템 을 통해 가장 빠르고 사랑받고 신뢰할 수 있는 플랫폼 중 하나로 남아 있습니다.



다운로드 및 업그레이드 


지금 Windows, macOS 및 Linux용 무료 .NET 7 릴리스를 다운로드 할 수 있습니다 .


.NET 7은 .NET Core 버전 을 사용하는 경우 간단한 업그레이드를 제공 하고, 현재 .NET Framework 버전을 유지하고 있는 경우 마이그레이션해야 하는 몇 가지 중요한 이유를 제공 합니다.


Visual Studio 2022 17.4 도 오늘 사용할 수 있습니다. Visual Studio 2022에서 .NET 7을 개발하면 개발자에게 동급 최고의 생산성 도구가 제공됩니다. Visual Studio 2022의 새로운 기능을 알아보려면 Visual Studio 2022 블로그 를 확인하세요.



.NET 7의 새로운 기능


.NET 7은 다음을 포함하는 여러 다른 제품, 라이브러리 및 플랫폼과 함께 릴리스됩니다.


이 블로그 게시물에서는 .NET 팀이 제공하는 데 중점을 둔 주요 테마를 강조합니다.


  • 통합
    • 하나의 BCL
    • 새로운 TFM
    • ARM64에 대한 기본 지원
    • Linux에서 향상된 .NET 지원

  • 모던(Moden)
    • 지속적인 성능 향상
    • 컨테이너 우선 워크플로우와 같은 개발자 생산성 향상
    • 동일한 코드베이스에서 크로스 플랫폼 모바일 및 데스크톱 앱 구축

  • .NET은 클라우드 네이티브 앱(cloud-native apps)용입니다.
    • 분산형 클라우드 네이티브 앱을 쉽게 구축하고 배포할 수 있습니다.

  • 단순(Simple)
    • C# 11로 코드 간소화 및 작성 감소
    • 클라우드 네이티브 앱을 위한 HTTP/3 및 최소 API 개선

  • 성능
    • 획기적인 성능 향상


아래에서 이러한 주제를 더 자세히 다루고 이 작업이 중요한 이유에 대해 더 많은 맥락을 공유할 것입니다.



시나리오


.NET 7은 매우 다재다능하여 모든 플랫폼에서 모든 앱을 빌드할 수 있습니다.

오늘부터 .NET으로 달성할 수 있는 몇 가지 시나리오를 강조해 보겠습니다.




통합


하나의 기본 클래스 라이브러리(BCL)


.NET 플랫폼


.NET 7 릴리스는 .NET 통합 여정의 세 번째 주요 릴리스입니다(2016년 .NET 5 이후).


.NET 7을 사용하면 하나의 SDK, 하나의 런타임, 하나의 기본 라이브러리 세트로 기술을 한 번 배우고 재사용하여 다양한 유형의 앱(클라우드, 웹, 데스크톱, 모바일, 게임, IoT 및 AI)을 빌드할 수 있습니다.



.NET 7 타겟팅


앱 또는 라이브러리에서 프레임워크를 대상으로 지정할 때 사용 가능하게 하려는 API 세트를 지정하는 것입니다. .NET 7을 대상으로 지정하려면 프로젝트에서 대상 프레임워크를 변경하는 것만큼 쉽습니다.


<TargetFramework>net7.0</TargetFramework>


대상 프레임워크 모니커(TFM) 를 대상으로 하는 앱은 지원되는 모든 운영 체제 및 CPU 아키텍처에서 작동합니다. .NET 7의 모든 API와 다음과 같은 운영 체제별 API에 대한 액세스를 제공합니다: net7.0

  • net7.0-android
  • net7.0-ios
  • net7.0-maccatalyst
  • net7.0-macos
  • net7.0-tvos
  • net7.0-windows


TFM 을 통해 노출되는 API 는 어디에서나 작동하도록 설계되었습니다. 

API가 .NET 7에서 지원되는지 확실하지 않은 경우 언제든지 https://apisof.net/을 확인할 수 있습니다. 다음 은 .NET 7에 기본 제공되는 새로 추가된 인터페이스의 예입니다: net7.0IJsonTypeInfoResolver


.NET의 API



ARM64


업계가 ARM으로 이동함에 따라 .NET도 마찬가지입니다. ARM CPU의 가장 큰 장점 중 하나는 전력 효율성입니다. 이것은 최저 전력 소비로 최고의 성능을 제공합니다. 


즉, 적은 비용으로 더 많은 작업을 수행할 수 있습니다. .NET 5에서 우리는 ARM64에 대한 성능 이니셔티브를 설명했습니다 . 이제 두 번의 릴리스 후에 우리가 얼마나 멀리 왔는지 여러분과 공유하고 싶습니다. 우리의 지속적인 목표는 고객이 .NET 애플리케이션을 ARM으로 이전할 수 있도록 x64와 ARM64의 성능 패리티를 일치시키는 것입니다.



런타임 개선


x64 및 ARM64를 조사하면서 겪었던 한 가지 문제는 L3 캐시 크기가 ARM64 시스템에서 올바르게 읽히지 않는다는 사실을 발견하는 것이었습니다. 


OS 또는 컴퓨터의 BIOS에서 L3 캐시 크기를 가져올 수 없는 경우 대략적인 크기를 반환하도록 추론을 변경했습니다. 이제 L3 캐시 크기당 대략적인 코어 수를 더 잘 파악할 수 있습니다. 


코어 수L3 캐시 크기
1~44MB
5~168MB
17~6416MB
65세 이상32MB


다음은 LSE 원자에 대한 이해였습니다. 익숙하지 않은 경우 중요한 영역에 대한 독점 액세스 권한을 얻기 위해 원자 API를 제공합니다. CISC 아키텍처 x86-x64 시스템에서 메모리에 대한 RMW(읽기-수정-쓰기) 작업은 잠금 접두사를 추가하여 단일 명령으로 수행할 수 있습니다.


그러나 RISC 아키텍처 시스템에서는 RMW 작업이 허용되지 않으며 모든 작업은 레지스터를 통해 수행됩니다. 따라서 동시성 시나리오의 경우 한 쌍의 지침이 있습니다. 


"Load Acquire"(ldaxr)는 다른 코어가 액세스할 수 없도록 메모리 영역에 대한 독점 액세스 권한을 얻고 "Store Release"(stlxr)는 다른 코어가 액세스할 수 있도록 액세스를 해제합니다. 이 쌍 사이에서 중요한 작업이 수행됩니다. ldaxr을 사용하여 내용을 로드한 후 메모리에서 다른 CPU가 작동하여 stlxr 작업이 실패한 경우 작업을 다시 시도하는 코드가 있습니다(cbnz는 다시 시도하기 위해 점프). 


ARM은 v8.1에서 LSE 원자 명령어를 도입했습니다. 이러한 지침을 사용하면 이러한 작업을 기존 버전보다 더 적은 코드로 더 빠르게 수행할 수 있습니다. 이를 Linux용으로 활성화하고 나중에 Windows로 확장했을 때 성능이 약 45% 향상되었습니다.


ARM 원자론



라이브러리 개선


내장 함수를 사용하는 라이브러리를 최적화하기 위해 새로운 플랫폼 간 도우미를 추가했습니다.


내장 함수를 사용하는 라이브러리를 최적화하기 위해 새로운 플랫폼 간 도우미를 추가했습니다. 여기에는 Vector64, Vector128 및 Vector256용 도우미가 포함됩니다. 


플랫폼 간 도우미를 사용하면 하드웨어 관련 내장 함수를 하드웨어에 구애받지 않는 내장 함수로 대체하여 벡터화 알고리즘을 통합할 수 있습니다. 이는 모든 플랫폼의 사용자에게 도움이 되지만 ARM64 전문 지식이 없는 개발자도 헬퍼를 사용하여 Arm64 하드웨어 고유 기능을 활용할 수 있으므로 ARM64가 가장 많은 이점을 얻을 것으로 예상됩니다.


EncodeToUtf8 및 DecodeFromUtf8과 같은 API를 SSE3 구현에서 벡터 기반 구현으로 재작성하면 최대 60%의 개선을 제공할 수 있습니다.


텍스트 처리 개선


마찬가지로 NarrowUtf16ToAscii() 및 GetIndexOfFirstNonAsciiChar()와 같은 다른 API를 변환하면 최대 35%의 성능 향상을 입증할 수 있습니다. 


System.Memory.Span<Byte>.Reverse 메서드 재작성



성능 영향


.NET 7에서의 작업으로 많은 MicroBenchmark가 10-60% 향상되었습니다. .NET 7을 시작하면서 ARM64의 RPS(초당 요청 수)는 더 낮았지만 x64의 패리티를 천천히 극복했습니다.


TechEmpower x64 대 ARM64 초당 요청(RPS)


마찬가지로 대기 시간(밀리초 단위로 측정)의 경우 x64의 패리티를 연결합니다.


TechEmpower x64 대 ARM64 대기 시간


자세한 내용 은 .NET 7의 ARM64 성능 개선 사항을 확인하십시오.



Linux에서 향상된 .NET 지원


.NET 6은 Ubuntu 22.04(Jammy)에 포함되어 있으며 apt install dotnet6 명령으로 설치할 수 있습니다. 또한 즉시 사용할 수 있는 최적화되고 사전 구축된 초소형 컨테이너 이미지가 있습니다.

dotnetapp % docker run --rm dotnetapp-chiseled
         42
         42              ,d                             ,d
         42              42                             42
 ,adPPYb,42  ,adPPYba, MM42MMM 8b,dPPYba,   ,adPPYba, MM42MMM
a8"    `Y42 a8"     "8a  42    42P'   `"8a a8P_____42   42
8b       42 8b       d8  42    42       42 8PP"""""""   42
"8a,   ,d42 "8a,   ,a8"  42,   42       42 "8b,   ,aa   42,
 `"8bbdP"Y8  `"YbbdP"'   "Y428 42       42  `"Ybbd8"'   "Y428

.NET 7.0.0-preview.7.22375.6
Linux 5.10.104-linuxkit #1 SMP PREEMPT Thu Mar 17 17:05:54 UTC 2022

OSArchitecture: Arm64
ProcessorCount: 4


Canonical 및 ARM과의 파트너십에 대한 자세한 내용은 .NET 6 is now in Ubuntu 22.04 를 참조 하십시오.



64비트 IBM Power 지원


x64 아키텍처(64비트 Intel/AMD), ARM64(64비트 ARM) 및 s390x(64비트 IBM Z) 외에도 .NET은 이제 RHEL을 대상으로 하는 ppc64le(64비트 IBM Power) 아키텍처에서도 사용할 수 있습니다. 8.7 및 RHEL 9.1.


이제 기본적으로 Power에서 실행할 수 있으므로 25,000명 이상의 IBM Power 고객은 Windows x86에서 기존 .NET 앱을 통합하여 IBM i 및 AIX 비즈니스 앱 및 데이터베이스와 동일한 Power 플랫폼에서 실행할 수 있습니다. 


그렇게 하면 RHEL 및 OpenShift 용량에 대한 온프레미스 종량제 확장과 결합된 최대 5배 더 작은 탄소 발자국으로 지속 가능성을 크게 개선하는 동시에 업계 최고의 엔드 투 엔드 엔터프라이즈 트랜잭션 및 데이터 보안을 제공할 수 있습니다.



모던 (Modern)


.NET 7은 최신 클라우드 네이티브 앱, 모바일 클라이언트, 에지 서비스 및 데스크톱 기술용으로 제작되었습니다. .NET MAUI를 사용하여 기본 성능을 손상시키지 않으면서 단일 코드베이스를 사용하여 모바일 경험을 만드십시오.


C# 및 Razor 템플릿과 같은 친숙한 기술을 사용하여 PWA(Progressive Web App)로 브라우저와 오프라인에서 실행되는 반응형 단일 페이지 애플리케이션(SPA)을 빌드합니다. 이러한 더 빠른 최신 경험은 새로운 애플리케이션만을 위한 것이 아닙니다. 


.NET 업그레이드 도우미는 호환성에 대한 피드백을 제공하고 경우에 따라 앱을 .NET 6 및 .NET 7로 완전히 마이그레이션합니다.



.NET MAUI


NET MAUI는 이제 수많은 개선 사항과 새로운 기능을 갖춘 .NET 7의 일부입니다. 


최신 .NET MAUI 블로그 공지 사항 을 읽으면 .NET MAUI와 이를 통해 모든 모바일 장치용 앱을 빌드할 수 있는 방법에 대해 알아볼 수 있습니다 .



Blazor (블레이저)


Blazor는 계속 발전하고 있으며 .NET 7에는 많은 주요 개선 사항이 포함되어 있습니다. Blazor는 이제 위치 변경 이벤트 처리, WebAssembly 디버깅 환경 개선, OpenID Connect를 사용한 인증에 대한 기본 지원을 지원합니다. 자세히 알아보려면 최신 Blazor 팀 블로그 게시물 을 읽어보세요 .



업그레이드 어시스턴트


.NET 업그레이드 도우미는 레거시 앱을 .NET 6 및 .NET 7로 가져오기 위한 단계별 지침, 통찰력 및 자동화를 제공합니다. 경우에 따라 마이그레이션을 수행할 수 있습니다! 오래된 코드베이스를 현대화할 때 시간과 복잡성을 줄이는 데 도움이 됩니다. 


예를 들어 CoreWCF의 도움을 받아 WCF 앱을 .NET Core로 가져오는 방법을 알아보세요. .NET 7을 사용하면 다음과 같은 경험이 향상됩니다.


  • ASP.NET에서 ASP.NET Core로
    • System.Web adapters (preview)
    • Incremental migrations (preview)
  • WinForms, WPF 및 콘솔/클래스 라이브러리에 추가된 분석기 및 코드 수정 프로그램
  • 바이너리 분석 기능
  • UWP에서 Windows 앱 SDK 및 WinUI 지원
     

지금까지 가장 빠르고 성능이 뛰어난 최신 .NET으로 앱을 이동할 준비가 되셨습니까? 오늘 업그레이드 어시스턴트를 다운로드하십시오 !



.NET 6 마이그레이션 하이라이트


작년에 .NET 6이 발표된 후 최신 버전의 .NET으로의 성공적인 여정이 많이 있었습니다. 


이 사례에서는 CPU 사용량의 상당한 개선, RPS(초당 요청 수) 증가, 스레드 풀 사용량 개선, 바이너리 크기 감소, 시작 시간 단축, 종속성 관리 단순화, 향후 기술 부채 감소, 인프라 비용 감소 등의 이점을 강조합니다 : 엔지니어링 만족도 및 생산성.




.NET은 클라우드 네이티브 앱을 지원합니다.


.NET 7을 사용하면 즉시 사용 가능한 클라우드 네이티브 애플리케이션을 그 어느 때보다 쉽게 ​​구축할 수 있습니다. 


Visual Studio의 연결된 서비스를 사용하여 데이터 서비스에 안전하게 연결하고 사용자 비밀 파일 또는 Azure Key Vault에서 연결 문자열을 안전하게 암호화합니다. 앱을 컨테이너 이미지에 직접 빌드합니다. 


Entity Framework 7을 사용하여 SQL Server의 JSON 지원을 사용하는 강력한 형식의 LINQ(Language Integrated Query) 쿼리를 작성하여 관계형 데이터베이스에 저장된 JSON 문서에서 콘텐츠를 빠르게 추출합니다. 


최소 API 환경에서 단 몇 줄의 코드를 사용하여 인증된 엔드포인트를 통해 안전한 JSON 문서를 제공합니다. Open Telemetry로 실행 중인 애플리케이션에 대한 인사이트를 수집하세요.



Azure는 Day Zero를 지원합니다.


.NET 7은 클라우드 네이티브 앱을 구축하는 데 적합할 뿐만 아니라 Windows 및 Linux용 App Service, Static Web Apps, Azure Functions 및 Azure Container Apps와 같은 Azure의 PaaS 서비스 는 .NET 5.0 및 6.0과 같은 연속 세 번째 릴리스를 위해 오늘 .NET 7에 사용할 준비가 되었습니다.


.NET 7 SDK는 .NET 7을 사용하여 새로운 App Services를 생성하는 고객을 위해 적시에 설치되므로 릴리스 첫 주 동안 .NET 7 애플리케이션의 시작 시간이 약간 더 길어질 수 있습니다. 


또한 .NET 7 미리 보기 릴리스를 실행 중인 경우 App Service를 다시 시작하기만 하면 GA 비트로 업데이트됩니다.



내장 컨테이너 지원


컨테이너의 인기와 실용적인 사용이 증가하고 있으며 많은 회사에서 컨테이너를 클라우드에 배포하는 데 선호하는 방법을 나타냅니다. 


그러나 컨테이너로 작업하면 이미지 빌드 및 게시, 보안 및 규정 준수 확인, 이미지 성능 최적화를 포함하여 팀의 백로그에 새로운 작업이 추가됩니다. 우리는 .NET 컨테이너를 사용하여 더 우수하고 간소화된 환경을 만들 수 있는 기회가 있다고 믿습니다.


이제 dotnet publish만으로 애플리케이션의 컨테이너화된 버전을 만들 수 있습니다. 우리는 자체의 풍부한 C# 도구 및 런타임 성능을 활용하고 정기적인 업데이트를 위해 .NET SDK 상자에 바로 내장되어 기존 빌드 논리와 원활하게 통합되는 것을 목표로 이 솔루션을 구축했습니다.


컨테이너 이미지는 이제 .NET SDK의 지원되는 출력 유형입니다. 


# create a new project and move to its directory
dotnet new mvc -n my-awesome-container-app
cd my-awesome-container-app

# add a reference to a (temporary) package that creates the container
dotnet add package Microsoft.NET.Build.Containers

# publish your project for linux-x64
dotnet publish --os linux --arch x64 -p:PublishProfile=DefaultContainer


빌트인 컨테이너 지원에 대한 자세한 내용은 .NET SDK에 대한 빌트인 컨테이너 지원 발표 를 참조하세요.



Microsoft Orleans


Microsoft Orleans 7.0은 POCO(Plain Old CLR Object) 그레인을 사용하여 더 간단한 프로그래밍 모델을 제공하고 3.x보다 최대 150% 향상된 성능을 제공하며 새로운 직렬화 및 불변성 개선 사항을 도입합니다. 


ASP.NET Core 개발자는 Orleans를 사용하여 단순하게 분산 상태를 추가할 수 있으며, 애플리케이션이 복잡성을 추가하지 않고 수평으로 확장될 것이라고 확신할 수 있습니다. 


우리는 웹 및 API 응용 프로그램이 클라우드 규모, 분산 호스팅 시나리오 또는 다중 클라우드 배포에 대비할 수 있도록 Orleans 기능을 ASP.NET 스택에 더 가깝게 만드는 데 계속 투자할 것입니다. 


가장 널리 사용되는 스토리지 메커니즘 및 데이터베이스를 지원하고 ASP.NET Core를 실행할 수 있는 모든 곳에서 실행할 수 있는 기능을 갖춘 Orleans는 새로운 프레임워크나 도구 세트를 배울 필요 없이 클라우드 네이티브 분산 기능으로 .NET 앱을 활성화할 수 있는 훌륭한 선택입니다. Orleans 7에 대해 자세히 알아보세요.



관찰 가능성


관찰 가능성의 목표는 애플리케이션이 확장되고 기술 복잡성이 증가함에 따라 애플리케이션의 상태를 더 잘 이해할 수 있도록 돕는 것입니다. .NET은 OpenTelemetry를 수용 하는 동시에 .NET 7에서 아래의 개선 사항을 적용했습니다.


Activity.Current 변경 이벤트 소개


분산 추적의 일반적인 구현은 AsyncLocal<T>를 사용하여 관리되는 스레드의 "범위 컨텍스트"를 추적합니다. 범위 컨텍스트에 대한 변경 사항은 valueChangedHandler 매개 변수를 사용하는 AsyncLocal<T> 생성자를 사용하여 추적됩니다. 


그러나 Activity가 OpenTelemetry에서 사용하는 범위를 나타내는 표준이 되면서 Activity.Current를 통해 컨텍스트를 추적하기 때문에 값 변경 핸들러를 설정할 수 없습니다. 


새 변경 이벤트를 대신 사용하여 원하는 알림을 받을 수 있습니다. 


Activity.CurrentChanged += CurrentChanged;

void CurrentChanged(object? sender, ActivityChangedEventArgs e)
{
  Console.WriteLine($"Activity.Current value changed from Activity:  {e.Previous.OperationName} to Activity: {e.Current.OperationName}");
}



수행자 활동 속성 열거자 메서드 노출


새로 노출된 다음 메서드는 성능이 중요한 시나리오에서 추가 할당 및 성능 항목 액세스 없이 활동의 태그, 링크 및 이벤트 속성을 열거하는 데 사용할 수 있습니다.

Activity a = new Activity("Root");

a.SetTag("key1", "value1");
a.SetTag("key2", "value2");

foreach (ref readonly KeyValuePair<string, object?> tag in a.EnumerateTagObjects())
{
  Console.WriteLine($"{tag.Key}, {tag.Value}");
}



수행자 ActivityEvent 및 ActivityLink 태그 열거자 메서드 노출


위와 유사하게 ActivityEvent및 ActivityLink Tag 개체도 노출되어 성능 항목 액세스에 대한 추가 할당을 줄입니다.

var tags = new List<KeyValuePair<string, object?>>()
{
  new KeyValuePair<string, object?>("tag1", "value1"),
  new KeyValuePair<string, object?>("tag2", "value2"),
};

ActivityLink link = new ActivityLink(default, new ActivityTagsCollection(tags));

foreach (ref readonly KeyValuePair<string, object?> tag in link.EnumerateTagObjects())
{
// Consume the link tags without any extra allocations or value copying.
}

ActivityEvent e = new ActivityEvent("SomeEvent", tags: new ActivityTagsCollection(tags));

foreach (ref readonly KeyValuePair<string, object?> tag in e.EnumerateTagObjects())
{
// Consume the event's tags without any extra allocations or value copying.
}



Simple

C# 11 및 F# 7 


C# 및 F# 언어에 대한 최신 추가 사항은 C# 11 및 F# 7 입니다. 

C# 11은 개체 초기화 개선, 원시 문자열 리터럴 등을 통해 코드를 단순화하면서 일반 수학과 같은 새로운 기능을 가능하게 합니다.



일반 수학


.NET 7은 기본 클래스 라이브러리에 대한 새로운 수학 관련 일반 인터페이스를 도입합니다. 


이러한 인터페이스의 가용성은 제네릭 형식 또는 메서드의 형식 매개 변수를 "숫자 유사"로 제한할 수 있음을 의미합니다. 또한 C# 11 이상에서는 정적 가상 인터페이스 멤버를 정의할 수 있습니다. 


연산자는 정적으로 선언해야 하므로 이 새로운 C# 기능을 사용하면 연산자를 숫자와 유사한 형식의 새 인터페이스에서 선언할 수 있습니다.


이러한 혁신을 통해 작업 중인 정확한 유형을 알 필요 없이 일반적으로 수학적 연산을 수행할 수 있습니다. 


예를 들어 두 개의 숫자를 더하는 메서드를 작성하려면 이전에는 각 유형(예: static int Add(int first, int second) 및 static float Add(float first, float second) 이제 유형 매개변수가 숫자와 유사한 유형으로 제한되는 단일 일반 메서드를 작성할 수 있습니다.


static T Add<T>(T left, T right) where T : INumber<T>
{
    return left + right;
}


이 메서드에서 형식 매개 변수 T는 새로운 INumber<TSelf> 인터페이스를 구현하는 형식으로 제한됩니다. 

INumber<TSelf>는 + 연산자를 포함하는 IAdditionOperators<TSelf,TOther,TResult> 인터페이스를 구현합니다. 


이를 통해 메서드는 일반적으로 두 숫자를 더할 수 있습니다. 이 메서드는 .NET 7에서 INumber<TSelf>를 구현하도록 모두 업데이트되었기 때문에 .NET의 기본 제공 숫자 유형과 함께 사용할 수 있습니다. 


라이브러리 작성자는 "중복" 오버로드를 제거하여 코드 기반을 단순화할 수 있기 때문에 일반 수학 인터페이스에서 가장 많은 이점을 얻을 수 있습니다. 다른 개발자들은 그들이 사용하는 API가 더 많은 유형을 지원하기 시작할 수 있기 때문에 간접적으로 이익을 얻을 것입니다. 


각 인터페이스에서 제공하는 핵심 API에 대한 자세한 내용은 Generic Math 문서를 확인하세요.



원시 문자열 리터럴


이제 문자열 리터럴에 대한 새로운 형식이 있습니다. 원시 문자열 리터럴은 이스케이프 시퀀스를 요구하지 않고 공백, 새 줄, 포함된 따옴표 및 기타 특수 문자를 포함한 임의의 텍스트를 포함할 수 있습니다. 


원시 문자열 리터럴은 3개 이상의 큰따옴표(""") 문자로 시작하고 같은 수의 큰따옴표 문자로 끝납니다.


string longMessage = """
    This is a long message.
    It has several lines.
        Some are indented
                more than others.
    Some should start at the first column.
    Some have "quoted text" in them.
    """;



.NET 라이브러리


많은 .NET의 자사 라이브러리가 .NET 7 릴리스에서 크게 개선되었습니다. 


Microsoft.Extensions.* 패키지에 대한 null 허용 주석 지원, System.Text.Json에 대한 계약 사용자 지정 및 유형 계층 구조, TAR(테이프 아카이브) 형식으로 데이터를 작성하는 데 도움이 되는 새로운 Tar API 등이 표시됩니다.


Microsoft.Extensions에 대한 Null 허용 주석


이제 모든 Microsoft.Extensions.* 라이브러리에는 잠재적인 null 역참조를 포착하기 위해 컴파일러가 참조 형식의 null 허용 여부를 추적할 수 있는 C# 8 옵트인 기능이 포함되어 있습니다. 이렇게 하면 코드로 인해 런타임에서 System.NullReferenceException이 발생할 가능성을 최소화할 수 있습니다. 


시스템.구성.호스팅


API ComposeExportedValue(CompositionContainer, T)를 통해 레거시 인터페이스에 System.ComponentModel.Composition.Hosting과 유사한 기능을 제공하는 단일 개체 인스턴스를 System.Composition.Hosting 컨테이너에 허용하는 새 API가 추가되었습니다. 


namespace System.Composition.Hosting
{
  public class ContainerConfiguration
  {
      public ContainerConfiguration WithExport<TExport>(TExport exportedInstance);
      public ContainerConfiguration WithExport<TExport>(TExport exportedInstance, string contractName = null, IDictionary<string, object> metadata = null);
      public ContainerConfiguration WithExport(Type contractType, object exportedInstance);
      public ContainerConfiguration WithExport(Type contractType, object exportedInstance, string contractName = null, IDictionary<string, object> metadata = null);
  }
}


TimeStamp, DateTime, DateTimeOffset 및 TimeOnly에 마이크로초(Microseconds) 및 나노초(Nanoseconds) 추가
 

.NET 7 이전에는 다양한 날짜 및 시간 구조에서 사용할 수 있는 가장 낮은 시간 증분은 Ticks 속성에서 사용할 수 있는 "틱"이었습니다. 

참고로 1틱은 100ns입니다. 
개발자는 전통적으로 마이크로초 및 나노초 값을 결정하기 위해 "틱" 값에 대한 계산을 수행해야 했습니다. .NET 7에서는 날짜 및 시간 구현에 마이크로초와 나노초를 모두 도입했습니다.
 

namespace System
{
  public struct DateTime
  {
    public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond);
    public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond, System.DateTimeKind kind);
    public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond, System.Globalization.Calendar calendar);
    public int Microsecond { get; }
    public int Nanosecond { get; }
    public DateTime AddMicroseconds(double value);
  }

  public struct DateTimeOffset
  {
    public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond, System.TimeSpan offset);
    public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond, System.TimeSpan offset, System.Globalization.Calendar calendar);
    public int Microsecond { get; }
    public int Nanosecond { get; }
    public DateTimeOffset AddMicroseconds(double microseconds);
  }

  public struct TimeSpan
  {
    public const long TicksPerMicrosecond = 10L;
    public const long NanosecondsPerTick = 100L;
    public TimeSpan(int days, int hours, int minutes, int seconds, int milliseconds, int microseconds);
    public int Microseconds { get; }
    public int Nanoseconds { get; }
    public double TotalMicroseconds { get; }
    public double TotalNanoseconds { get; }
    public static TimeSpan FromMicroseconds(double microseconds);
  }

  public struct TimeOnly
  {
    public TimeOnly(int hour, int minute, int second, int millisecond, int microsecond);
    public int Microsecond { get; }
    public int Nanosecond { get; }
  }
}



Microsoft.Extensions.Caching


IMemoryCache에 대한 캐시 적중, 누락 및 예상 크기를 보유하는 MemoryCacheStatistics의 새로운 API인 IMemoryCache에 대한 메트릭 지원을 추가했습니다. TrackStatistics 플래그가 활성화되면 GetCurrentStatistics()를 호출하여 MemoryCacheStatistics의 인스턴스를 가져올 수 있습니다.


GetCurrentStatistics() API를 통해 앱 개발자는 이벤트 카운터 또는 메트릭 API를 사용하여 하나 이상의 메모리 캐시에 대한 통계를 추적할 수 있습니다.


// when using `services.AddMemoryCache(options => options.TrackStatistics = true);` to instantiate
[EventSource(Name = "Microsoft-Extensions-Caching-Memory")]
internal sealed class CachingEventSource : EventSource
{
  public CachingEventSource(IMemoryCache memoryCache)
  {
    _memoryCache = memoryCache;
  }
  protected override void OnEventCommand(EventCommandEventArgs command)
  {
    if (command.Command == EventCommand.Enable)
    {
      if (_cacheHitsCounter == null)
      {
          _cacheHitsCounter = new PollingCounter("cache-hits", this, () => _memoryCache.GetCurrentStatistics().CacheHits)
          {
            DisplayName = "Cache hits",
          };
      }
    }
  }
}


그런 다음 dotnet-counters 도구를 사용하여 아래 통계를 볼 수 있습니다.


Press p to pause, r to resume, q to quit.
    Status: Running

[System.Runtime]
    CPU Usage (%)                                      0
    Working Set (MB)                                  28
[Microsoft-Extensions-Caching-MemoryCache]
    cache-hits                                       269



System.Formats.Tar API


Tar 아카이브의 읽기, 쓰기, 보관 및 추출을 허용하는 플랫폼 간 API가 포함 된 새 어셈블리인 System.Formats.Tar를 추가했습니다 . 이러한 API는 게시 대상으로 컨테이너를 생성하기 위해 SDK에서도 사용됩니다.


// Generates a tar archive where all the entry names are prefixed by the root directory 'SourceDirectory'
TarFile.CreateFromDirectory(sourceDirectoryName: "/home/dotnet/SourceDirectory/", destinationFileName: "/home/dotnet/destination.tar", includeBaseDirectory: true);

// Extracts the contents of a tar archive into the specified directory, but avoids overwriting anything found inside
TarFile.ExtractToDirectory(sourceFileName: "/home/dotnet/destination.tar", destinationDirectoryName: "/home/dotnet/DestinationDirectory/", overwriteFiles: false);


유형 변환기


이제 새로 추가된 기본 유형 DateOnlyTimeOnlyInt128UInt128 및 Half에 대한 노출된 유형 변환기가 있습니다.


namespace System.ComponentModel
{
  public class DateOnlyConverter : System.ComponentModel.TypeConverter
  {
    public DateOnlyConverter() { }
  }

  public class TimeOnlyConverter : System.ComponentModel.TypeConverter
  {
    public TimeOnlyConverter() { }
  }

  public class Int128Converter : System.ComponentModel.BaseNumberConverter
  {
    public Int128Converter() { }
  }

  public class UInt128Converter : System.ComponentModel.BaseNumberConverter
  {
    public UInt128Converter() { }
  }

  public class HalfConverter : System.ComponentModel.BaseNumberConverter
  {
    public HalfConverter() { }
  }
}


이들은 보다 원시적인 유형으로 쉽게 변환할 수 있는 유용한 변환기입니다.

TypeConverter dateOnlyConverter = TypeDescriptor.GetConverter(typeof(DateOnly));
// produce DateOnly value of DateOnly(1940, 10, 9)
DateOnly? date = dateOnlyConverter.ConvertFromString("1940-10-09") as DateOnly?;

TypeConverter timeOnlyConverter = TypeDescriptor.GetConverter(typeof(TimeOnly));
// produce TimeOnly value of TimeOnly(20, 30, 50)
TimeOnly? time = timeOnlyConverter.ConvertFromString("20:30:50") as TimeOnly?;

TypeConverter halfConverter = TypeDescriptor.GetConverter(typeof(Half));
// produce Half value of -1.2
Half? half = halfConverter.ConvertFromString(((Half)(-1.2)).ToString()) as Half?;

TypeConverter Int128Converter = TypeDescriptor.GetConverter(typeof(Int128));
// produce Int128 value of Int128.MaxValue which equal 170141183460469231731687303715884105727
Int128? int128 = Int128Converter.ConvertFromString("170141183460469231731687303715884105727") as Int128?;

TypeConverter UInt128Converter = TypeDescriptor.GetConverter(typeof(UInt128));
// produce UInt128 value of UInt128.MaxValue Which equal 340282366920938463463374607431768211455
UInt128? uint128 = UInt128Converter.ConvertFromString("340282366920938463463374607431768211455") as UInt128?;



System.Text.Json 계약 사용자 정의


System.Text.Json은 해당 유형에 대한 JSON 계약을 구성하여 지정된 .NET 유형이 직렬화 및 역직렬화되는 방식을 결정합니다. 계약은 유형의 형태(예: 사용 가능한 생성자, 속성 및 필드, 구현 여부) IEnumerable 또는 IDictionary 리플렉션을 사용하는 런타임 또는 소스 생성기를 사용하는 컴파일 타임에 파생됩니다. 


이전 릴리스에서는 사용자가 형식 선언을 수정할 수 있다고 가정하고 System.Text.Json 특성 주석을 사용하여 파생된 계약을 제한적으로 조정할 수 있었습니다.


주어진 유형 T에 대한 계약 메타데이터는 JsonTypeInfo<T>를 사용하여 표현되며, 이전 버전에서는 소스 생성기 API에서만 사용되는 불투명한 토큰 역할을 했습니다. 


.NET 7부터 JsonTypeInfo 계약 메타데이터의 대부분의 측면이 노출되어 사용자가 수정할 수 있게 되었습니다. 계약 사용자 지정을 통해 사용자는 IJsonTypeInfoResolver 인터페이스의 구현을 사용하여 자신의 JSON 계약 해결 논리를 작성할 수 있습니다. 


public interface IJsonTypeInfoResolver
{
  JsonTypeInfo? GetTypeInfo(Type type, JsonSerializerOptions options);
}


계약 확인자는 지정된 Type 및 JsonSerializerOptions 조합에 대해 구성된 JsonTypeInfo 인스턴스를 반환합니다. 확인자가 지정된 입력 유형에 대한 메타데이터를 지원하지 않는 경우 null을 반환할 수 있습니다. 


기본 반사 기반 직렬 변환기에 의해 수행되는 계약 해결은 이제 IJsonTypeInfoResolver를 구현하는 DefaultJsonTypeInfoResolver 클래스를 통해 노출됩니다. 이 클래스를 사용하면 사용자가 사용자 정의 수정으로 기본 반사 기반 해상도를 확장하거나 소스 생성 리졸버와 같은 다른 리졸버와 결합할 수 있습니다.


.NET 7부터 소스 생성에 사용되는 JsonSerializerContext 클래스도 IJsonTypeInfoResolver를 구현합니다. 소스 생성기에 대한 자세한 내용은 System.Text.Json에서 소스 생성을 사용하는 방법을 참조하세요.


JsonSerializerOptions 인스턴스는 새로운 TypeInfoResolver 속성을 사용하여 사용자 지정 확인자로 구성할 수 있습니다.

// configure to use reflection contracts
var reflectionOptions = new JsonSerializerOptions
{
    TypeInfoResolver = new DefaultJsonTypeInfoResolver()
};

// configure to use source generated contracts
var sourceGenOptions = new JsonSerializerOptions
{
    TypeInfoResolver = EntryContext.Default
};

[JsonSerializable(typeof(MyPoco))]
public partial class EntryContext : JsonSerializerContext { }


계약 사용자 지정에 대한 자세한 내용은 [What's new in System.Text.Json in .NET 7] 블로그 게시물을 확인 하세요.


System.Text.Json 유형 계층


System.Text.Json은 이제 사용자 정의 형식 계층 구조의 다형성 직렬화 및 역직렬화를 지원합니다. 이는 새로운 JsonDerivedTypeAttribute로 유형 계층 구조의 기본 클래스를 장식하여 활성화할 수 있습니다. 


[JsonDerivedType(typeof(Derived))]
public class Base
{
    public int X { get; set; }
}

public class Derived : Base
{
    public int Y { get; set; }
}


이 구성은 특히 런타임 유형이 파생인 경우 기본에 대한 다형성 직렬화를 활성화합니다.


Base value = new Derived();
JsonSerializer.Serialize<Base>(value); // { "X" : 0, "Y" : 0 }


페이로드가 기본으로 라운드 트립되기 때문에 이것은 다형성 역직렬화를 활성화하지 않습니다. 

Base value = JsonSerializer.Deserialize<Base>(@"{ ""X"" : 0, ""Y"" : 0 }");
value is Derived; // false


형식 계층 구조에 대한 자세한 내용은 What's new in System.Text.Json in .NET 7 블로그 게시물을 확인 하세요.



.NET SDK


.NET SDK는 이전보다 생산성을 높일 수 있는 새로운 기능을 계속 추가합니다. .NET 7에서는 .NET CLI, 템플릿 작성 및 중앙 위치에서 패키지 관리를 통해 사용자 환경을 개선합니다.


CLI 파서 및 탭 완성


dotnet new 명령에는 사용자가 알고 좋아하는 많은 하위 명령에 대해 보다 일관되고 직관적인 인터페이스가 제공되었습니다. 템플릿 옵션 및 인수의 탭 완성도 지원합니다. 이제 CLI는 사용자가 입력할 때 유효한 인수 및 옵션에 대한 피드백을 제공합니다. 


예를 들어 새로운 도움말 출력은 다음과 같습니다.

 dotnet new --help
Description:
  Template Instantiation Commands for .NET CLI.

Usage:
  dotnet new [<template-short-name> [<template-args>...]] [options]
  dotnet new [command] [options]

Arguments:
  <template-short-name>  A short name of the template to create.
  <template-args>        Template specific options to use.

Options:
  -?, -h, --help  Show command line help.

Commands:
  install <package>       Installs a template package.
  uninstall <package>     Uninstalls a template package.
  update                  Checks the currently installed template packages for update, and install the updates.
  search <template-name>  Searches for the templates on NuGet.org.
  list <template-name>    Lists templates containing the specified template name. If no name is specified, lists all templates.


dotnet CLI는 몇 가지 예를 들면 PowerShell, bash, zsh 및 fish와 같은 인기 있는 셸을 사용하여 꽤 오랫동안 탭 완성을 지원해 왔습니다.


그러나 의미 있는 완성을 구현하는 것은 개별 dotnet 명령에 달려 있습니다. .NET 7의 경우 dotnet new 명령은 탭 완성을 제공하는 방법을 배웠습니다.


 dotnet new angular
angular              grpc                 razor                viewstart            worker               -h
blazorserver         mstest               razorclasslib        web                  wpf                  /?
blazorwasm           mvc                  razorcomponent       webapi               wpfcustomcontrollib  /h
classlib             nugetconfig          react                webapp               wpflib               install
console              nunit                reactredux           webconfig            wpfusercontrollib    list
editorconfig         nunit-test           sln                  winforms             xunit                search
gitignore            page                 tool-manifest        winformscontrollib   --help               uninstall
globaljson           proto                viewimports          winformslib          -?                   update


이것은 새로운 .NET 프로젝트를 생성할 때 어떤 옵션과 인수를 사용할 수 있는지 알 수 있도록 선택하는 데 도움이 될 수 있습니다.


 dotnet new web --dry-run
--dry-run                  --language                 --output                   -lang
--exclude-launch-settings  --name                     --type                     -n
--force                    --no-https                 -?                         -o
--framework                --no-restore               -f                         /?
--help                     --no-update-check          -h                         /h


또한 주어진 명령에 대해 일반적으로 잘못되거나 지원되지 않는 일반적인 옵션 및 인수는 무엇입니까? 대신 현재 버전의 .NET CLI에서 지원되는 항목만 표시됩니다.


 dotnet new blazorserver --auth Individual
Individual     IndividualB2C  MultiOrg       None           SingleOrg      Windows



템플릿 작성


.NET 7은 .NET 템플릿에 제약 조건 개념을 추가합니다. 제약 조건을 사용하면 템플릿이 허용되는 컨텍스트를 정의할 수 있으므로 템플릿 엔진이 dotnet new list와 같은 명령에 표시해야 하는 템플릿을 결정하는 데 도움이 됩니다. 


이 릴리스에서는 세 가지 제약 조건에 대한 지원을 추가했습니다.


  • 운영 체제: 사용자의 운영 체제에 따라 템플릿을 제한합니다 .
  • 템플릿 엔진 호스트: 어떤 호스트가 템플릿 엔진을 실행하는지에 따라 템플릿을 제한합니다. 이것은 일반적으로 .NET CLI 자체이거나 Visual Studio 또는 Mac용 Visual Studio의 새 프로젝트 대화 상자와 같은 포함된 시나리오입니다.
  • 설치된 워크로드: 템플릿을 사용할 수 있으려면 지정된 .NET SDK 워크로드가 설치되어 있어야 합니다.


모든 경우에 이러한 제약 조건을 설명하는 것은 템플릿의 구성 파일에 새 제약 조건 섹션을 추가하는 것만큼 쉽습니다.


 "constraints": {
       "web-assembly": {
           "type": "workload",
           "args": "wasm-tools"
       },
   }


또한 선택 매개변수에 대한 새로운 기능을 추가했습니다. 이것은 사용자가 단일 선택에서 둘 이상의 값을 지정할 수 있는 기능입니다. 

이는 플래그 스타일 열거형을 사용하는 것과 같은 방식으로 사용할 수 있습니다. 


이 매개변수 유형의 일반적인 예는 다음과 같습니다. 

  • 웹 템플릿에서 여러 형태의 인증을 선택합니다.
  • MAUI 템플릿에서 한 번에 여러 대상 플랫폼(iOS, Android, 웹)을 선택합니다.


이 동작을 선택하는 것은 템플릿 구성의 매개변수 정의에 "allowMultipleValues": true 를 추가하는 것만큼 간단합니다. 일단 그렇게 하면 사용자가 선택한 특정 값을 감지하는 데 도움이 되도록 템플릿의 콘텐츠에서 사용할 여러 도우미 기능에 액세스할 수 있습니다. 



중앙 패키지 관리


종속성 관리는 NuGet의 핵심 기능입니다. 단일 프로젝트에 대한 종속성을 쉽게 관리할 수 있습니다. 다중 프로젝트 솔루션의 종속성을 관리하는 것은 크기와 복잡성이 확장되기 시작하면서 어려울 수 있습니다. 


다양한 프로젝트에 대한 공통 종속성을 관리하는 경우 NuGet의 중앙 패키지 관리 기능을 활용하여 단일 위치에서 이 모든 작업을 쉽게 수행할 수 있습니다.


중앙 패키지 관리를 시작하려면 솔루션의 루트에 Directory.Packages.props 파일을 만들고 MSBuild 속성 ManagePackageVersionsCentrally를 true로 설정할 수 있습니다.


내부에서 패키지 ID 및 버전을 정의하는 <PackageVersion /> 요소를 사용하여 솔루션에 필요한 각 패키지 버전을 정의할 수 있습니다.


<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>

  <ItemGroup>
    <PackageVersion Include="Newtonsoft.Json" Version="13.0.1" />
  </ItemGroup>
</Project>


솔루션의 프로젝트 내에서 알고 있고 좋아하는 각각의 <PackageReference /> 구문을 사용할 수 있지만 대신 중앙에서 관리되는 버전을 유추하기 위해 Version 특성이 없습니다.


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

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" />
  </ItemGroup>
</Project>



성능


성능은 모든 .NET 릴리스에서 큰 부분을 차지했습니다. 매년 .NET 팀은 최신 개선 사항에 대한 블로그를 게시합니다. 다음은 최신 성능 게시물의 짧은 설명입니다.


요약: .NET 7은 빠릅니다. 정말 빠릅니다. 성능에 영향을 미치는 1,000개의 PR이 이번 릴리스에서 런타임 및 핵심 라이브러리에 포함되었으며 ASP.NET Core, Windows Forms 및 Entity Framework 등의 모든 개선 사항은 신경 쓰지 마십시오. 지금까지 가장 빠른 .NET입니다. 관리자가 프로젝트를 .NET 7로 업그레이드해야 하는 이유를 묻는다면 "릴리스의 모든 새로운 기능 외에도 .NET 7은 매우 빠릅니다."라고 말할 수 있습니다. – 스티븐 토브


다음은 JIT 컴파일러의 일부 성능 향상에 대한 간략한 요약입니다. 모든 변경 사항에 대해 자세히 알아보려면 .NET 7의 성능 향상을 살펴보십시오 .



온스택 교체(OSR)


OSR(On Stack Replacement)을 사용하면 해당 메서드가 "스택에서" 활성 상태이더라도 런타임에서 메서드 실행 중간에 현재 실행 중인 메서드에 의해 실행되는 코드를 변경할 수 있습니다. 계층화된 컴파일을 보완하는 역할을 합니다.


OSR을 사용하면 장기 실행 메서드가 실행 중간에 더 최적화된 버전으로 전환할 수 있으므로 런타임은 처음에 모든 메서드를 빠르게 JIT한 다음 해당 메서드가 계층화된 컴파일을 통해 자주 호출되거나 OSR을 통해 장기 실행 루프가 있는 경우 더 최적화된 버전으로 전환할 수 있습니다. 


OSR은 시작 시간을 향상시킵니다. 이제 거의 모든 메서드가 초기에 빠른 JIT에 의해 jitted됩니다. 우리는 Avalonia "IL" 스파이와 같은 지팅이 많은 애플리케이션에서 시작 시간이 25% 향상되었음을 확인했으며, 우리가 추적하는 다양한 TechEmpower 벤치마크는 첫 번째 요청까지의 시간이 10-30% 향상되었음을 보여줍니다.


OSR 최초 응답 시간


OSR은 또한 응용 프로그램의 성능을 향상시킬 수 있으며 특히 동적 PGO를 사용하는 응용 프로그램은 루프가 있는 방법이 더 잘 최적화되어 있습니다. 예를 들어 Array2마이크로벤치마크는 OSR이 활성화되었을 때 극적인 개선을 보였습니다. 


OSR Array2 성능



프로필 기반 최적화(PGO)


PGO(Profile-Guided Optimization)는 오랫동안 다양한 언어와 컴파일러에서 사용되었습니다. 기본 아이디어는 다양한 흥미로운 정보를 추적하기 위해 응용 프로그램에 계측을 주입하도록 컴파일러에 요청하여 응용 프로그램을 컴파일하는 것입니다. 


그런 다음 다양한 일반적인 시나리오를 통해 실행하면서 앱을 속도에 맞게 조정하여 앱이 실행될 때 발생하는 상황을 "프로파일링"한 다음 그 결과를 저장합니다. 그런 다음 앱이 다시 컴파일되어 이러한 계측 결과를 컴파일러에 다시 제공하고 예상되는 사용 방식에 맞게 앱을 최적화할 수 있습니다.


PGO에 대한 이러한 접근 방식을 "정적 PGO"라고 합니다. 정보가 실제 배포 전에 수집되기 때문입니다. 이는 .NET이 수년 동안 다양한 형태로 수행해 온 것입니다. .NET에서 흥미로운 개발은 .NET 6에서 도입되었지만 기본적으로 꺼져 있는 "동적 PGO"입니다.


동적 PGO는 계층화된 컴파일을 활용합니다. JIT는 Tier-0 코드를 계측하여 메서드가 호출된 횟수 또는 루프의 경우 루프가 실행된 횟수를 추적합니다. 계층화된 컴파일은 다양한 가능성을 계측할 수 있습니다. 


예를 들어 인터페이스 디스패치의 대상으로 사용되는 구체적인 유형을 정확히 추적한 다음 계층 1에서 가장 일반적인 유형을 예상하도록 코드를 특수화할 수 있습니다(이를 "보호된 탈가상화" 또는 GDV라고 함). ). 


이 작은 예에서 이것을 볼 수 있습니다. 

DOTNET_TieredPGO환경 변수를 1로 설정 한 다음 .NET 7에서 실행합니다.


class Program
{
  static void Main()
  {
    IPrinter printer = new Printer();
    for (int i = 0; ; i++)
    {
      DoWork(printer, i);
    }
  }

  static void DoWork(IPrinter printer, int i)
  {
    printer.PrintIfTrue(I == int.MaxValue);
  }

  interface iPrinter
  {
    void PrintIfTrue(bool condition);
  }

  class Printer : iPrinter
  {
    public void PrintIfTrue(bool condition)
    {
      if (condition) Console.WriteLine"Print”");
    }
  }
}


PGO에서 얻을 수 있는 주요 개선 사항은 이제 .NET 7에서 OSR과 함께 작동한다는 것입니다. 이는 인터페이스 디스패치를 ​​수행하는 핫 실행 메서드가 이러한 가상화/인라이닝 최적화를 얻을 수 있음을 의미합니다.


PGO를 비활성화하면 .NET 6 및 .NET 7에 대해 동일한 성능 처리량을 얻을 수 있습니다.


방법실행 시간평균비율
DelegatePGO
.NET 6.01.665ns1.00
DelegatePGO
.NET 7.01.659ns1.00


그러나 <TieredPGO>true</TieredPGO> 또는 환경 변수 DOTNET_TieredPGO=1을 통해 .csproj에서 동적 PGO를 활성화하면 상황이 바뀝니다. 


.NET 6은 ~14% 더 빠르지만 .NET 7은 ~3배 더 빠릅니다. 


방법실행 시간평균비율
DelegatePGO
.NET 6.01.427.7ns1.00
DelegatePGO
.NET 7.0539.00.38



네이티브 AOT


많은 사람들에게 소프트웨어 맥락에서 "성능"이라는 단어는 처리량에 관한 것입니다. 어떤 것이 얼마나 빨리 실행됩니까? 초당 얼마나 많은 데이터를 처리할 수 있습니까? 초당 몇 개의 요청을 처리할 수 있습니까? 등등. 그러나 성능에는 다른 많은 측면이 있습니다. 얼마나 많은 메모리를 소비합니까? 얼마나 빨리 시작되어 유용한 작업을 수행할 수 있습니까? 디스크에서 얼마나 많은 공간을 사용합니까? 다운로드하는 데 얼마나 걸립니까?


그리고 관련 우려 사항이 있습니다. 이러한 목표를 달성하려면 어떤 종속성이 필요합니까? 이러한 목표를 달성하기 위해 어떤 종류의 작업을 수행해야 하며 이러한 모든 작업이 대상 환경에서 허용됩니까? 이 단락 중 마음에 드는 부분이 있다면 귀하는 현재 .NET 7에서 제공되는 기본 AOT 지원의 대상입니다.


.NET은 오랫동안 AOT 코드 생성을 지원해 왔습니다. 예를 들어 .NET Framework에는 .NET Core 형식이 ngen있고 .NET Core에는 crossgen두 솔루션 모두 IL의 일부가 이미 어셈블리 코드로 컴파일된 표준 .NET 실행 파일을 포함하지만 모든 메서드에 생성된 어셈블리 코드가 있는 것은 아닙니다. 다양한 항목이 생성된 어셈블리 코드를 무효화할 수 있습니다. 모든 네이티브 어셈블리 코드를 로드할 수 있으며 이러한 모든 경우에 런타임은 JIT 컴파일러를 계속 사용합니다. 네이티브 AOT는 다릅니다. 자체적으로 .NET Native의 진화인 CoreRT의 진화이며 JIT가 전혀 없습니다.


빌드를 게시하여 생성된 바이너리는 대상 플랫폼의 플랫폼별 파일 형식(예: Windows의 COFF, Linux의 ELF, macOS의 Mach-O)에서 완전히 독립 실행형 실행 파일이며 표준 이외의 외부 종속성은 없습니다. 해당 플랫폼(예: libc). 그리고 그것은 완전히 기본입니다. IL도 없고, JIT도 없고, 아무것도 없습니다. 필요한 모든 코드는 표준 .NET 앱 및 서비스와 함께 사용되는 동일한 GC와 스레딩 등을 중심으로 서비스를 제공하는 최소 런타임을 포함하여 실행 파일로 컴파일 및/또는 링크됩니다.


이 모든 것은 매우 빠른 시작 시간, 소규모의 완전 독립형 배포, JIT 컴파일러가 허용되지 않는 위치에서 실행할 수 있는 기능(쓰기 가능했던 메모리 페이지를 실행할 수 없기 때문에)과 같은 큰 이점을 제공합니다. 또한 제한 사항이 있습니다. JIT가 없다는 것은 임의 어셈블리(예: Assembly.LoadFile)의 동적 로드가 없고 리플렉션 방출(예: DynamicMethod)이 없다는 것을 의미하며 모든 것이 컴파일되고 앱에 연결되어 있으므로 더 많은 기능이 사용됨을 의미합니다( 또는 사용될 수 있음) 더 큰 배포가 가능합니다. 이러한 제한 사항에도 불구하고 특정 애플리케이션 클래스의 경우 Native AOT는 .NET 7에 매우 흥미롭고 환영할 만한 추가 기능입니다. 


현재 Native AOT는 콘솔 애플리케이션에 중점을 두고 있으므로 콘솔 앱을 만들어 보겠습니다.

dotnet new console -o nativeaotexample


이제 "Hello World" 콘솔 애플리케이션이 있습니다. 기본 AOT를 사용하여 애플리케이션 게시를 활성화하려면 기존 <PropertyGroup>에 다음을 포함하도록 .csproj를 편집합니다. 

<PublishAot>true</PublishAot>


이제 네이티브 AOT를 대상으로 할 수 있도록 앱이 완전히 구성되었습니다. 남은 것은 게시하는 것입니다. Windows x64 런타임 에 게시하려는 경우 다음 명령을 사용할 수 있습니다.

dotnet publish -r win-x64 -c Release


이렇게 하면 출력 게시 디렉터리에 실행 파일이 생성됩니다.

Directory: C:\nativeaotexample\bin\Release\net7.0\win-x64\publish

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           8/27/2022  6:18 PM        3648512 nativeaotexample.exe
-a---           8/27/2022  6:18 PM       14290944 nativeaotexample.pdb


그 ~3.5MB .exe는 실행 파일이고 그 옆에 있는 .pdb는 앱 배포에 필요하지 않은 디버그 정보입니다. 이제 어떤 .NET이 상자에 설치되거나 설치되지 않을 수 있는지에 관계없이 해당 nativeaotexample.exe를 64비트 Windows 시스템에 복사할 수 있으며 앱이 실행됩니다.



.NET 7이 지원됩니다

.NET 릴리스 일정


.NET 7은 Microsoft에서 공식적으로 지원합니다. 18개월 동안 지원되는 STS( Standard Term Support ) 릴리스 로 레이블이 지정되어 있습니다. 


홀수 번호의 .NET 릴리스는 후속 STS 또는 LTS 릴리스 이후 6개월 동안 무료 지원 및 패치를 받는 STS 릴리스입니다. 자세한 내용은 .NET 및 .NET Core 지원 수명 주기 설명서를 참조하세요.



피드백


GitHub 에서 문제를 찬성하고, 개발자 커뮤니티에서 피드백을 제공하고, 커뮤니티의 다른 사람들과 .NET 앱 및 프로젝트를 공유하여 .NET 8 및 향후 릴리스를 구체화할 수 있도록 도와주세요 .

#dotnet7 을 사용하여 생각을 공유하고 .NET 7에 대한 최신 뉴스를 확인하십시오.


지금 .NET 7 다운로드

우리는 다음과 같이 말하고 싶습니다.

.NET 커뮤니티 감사합니다!

.NET은 커뮤니티 없이는 존재할 수 없습니다. .NET 프로젝트는 모든 사람의 독특하고 창의적인 기여를 통한 프로젝트입니다. 이러한 위대한 성취와 관대함은 주변 사람들에 대한 지원과 배려에서 나옵니다. .NET 커뮤니티에 참여하고, 공유하고, 소속되어 주셔서 감사합니다.


.NET 7은 성능, 기능 및 유용성과 같은 기본 사항을 개선하여 개발자 삶의 질을 향상시키는 주요 릴리스입니다. 이러한 새로운 기능과 추가 기능이 계속해서 .NET 플랫폼을 즐겁게 사용하기를 바랍니다.


당신은 무엇을 기다리고 있습니까? 지금 바로 .NET 7을 다운로드 해보세요!!


  • 페이스북으로 공유
  • 트위터로  공유
  • 구글플러스로 공유
  • 카카오톡으로 보내기

댓글목록

등록된 댓글이 없습니다.

그레이프시티 홈페이지를 통해 제품에 대해서 더 자세히 알아 보세요!
홈페이지 바로가기
그레이프시티 홈페이지를 통해 제품에 대해서 더 자세히 알아 보세요!
홈페이지 바로가기
이메일 : sales-kor@grapecity.com | 전화 : 1670-0583 | 경기도 안양시 동안구 시민대로 230, B-703(관양동, 아크로타워) 그레이프시티(주) 대표자 : 허경명 | 사업자등록번호 : 123-84-00981 | 통신판매업신고번호 : 2013-경기안양-00331 Copyright ⓒ 2022 GrapeCity inc.