ASP.NET Core 6.0의 새로운 기능

이 문서에서는 ASP.NET Core 6.0의 가장 중요한 변경 내용을 중점적으로 설명하고 관련 문서의 링크를 제공합니다.

ASP.NET Core MVC 및 Razor 개선 사항

최소 API

최소 API는 최소한의 종속성으로 HTTP API를 만들도록 설계되었습니다. ASP.NET Core에 최소 파일, 기능, 종속성만 포함하려는 앱과 마이크로 서비스에 적합합니다. 자세한 내용은 다음을 참조하세요.

SignalR

SignalR 연결에 대한 장기 실행 활동 태그

SignalR은 새로운 Microsoft.AspNetCore.Http.Features.IHttpActivityFeature.Activity를 사용하여 요청 활동에 http.long_running 태그를 추가합니다. IHttpActivityFeature.ActivityAzure Monitor Application Insights 같은 APM 서비스가 장기 실행 요청 경고를 생성하지 못하도록 SignalR 요청을 필터링하는 데 사용됩니다.

SignalR 성능 향상

  • HubCallerClients를 모든 허브 메서드 호출에서가 아닌 연결당 한 번 할당합니다.
  • SignalRDefaultHubDispatcher.Invoke에서 클로저 할당을 사용하지 않습니다. 클로저 할당을 방지하기 위해 상태가 매개 변수를 통해 로컬 정적 함수에 전달됩니다. 자세한 내용은 이 GitHub 끌어오기 요청을 참조하세요.
  • 서버-클라이언트 스트리밍에서 스트림 항목당 대신 스트림당 단일 StreamItemMessage를 할당합니다. 자세한 내용은 이 GitHub 끌어오기 요청을 참조하세요.

Razor 컴파일러

소스 생성기를 사용하도록 Razor 컴파일러를 업데이트

이제 Razor 컴파일러는 C# 소스 생성기를 기반으로 합니다. 소스 생성기는 컴파일 중에 실행되며 컴파일되는 내용을 검사하여 프로젝트의 나머지 부분과 함께 컴파일되는 추가 파일을 생성합니다. 소스 생성기를 사용하면 Razor 컴파일러가 간소화되고 빌드 시간이 크게 단축됩니다.

Razor 컴파일러가 더 이상 별도의 뷰 어셈블리를 생성하지 않음

이전에는 Razor 컴파일러가 앱에 정의된 생성된 뷰 및 페이지(.cshtml 파일)를 포함하는 별도의 뷰 어셈블리를 생성하는 2단계 컴파일 프로세스를 사용했습니다. 생성된 형식은 public이고 AspNetCore 네임스페이스 아래에 있었습니다.

업데이트된 Razor 컴파일러는 뷰 및 페이지 형식을 주 프로젝트 어셈블리에 빌드합니다. 이러한 형식은 이제 기본적으로 AspNetCoreGeneratedDocument 네임스페이스에서 내부 봉인 상태로 생성됩니다. 이로써 빌드 성능이 향상되고, 단일 파일 배포가 가능하며, 이러한 형식이 핫 다시 로드에 참여할 수 있습니다.

이 변경 사항에 대한 자세한 내용은 GitHub에서 관련 공지를 참조하세요.

ASP.NET Core 성능 및 API 개선

할당을 줄이고 스택 전반의 성능을 향상시키기 위해 많은 사항이 변경되었습니다.

유휴 TLS 연결에 대한 메모리 공간 감소

데이터가 가끔씩만 전송되는 장기 실행 TLS 연결의 경우 .NET 6에서 ASP.NET Core 앱의 메모리 공간을 크게 줄였습니다. 이는 WebSocket 서버와 같은 시나리오의 확장성을 개선하는 데 도움이 될 것입니다. 이러한 결과는 System.IO.Pipelines, SslStream, Kestrel에서 실현한 다수의 기능 덕분에 가능할 수 있었습니다. 다음 섹션에서는 메모리 공간 축소에 기여한 몇 가지 개선 사항을 자세히 설명합니다.

System.IO.Pipelines.Pipe 크기 축소

설정된 모든 연결에 대해 두 개의 파이프가 Kestrel에 할당됩니다.

  • 요청을 위한 앱 측 전송 레이어.
  • 응답을 위한 전송 측 애플리케이션 레이어.

System.IO.Pipelines.Pipe의 크기를 368바이트에서 264바이트로 축소(약 28.2% 감소)하여 연결당 208바이트(파이프당 104바이트)를 절약합니다.

Pool SocketSender

SocketSender 개체(해당 하위 클래스 SocketAsyncEventArgs)는 런타임에 약 350바이트입니다. 연결당 새 SocketSender 개체를 할당하는 대신 풀링할 수 있습니다. 일반적으로 전송은 매우 빠르므로 SocketSender 개체를 풀링할 수 있습니다. 풀링을 사용하면 연결당 오버헤드가 줄어듭니다. 연결당 350바이트를 할당하는 대신 IOQueue당 350바이트만 할당됩니다. 할당은 경합을 방지하기 위해 큐 단위로 이루어집니다. 유휴 연결이 5000개인 WebSocket 서버는 SocketSender 개체에 대해 ~1.75MB(350바이트 * 5000)를 할당하던 것이 이제 ~2.8kb(350바이트 * 8)를 할당하게 되었습니다.

SslStream을 사용한 제로 바이트 읽기

버퍼리스 읽기는 소켓에 사용할 수 있는 데이터가 없는 경우 메모리 풀에서 메모리를 임대하지 않도록 하기 위해 ASP.NET Core에서 채택한 기술입니다. 이 변경 이전에는 유휴 연결이 5000개인 WebSocket 서버는 TLS를 사용하지 않는 경우 최대 200MB가 필요했으며 TLS를 사용하는 경우 ~800MB가 필요했습니다. 이러한 할당 중 일부(연결당 4k)는 SslStream에서 읽기가 완료될 때까지 기다리는 동안 Kestrel이 ArrayPool<T> 버퍼를 유지하기 위한 것입니다. 이러한 연결은 유휴 상태였으므로 읽기가 완료되지 않아도 버퍼를 ArrayPool에 반환하여 ArrayPool이 더 많은 메모리를 할당하도록 했습니다. 나머지 할당은 SslStream 자체를 위한 것이었습니다. TLS 핸드셰이크용 4k 버퍼와 일반 읽기용 32k 버퍼입니다. .NET 6에서 사용자가 SslStream에서 제로 바이트 읽기를 수행하고 사용 가능한 데이터가 없는 경우 SslStream은 내부적으로 래핑된 기본 스트림에 대해 제로 바이트 읽기를 수행합니다. 최상의 경우(유휴 연결), 이러한 변경 덕분에 연결당 40Kb 절감이 발생하지만, 소비자(Kestrel)는 사용하지 않는 버퍼를 유지할 필요 없이 데이터를 사용할 수 있을 때 알림을 받습니다.

PipeReader를 사용한 제로 바이트 읽기

SslStream에서 버퍼리스 읽기가 지원되는 경우 StreamPipeReader로 조정하는 내부 형식인 StreamPipeReader 제로 바이트 읽기를 수행할 수 있는 옵션이 추가되었습니다. Kestrel에서 StreamPipeReader는 기본 SslStreamPipeReader로 조정하는 데 사용됩니다. 따라서 PipeReader에서 이러한 제로 바이트 읽기 의미 체계를 노출해야 했습니다.

이제 다음 API를 사용하여, 제로 바이트 읽기 의미 체계(예: SslStream, NetworkStream 등)를 지원하는 기본 Stream을 통해 제로 바이트 읽기를 지원하는 PipeReader를 만들 수 있습니다.

var reader = PipeReader.Create(stream, new StreamPipeReaderOptions(useZeroByteReads: true));

SlabMemoryPool에서 슬랩 제거

힙의 조각화를 줄이기 위해 Kestrel에서는 메모리 풀의 일부로 128KB 메모리의 슬랩을 할당하는 기술을 채택했습니다. 이러한 슬랩은 Kestrel이 내부적으로 사용하는 4KB 블록으로 추가로 분할됩니다. GC가 이 배열을 재배치하지 않도록 강제로 대형 개체 힙에 할당하려면 슬랩이 85KB보다 커야 했습니다. 그러나 새로운 GC 세대 POH(고정 개체 힙)가 도입되면서 더 이상 슬랩에 블록을 할당하는 것은 의미가 없습니다. Kestrel는 이제 POH에 직접 블록을 할당하여 메모리 풀 관리와 관련된 복잡성을 줄입니다. 이로써 Kestrel이 사용하는 메모리 풀을 더 손쉽게 축소할 수 있다는 점을 비롯해 향후 기능 개선이 더 용이해졌습니다.

IAsyncDisposable 지원

IAsyncDisposable는 이제 컨트롤러, Razor Pages 및 뷰 구성 요소에 사용할 수 있습니다. 팩터리 및 활성기 관련 인터페이스에 비동기 버전이 추가되었습니다.

  • 새 메서드는 동기 버전에 위임하고 Dispose를 호출하는 기본 인터페이스 구현을 제공합니다.
  • 이러한 구현은 기본 구현을 재정의하고 IAsyncDisposable 구현 삭제를 처리합니다.
  • 두 인터페이스가 모두 구현되었을 때 IAsyncDisposable 구현이 IDisposable 구현보다 우선합니다.
  • Extender 컨트롤은 IAsyncDisposable 인스턴스를 지원하기 위해 포함된 새 메서드를 재정의해야 합니다.

IAsyncDisposable은 다음과 함께 사용할 때 유용합니다.

  • 비동기 열거자(예: 비동기 스트림).
  • 해제할 리소스 집약적 I/O 작업이 있는 관리되지 않는 리소스.

이 인터페이스를 구현하는 경우 DisposeAsync 메서드를 사용하여 리소스를 해제합니다.

Utf8JsonWriter를 만들고 사용하는 컨트롤러를 고려합니다. Utf8JsonWriterIAsyncDisposable 리소스입니다.

public class HomeController : Controller, IAsyncDisposable
{
    private Utf8JsonWriter? _jsonWriter;
    private readonly ILogger<HomeController> _logger;

    public HomeController(ILogger<HomeController> logger)
    {
        _logger = logger;
        _jsonWriter = new Utf8JsonWriter(new MemoryStream());
    }

IAsyncDisposableDisposeAsync를 구현해야 합니다.

public async ValueTask DisposeAsync()
{
    if (_jsonWriter is not null)
    {
        await _jsonWriter.DisposeAsync();
    }

    _jsonWriter = null;
}

SignalR C++ 클라이언트용 Vcpkg 포트

Vcpkg는 C 및 C++ 라이브러리용 플랫폼 간 명령줄 패키지 관리자입니다. 최근에 vcpkg에 포트를 추가하여 SignalR C++ 클라이언트에 대한 CMake 네이티브 지원을 구현했습니다. vcpkg는 MSBuild에서도 작동합니다.

Vcpkg가 도구 체인 파일에 포함된 경우 다음 코드 조각을 사용하여 SignalR 클라이언트를 CMake 프로젝트에 추가할 수 있습니다.

find_package(microsoft-signalr CONFIG REQUIRED)
link_libraries(microsoft-signalr::microsoft-signalr)

위의 코드 조각에서 SignalR C++ 클라이언트는 #include를 사용할 준비가 되어 있고 추가 구성 없이 프로젝트에서 사용됩니다. SignalR C++ 클라이언트를 활용하는 C++ 애플리케이션에 대한 전체 예제는 halter73/SignalR-Client-Cpp-Sample 리포지토리를 참조하세요.

Blazor

프로젝트 템플릿 변경 사항

이전 Blazor Server 앱의 _Host.cshtml 파일에 나타난 레이아웃 콘텐츠에 대한 Pages/_Layout.cshtml 파일 사용을 포함하여 Blazor 앱에 대한 몇 가지 프로젝트 템플릿 변경이 이루어졌습니다. 6.0 프로젝트 템플릿에서 앱을 만들거나 프로젝트 템플릿의 ASP.NET Core 참조 원본에 액세스하여 변경 사항을 알아보세요.

Blazor WebAssembly 네이티브 종속성 지원

Blazor WebAssembly 앱은 WebAssembly에서 실행되도록 빌드된 네이티브 종속성을 사용할 수 있습니다. 자세한 내용은 ASP.NET Core Blazor WebAssembly 네이티브 종속성을 참조하세요.

WebAssembly AOT(실시간) 컴파일 및 런타임 다시 링크

Blazor WebAssembly는 .NET 코드를 WebAssembly로 직접 컴파일할 수 있는 AOT(ahead-of-time) 컴파일을 지원합니다. AOT 컴파일을 수행하면 앱 크기가 커지는 대신 런타임 성능이 향상됩니다. .NET WebAssembly 런타임을 다시 링크하면 사용되지 않는 런타임 코드가 삭제되므로 다운로드 속도가 향상됩니다. 자세한 내용은 AOT(Ahead-of-Time) 컴파일런타임 다시 링크를 참조하세요.

미리 렌더링된 상태 유지

Blazor는 앱이 완전히 로드되었을 때 상태를 다시 만들 필요가 없도록 미리 렌더링된 페이지에서 상태 지속을 지원합니다. 자세한 내용은 ASP.NET Core Razor 구성 요소 미리 렌더링 및 통합을 참조하세요.

오류 경계

오류 경계는 UI 수준에서 예외를 처리하는 편리한 방법입니다. 자세한 내용은 ASP.NET Core Blazor 앱의 오류 처리를 참조하세요.

SVG 지원

SVG 내에서 임의의 HTML을 표시하도록 <foreignObject> 요소 요소를 지원합니다. 자세한 내용은 ASP.NET Core Razor 구성 요소를 참조하세요.

JS Interop에서 바이트 배열 전송을 위한 Blazor Server 지원

Blazor는 최적화된 바이트 배열 JS interop을 지원하여 바이트 배열이 Base64로 인코딩/디코딩되는 것을 방지합니다. 자세한 내용은 다음 리소스를 참조하세요.

쿼리 문자열 향상

쿼리 문자열 작업에 대한 지원이 개선되었습니다. 자세한 내용은 ASP.NET Core Blazor 라우팅 및 탐색을 참조하세요.

다중 선택을 위한 바인딩

바인딩은 <input> 요소가 있는 다중 옵션 선택을 지원합니다. 자세한 내용은 다음 리소스를 참조하세요.

헤드(<head>) 콘텐츠 컨트롤

Razor 구성 요소는 페이지의 제목(<title> 요소) 설정과 메타데이터(<meta> 요소) 수정을 포함해 페이지의 HTML <head> 요소 콘텐츠를 수정할 수 있습니다. 자세한 내용은 ASP.NET Core Blazor 앱의 <head> 콘텐츠 제어를 참조하세요.

Angular 및 React 구성 요소 생성

Angular 또는 React와 같은 웹 프레임워크용 Razor 구성 요소에서 프레임워크별 JavaScript 구성 요소를 생성합니다. 자세한 내용은 ASP.NET Core Razor 구성 요소를 참조하세요.

JavaScript에서 구성 요소 렌더링

기존 javascript 앱에 대한 Javascript에서 Razor 구성 요소를 동적으로 렌더링합니다. 자세한 내용은 ASP.NET Core Razor 구성 요소를 참조하세요.

사용자 지정 요소

표준 HTML 인터페이스를 사용하는 사용자 지정 요소를 빌드하는 데 실험적 지원을 사용할 수 있습니다. 자세한 내용은 ASP.NET Core Razor 구성 요소를 참조하세요.

상위 구성 요소에서 구성 요소 제네릭 형식 유추

상위 구성 요소는 새 [CascadingTypeParameter] 특성을 사용하여 형식 매개 변수를 이름으로 하위 항목에 계단식으로 배열할 수 있습니다. 자세한 내용은 ASP.NET Core Razor 구성 요소를 참조하세요.

동적으로 렌더링되는 구성 요소

새 기본 제공 DynamicComponent 구성 요소를 사용하여 형식별로 구성 요소를 렌더링합니다. 자세한 내용은 동적으로 렌더링되는 ASP.NET Core Razor 구성 요소를 참조하세요.

향상된 Blazor 접근성

FocusOnNavigate 구성 요소를 사용하여 한 페이지에서 다른 페이지로 이동한 후 CSS 선택기를 기반으로 UI 포커스를 요소로 설정합니다. 자세한 내용은 ASP.NET Core Blazor 라우팅 및 탐색을 참조하세요.

사용자 지정 이벤트 인수 지원

Blazor는 사용자 지정 이벤트를 사용하여 .NET 이벤트 처리기로 임의 데이터를 전달할 수 있도록 하는 사용자 지정 이벤트 인수를 지원합니다. 자세한 내용은 ASP.NET Core Blazor 이벤트 처리를 참조하세요.

필수 매개 변수

[EditorRequired] 특성을 적용하여 필수 구성 요소 매개 변수를 지정합니다. 자세한 내용은 ASP.NET Core Razor 구성 요소를 참조하세요.

페이지, 뷰 및 구성 요소가 있는 JavaScript 파일의 공동 배치

앱에서 스크립트를 구성하는 편리한 방법으로 페이지, 보기 및 Razor 구성 요소에 대한 JavaScript 파일을 공동 배치합니다. 자세한 내용은 ASP.NET Core Blazor JavaScript 상호 운용성(JS)을 참조하세요.

JavaScript 이니셜라이저

JavaScript 이니셜라이저가 Blazor 앱 로드 전후에 논리를 실행합니다. 자세한 내용은 ASP.NET Core Blazor JavaScript 상호 운용성(JS)을 참조하세요.

JavaScript interop 스트리밍

Blazor는 이제 .NET와 JavaScript 간의 직접 스트리밍 데이터를 지원합니다. 자세한 내용은 다음 리소스를 참조하세요.

제네릭 형식 제약 조건

이제 제네릭 형식 매개 변수가 지원됩니다. 자세한 내용은 ASP.NET Core Razor 구성 요소를 참조하세요.

WebAssembly 배포 레이아웃

배포 레이아웃을 사용하여 제한적 보안 환경에서 Blazor WebAssembly 앱 다운로드가 가능합니다. 자세한 내용은 ASP.NET Core 호스팅 Blazor WebAssembly 앱의 배포 레이아웃을 참조하세요.

새 Blazor 문서

이전 섹션에 설명된 Blazor 기능 외에도 다음과 같은 주제에서 새로운 Blazor 문서를 이용 수 있습니다.

  • ASP.NET Core Blazor 파일 다운로드: 클라이언트로 효율적으로 전송하기 위해 네이티브 byte[] 스트리밍 interop을 사용하여 파일을 다운로드하는 방법을 알아봅니다.
  • ASP.NET Core Blazor에서 이미지 작업: 이미지 데이터를 스트리밍하고 이미지를 미리 보는 방법을 비롯하여 Blazor 앱에서 이미지로 작업하는 방법을 알아봅니다.

.NET MAUI, WPF, Windows Forms로 Blazor Hybrid 앱 구축

Blazor Hybrid를 사용하여 데스크톱 및 모바일 네이티브 클라이언트 프레임워크를 .NET 및 Blazor와 혼합합니다.

  • .NET Multi-platform App UI(.NET MAUI): C#과 XAML을 사용하여 네이티브 모바일 및 데스크톱 앱을 만들기 위한 플랫폼 간 프레임워크입니다.
  • Blazor Hybrid 앱은 WPF(Windows Presentation Foundation) 및 Windows Forms 프레임워크를 사용하여 구축할 수 있습니다.

Important

Blazor Hybrid는 미리 보기 상태이며 최종 릴리스 전에 프로덕션 앱에서 사용해서는 안 됩니다.

자세한 내용은 다음 리소스를 참조하세요.

Kestrel

HTTP/3은 현재 초안 상태이므로 변경될 수 있습니다. ASP.NET Core에서 HTTP/3 지원은 릴리스되지 않았으며 .NET 6에 포함된 미리 보기 기능입니다.

Kestrel은 이제 HTTP/3을 지원합니다. 자세한 내용은 ASP.NET Core Kestrel 웹 서버에서 HTTP/3 사용 및 블로그 항목 .NET 6의 HTTP/3 지원을 참조하세요.

선택한 로깅에 대한 새 Kestrel 로깅 범주

이 변경 이전에는 Kestrel에서 자세한 정보 로깅을 사용할 경우 모든 Kestrel이 Microsoft.AspNetCore.Server.Kestrel 로깅 범주 이름을 공유하므로 엄청난 비용이 들었습니다. Microsoft.AspNetCore.Server.Kestrel은 여전히 사용할 수 있지만 다음과 같은 새로운 하위 범주를 사용하면 로깅을 더 자세히 제어할 수 있습니다.

  • Microsoft.AspNetCore.Server.Kestrel(현재 범주): ApplicationError, ConnectionHeadResponseBodyWrite, ApplicationNeverCompleted, RequestBodyStart, RequestBodyDone, RequestBodyNotEntirelyRead, RequestBodyDrainTimedOut, ResponseMinimumDataRateNotSatisfied, InvalidResponseHeaderRemoved, HeartbeatSlow.
  • Microsoft.AspNetCore.Server.Kestrel.BadRequests: ConnectionBadRequest, RequestProcessingError, RequestBodyMinimumDataRateNotSatisfied.
  • Microsoft.AspNetCore.Server.Kestrel.Connections: ConnectionAccepted, ConnectionStart,ConnectionStop, , ConnectionPause, ConnectionKeepAliveConnectionResume, ConnectionRejected, ConnectionDisconnect, NotAllConnectionsClosedGracefully, NotAllConnectionsAbortedApplicationAbortedConnection.
  • Microsoft.AspNetCore.Server.Kestrel.Http2: Http2ConnectionError, Http2ConnectionClosing,Http2ConnectionClosed, , Http2StreamError, HPackDecodingErrorHttp2StreamResetAbort, HPackEncodingError, Http2FrameReceivedHttp2FrameSending, Http2MaxConcurrentStreamsReached.
  • Microsoft.AspNetCore.Server.Kestrel.Http3: Http3ConnectionError,Http3ConnectionClosing, , Http3StreamAbortHttp3ConnectionClosed, Http3FrameReceived. Http3FrameSending

기존 규칙은 계속 작동하지만 이제 보다 세부적으로 적용할 규칙을 선택할 수 있습니다. 예를 들어 잘못된 요청에 대한 Debug 로깅을 설정하는 경우 관찰 오버헤드가 크게 줄어들고 다음 구성으로 설정할 수 있습니다.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.AspNetCore.Kestrel.BadRequests": "Debug"
    }
  }

로그 필터링은 일치 범주 접두사가 가장 긴 규칙을 적용합니다. 자세한 내용은 필터링 규칙 적용 방식을 참조하세요.

EventSource 이벤트를 통해 KestrelServerOptions 방출

세부 정보 표시 EventLevel.LogAlways가 설정된 경우 KestrelEventSource는 JSON 직렬화된 KestrelServerOptions를 포함하는 새 이벤트를 내보냅니다. 이 이벤트를 사용하면 수집된 추적을 분석할 때 서버 동작을 더 쉽게 추론할 수 있습니다. 다음 JSON은 이벤트 페이로드의 한 예입니다.

{
  "AllowSynchronousIO": false,
  "AddServerHeader": true,
  "AllowAlternateSchemes": false,
  "AllowResponseHeaderCompression": true,
  "EnableAltSvc": false,
  "IsDevCertLoaded": true,
  "RequestHeaderEncodingSelector": "default",
  "ResponseHeaderEncodingSelector": "default",
  "Limits": {
    "KeepAliveTimeout": "00:02:10",
    "MaxConcurrentConnections": null,
    "MaxConcurrentUpgradedConnections": null,
    "MaxRequestBodySize": 30000000,
    "MaxRequestBufferSize": 1048576,
    "MaxRequestHeaderCount": 100,
    "MaxRequestHeadersTotalSize": 32768,
    "MaxRequestLineSize": 8192,
    "MaxResponseBufferSize": 65536,
    "MinRequestBodyDataRate": "Bytes per second: 240, Grace Period: 00:00:05",
    "MinResponseDataRate": "Bytes per second: 240, Grace Period: 00:00:05",
    "RequestHeadersTimeout": "00:00:30",
    "Http2": {
      "MaxStreamsPerConnection": 100,
      "HeaderTableSize": 4096,
      "MaxFrameSize": 16384,
      "MaxRequestHeaderFieldSize": 16384,
      "InitialConnectionWindowSize": 131072,
      "InitialStreamWindowSize": 98304,
      "KeepAlivePingDelay": "10675199.02:48:05.4775807",
      "KeepAlivePingTimeout": "00:00:20"
    },
    "Http3": {
      "HeaderTableSize": 0,
      "MaxRequestHeaderFieldSize": 16384
    }
  },
  "ListenOptions": [
    {
      "Address": "https://127.0.0.1:7030",
      "IsTls": true,
      "Protocols": "Http1AndHttp2"
    },
    {
      "Address": "https://[::1]:7030",
      "IsTls": true,
      "Protocols": "Http1AndHttp2"
    },
    {
      "Address": "http://127.0.0.1:5030",
      "IsTls": false,
      "Protocols": "Http1AndHttp2"
    },
    {
      "Address": "http://[::1]:5030",
      "IsTls": false,
      "Protocols": "Http1AndHttp2"
    }
  ]
}

거부된 HTTP 요청에 대한 새 DiagnosticSource 이벤트

Kestrel는 이제 서버 레이어에서 거부된 HTTP 요청에 대한 새 DiagnosticSource 이벤트를 내보냅니다. 이 변경 이전에는 이러한 거부된 요청을 관찰할 방법이 없었습니다. 새 DiagnosticSource 이벤트 Microsoft.AspNetCore.Server.Kestrel.BadRequest에는 요청을 거부한 이유를 검사하는 데 사용할 수 있는 IBadRequestExceptionFeature가 포함되어 있습니다.

using Microsoft.AspNetCore.Http.Features;
using System.Diagnostics;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var diagnosticSource = app.Services.GetRequiredService<DiagnosticListener>();
using var badRequestListener = new BadRequestEventListener(diagnosticSource,
    (badRequestExceptionFeature) =>
{
    app.Logger.LogError(badRequestExceptionFeature.Error, "Bad request received");
});
app.MapGet("/", () => "Hello world");

app.Run();

class BadRequestEventListener : IObserver<KeyValuePair<string, object>>, IDisposable
{
    private readonly IDisposable _subscription;
    private readonly Action<IBadRequestExceptionFeature> _callback;

    public BadRequestEventListener(DiagnosticListener diagnosticListener,
                                   Action<IBadRequestExceptionFeature> callback)
    {
        _subscription = diagnosticListener.Subscribe(this!, IsEnabled);
        _callback = callback;
    }
    private static readonly Predicate<string> IsEnabled = (provider) => provider switch
    {
        "Microsoft.AspNetCore.Server.Kestrel.BadRequest" => true,
        _ => false
    };
    public void OnNext(KeyValuePair<string, object> pair)
    {
        if (pair.Value is IFeatureCollection featureCollection)
        {
            var badRequestFeature = featureCollection.Get<IBadRequestExceptionFeature>();

            if (badRequestFeature is not null)
            {
                _callback(badRequestFeature);
            }
        }
    }
    public void OnError(Exception error) { }
    public void OnCompleted() { }
    public virtual void Dispose() => _subscription.Dispose();
}

자세한 내용은 Kestrel의 로깅 및 진단을 참조하세요.

수락 소켓에서 ConnectionContext 만들기

SocketConnectionContextFactory를 사용하면 수락된 소켓에서 ConnectionContext를 만들 수 있습니다. 그러므로 SocketConnection에서 이루어지는 모든 성능 작업 및 풀링에 대한 손실 없이 사용자 지정 소켓 기반 IConnectionListenerFactory를 빌드할 수 있습니다.

SocketConnectionContextFactory를 사용하는 방법을 보여주는 이 사용자 지정 IConnectionListenerFactory 예제를 참조하세요.

Kestrel은 Visual Studio용 기본 시작 프로필입니다.

모든 새 dotnet 웹 프로젝트의 기본 시작 프로필은 Kestrel입니다. Kestrel 시작이 훨씬 더 빠르며 앱을 개발하는 동안 응답성이 더 뛰어난 환경을 만들어 줍니다.

IIS Express는 여전히 Windows 인증 또는 포트 공유와 같은 시나리오의 시작 프로필로 사용할 수 있습니다.

Kestrel용 Localhost 포트는 임의입니다.

자세한 내용은 이 문서의 Kestrel용 템플릿 생성 포트를 참조하세요.

인증 및 권한 부여

인증 서버

.NET 3부터 .NET 5까지는 SPA 및 Blazor 애플리케이션에 대한 JWT 토큰 발행을 지원하는 템플릿의 일부로 IdentityServer4를 사용했습니다. 이제 템플릿에서 Duende Identity Server를 사용합니다.

ID 모델을 확장하고 기존 프로젝트를 업데이트하는 경우 코드의 네임스페이스를 IdentityServer4.IdentityServer에서 Duende.IdentityServer로 업데이트하고 해당 마이그레이션 지침을 따라야 합니다.

Duende Identity Server 라이선스 모델이 상호 라이선스로 변경되어 프로덕션 환경에서 상업적으로 사용하는 경우 라이선스 비용이 필요할 수 있습니다. 자세한 내용은 Duende 라이선스 페이지를 참조하세요.

지연된 클라이언트 인증서 협상

이제 개발자는 HttpsConnectionAdapterOptionsClientCertificateMode.DelayCertificate를 지정하여 지연된 클라이언트 인증서 협상을 사용할 수 있습니다. HTTP/2는 지연된 인증서 재협상을 금지하므로 이 기능은 HTTP/1.1 연결에서만 작동합니다. 이 API의 호출자는 클라이언트 인증서를 요청하기 전에 요청 본문을 버퍼링해야 합니다.

using Microsoft.AspNetCore.Server.Kestrel.Https;
using Microsoft.AspNetCore.WebUtilities;

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseKestrel(options =>
{
    options.ConfigureHttpsDefaults(adapterOptions =>
    {
        adapterOptions.ClientCertificateMode = ClientCertificateMode.DelayCertificate;
    });
});

var app = builder.Build();
app.Use(async (context, next) =>
{
    bool desiredState = GetDesiredState();
    // Check if your desired criteria is met
    if (desiredState)
    {
        // Buffer the request body
        context.Request.EnableBuffering();
        var body = context.Request.Body;
        await body.DrainAsync(context.RequestAborted);
        body.Position = 0;

        // Request client certificate
        var cert = await context.Connection.GetClientCertificateAsync();

        //  Disable buffering on future requests if the client doesn't provide a cert
    }
    await next(context);
});


app.MapGet("/", () => "Hello World!");
app.Run();

이제 새 OnCheckSlidingExpiration을 사용하여 Cookie 인증 슬라이딩 만료를 사용자 지정하거나 표시하지 않을 수 있습니다. 예를 들어 인증 세션에 영향을 주지 않고 서버를 주기적으로 ping해야 하는 단일 페이지 앱에서 이 이벤트를 사용할 수 있습니다.

기타

핫 다시 로드

핫 다시 로드를 사용하여 앱 상태를 손실하지 않고 실행 중인 앱의 UI 및 코드를 신속하게 업데이트할 수 있어 개발자 환경의 속도와 생산성이 향상됩니다. 자세한 내용은 ASP.NET Core용 NET 핫 다시 로드 지원.NET 핫 다시 로드 진행 상황 및 Visual Studio 2022 하이라이트에 대한 업데이트를 참조하세요.

향상된 SPA(단일 페이지 앱) 템플릿

Angular 및 React용 ASP.NET Core 프로젝트 템플릿을 업데이트하여 최신 프런트 엔드 웹 개발의 일반적인 패턴에 긴밀히 부합하고 보다 유연하게 단일 페이지 앱에 대한 향상된 패턴을 사용할 수 있게 되었습니다.

이전에는 Angular 및 React용 ASP.NET Core 템플릿은 개발 중에 특수 미들웨어를 사용하여 프런트 엔드 프레임워크용 개발 서버를 시작하고 요청을 ASP.NET Core 개발 서버로 프록시했습니다. 프런트 엔드 개발 서버를 시작하기 위한 논리는 해당 프런트 엔드 프레임워크에 대한 명령줄 인터페이스에만 적용되었습니다. 이 패턴을 사용하여 추가 프런트 엔드 프레임워크를 지원하는 것은 ASP.NET Core 논리를 추가하는 것을 의미했습니다.

.NET 6에서 업데이트된 Angular 및 React용 ASP.NET Core 템플릿은 이러한 상황을 전환하고 대부분의 최신 프런트 엔드 프레임워크의 개발 서버에서 기본 제공 프록시 지원을 활용합니다. ASP.NET Core 앱이 시작되면 이전처럼 프런트 엔드 개발 서버가 시작되지만 개발 서버는 백 엔드 ASP.NET Core 프로세스에 대한 요청을 프록시하도록 구성됩니다. 프록시를 설정하는 모든 프런트 엔드 관련 구성은 ASP.NET Core가 아닌 앱의 일부입니다. 다른 프런트 엔드 프레임워크와 함께 작동하도록 ASP.NET Core 프로젝트를 설정하는 것은 이제 간단합니다. 선택한 프레임워크가 Angular 및 React 템플릿에 설정된 패턴을 사용하여 ASP.NET Core 백 엔드에 프록시하도록 프런트 엔드 개발 서버를 설정합니다.

ASP.NET Core 앱의 시작 코드에는 더 이상 단일 페이지 앱 관련 논리가 필요하지 않습니다. 개발 중에 프런트 엔드 개발 서버를 시작하는 논리는 런타임에 새 Microsoft.AspNetCore.SpaProxy 패키지에 의해 앱에 삽입됩니다. 대체 라우팅은 SPA별 미들웨어 대신 엔드포인트 라우팅을 사용하여 처리됩니다.

이 패턴을 따르는 템플릿은 Visual Studio 또는 명령줄에서 dotnet run을 사용하여 단일 프로젝트로 실행될 수 있습니다. 앱이 게시되면 ClientApp 폴더의 프런트 엔드 코드가 이전처럼 빌드되고 호스트 ASP.NET Core 앱의 웹 루트에 수집되어 정적 파일로 제공됩니다. 템플릿에 포함된 스크립트는 ASP.NET Core 개발 인증서를 통해 HTTPS를 사용하도록 프런트 엔드 개발 서버를 구성합니다.

.NET 6의 HTTP/3 지원(초안)

HTTP/3은 현재 초안 상태이므로 변경될 수 있습니다. ASP.NET Core에서 HTTP/3 지원은 릴리스되지 않았으며 .NET 6에 포함된 미리 보기 기능입니다.

.NET 6의 HTTP/3 지원 블로그 항목을 참조하세요.

Null 허용 참조 형식 주석

ASP.NET Core 6.0 소스 코드의 일부에는 Null 허용 여부 주석이 적용되었습니다.

C# 8의 새로운 Null 허용 기능을 활용하여 ASP.NET Core 참조 형식 처리에 추가로 컴파일 시간 안전을 제공할 수 있습니다. 예를 들면 null 참조 예외로부터 보호입니다. Null 허용 주석 사용을 옵트인한 프로젝트에는 ASP.NET Core API에서 새 빌드 시간 경고가 표시될 수 있습니다.

Null 허용 참조 형식을 사용하도록 설정하려면 프로젝트 파일에 다음 속성을 추가합니다.

<PropertyGroup>
    <Nullable>enable</Nullable>
</PropertyGroup>

자세한 내용은 nullable 참조 형식을 참조하세요.

소스 코드 분석

애플리케이션 코드에서 잘못된 미들웨어 구성 또는 순서, 라우팅 충돌 등과 같은 문제를 검사하는 여러 .NET 컴파일러 플랫폼 분석기가 추가되었습니다. 자세한 내용은 ASP.NET Core 앱의 코드 분석을 참조하세요.

웹앱 템플릿 개선

웹앱 템플릿:

  • 새로운 최소 호스팅 모델을 사용합니다.
  • 앱을 만드는 데 필요한 파일 수와 코드 줄이 대폭 줄어듭니다. 예를 들어 ASP.NET Core 빈 웹앱은 4줄의 코드가 있는 C# 파일을 하나 만들며 이는 완전한 앱입니다.
  • Startup.csProgram.cs를 단일 Program.cs 파일로 통합합니다.
  • 최상위 문을 사용하여 앱에 필요한 코드를 최소화합니다.
  • 전역 using 지시문을 사용하여 필요한 using의 줄 수를 없애거나 최소화합니다.

Kestrel용 템플릿 생성 포트

프로젝트를 만드는 동안 Kestrel 웹 서버가 사용할 임의 포트가 할당됩니다. 임의 포트는 동일한 컴퓨터에서 여러 프로젝트가 실행되는 경우 포트 충돌을 최소화하는 데 도움이 될 수 있습니다.

프로젝트를 만들 때 5000-5300 사이의 임의의 HTTP 포트와 7000-7300 사이의 임의의 HTTPS 포트가 생성된 Properties/launchSettings.json 파일에 지정됩니다. 파일에서 포트를 Properties/launchSettings.json 변경할 수 있습니다. 포트를 지정하지 않으면 Kestrel이 기본적으로 HTTP 5000 및 HTTPS 5001 포트를 사용합니다. 자세한 내용은 ASP.NET Core Kestrel 웹 서버에 대한 엔드포인트 구성을 참조하세요.

새 로깅 기본값

다음 변경 사항은 appsettings.jsonappsettings.Development.json 모두에 적용되었습니다.

- "Microsoft": "Warning",
- "Microsoft.Hosting.Lifetime": "Information"
+ "Microsoft.AspNetCore": "Warning"

"Microsoft": "Warning"에서 "Microsoft.AspNetCore": "Warning"으로 변경됨에 따라 Microsoft.AspNetCore제외한Microsoft 네임스페이스의 모든 정보 메시지가 로그됩니다. 예를 들어 Microsoft.EntityFrameworkCore는 이제 정보 수준에서 로그됩니다.

개발자 예외 페이지 미들웨어를 자동으로 추가

개발 환경에서는 DeveloperExceptionPageMiddleware가 기본적으로 추가됩니다. 더 이상 다음 코드를 웹 UI 앱에 추가할 필요가 없습니다.

if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

HttpSysServer에서 Latin1 인코딩된 요청 헤더 지원

HttpSysServer는 이제 Latin1로 인코딩된 요청 헤더의 디코딩을 지원합니다. 이렇게 하려면 HttpSysOptions에서 UseLatin1RequestHeaders 속성을 true로 설정합니다.

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseHttpSys(o => o.UseLatin1RequestHeaders = true);

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();

ASP.NET Core 모듈 로그에 타임스탬프 및 PID를 포함

IIS용 ANCM(ASP.NET Core 모듈) ANCM 향상된 진단 로그에는 로그를 내보내는 프로세스의 타임스탬프 및 PID가 포함됩니다. 로깅 타임스탬프 및 PID를 사용하면 여러 IIS 작업자 프로세스가 실행 중일 때 IIS에서 중첩 프로세스가 다시 시작하는 문제를 쉽게 진단할 수 있습니다.

결과 로그는 아래 샘플 출력과 비슷합니다.

[2021-07-28T19:23:44.076Z, PID: 11020] [aspnetcorev2.dll] Initializing logs for 'C:\<path>\aspnetcorev2.dll'. Process Id: 11020. File Version: 16.0.21209.0. Description: IIS ASP.NET Core Module V2. Commit: 96475a2acdf50d7599ba8e96583fa73efbe27912.
[2021-07-28T19:23:44.079Z, PID: 11020] [aspnetcorev2.dll] Resolving hostfxr parameters for application: '.\InProcessWebSite.exe' arguments: '' path: 'C:\Temp\e86ac4e9ced24bb6bacf1a9415e70753\'
[2021-07-28T19:23:44.080Z, PID: 11020] [aspnetcorev2.dll] Known dotnet.exe location: ''

IIS에 대해 사용되지 않은 수신 버퍼 크기를 구성 가능

이전에 IIS 서버는 사용되지 않은 요청 본문을 64KiB만 버퍼링했습니다. 64KiB 버퍼링 때문에 읽기가 이 최대 크기로 제한되었습니다. 이는 업로드와 같은 대용량 본문에서 성능에 영향을 줍니다. .NET 6에서는 기본 버퍼 크기가 64KiB에서 1MiB로 변경되어 대용량 업로드를 위한 처리량이 향상됩니다. 테스트 결과를 보면, 9초가 걸리던 700MiB 업로드가 이제 2.5초밖에 걸리지 않습니다.

버퍼 크기 확대의 단점은 앱이 요청 본문을 빠르게 읽지 못하는 경우 요청당 메모리 소비가 증가한다는 것입니다. 따라서 기본 버퍼 크기를 변경한 외에도 버퍼 크기 구성이 가능해졌으므로 애플리케이션에서 워크로드에 따라 버퍼 크기를 구성할 수 있습니다.

뷰 구성 요소 태그 도우미

다음 코드와 같이 선택적 매개 변수를 사용하는 뷰 구성 요소를 고려합니다.

class MyViewComponent
{
    IViewComponentResult Invoke(bool showSomething = false) { ... }
}

ASP.NET Core 6에서는 showSomething 매개 변수의 값을 지정하지 않아도 태그 도우미를 호출할 수 있습니다.

<vc:my />

Angular 템플릿을 Angular12로 업데이트

Angular용 ASP.NET Core 6.0 템플릿은 이제 Angular 12를 사용합니다.

React 템플릿은 React 17로 업데이트되었습니다.

Json.NET 출력 포맷터에서 디스크에 쓰기 전에 버퍼 임계값 구성 가능

참고: 호환성을 위해 Newtonsoft.Json 직렬 변환기가 필요한 경우를 제외하고 System.Text.Json 출력 포맷터를 사용하는 것이 좋습니다. System.Text.Json 직렬 변환기는 완전 async이며 더 큰 페이로드에서도 효율적으로 작동합니다.

기본적으로 Newtonsoft.Json 출력 포맷터는 디스크에 버퍼링하기 전에 메모리에서 최대 32KiB까지 응답을 버퍼링합니다. 이는 동기 IO를 수행하지 않기 위한 것입니다. 그럴 경우 스레드 고갈 및 애플리케이션 교착 같은 부작용이 발생할 수 있습니다. 그러나 응답이 32KiB보다 크면 상당한 디스크 I/O가 발생합니다. 이제 디스크에 버퍼링하기 전에 MvcNewtonsoftJsonOptions.OutputFormatterMemoryBufferThreshold 속성을 통해 메모리 임계값을 구성할 수 있습니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages()
            .AddNewtonsoftJson(options =>
            { 
                options.OutputFormatterMemoryBufferThreshold = 48 * 1024;
            });

var app = builder.Build();

자세한 내용은 이 GitHub 끌어오기 요청NewtonsoftJsonOutputFormatterTest.cs 파일을 참조하세요.

HTTP 헤더에 대한 get 및 set 속도 향상

IHeaderDictionary에 대한 속성으로 Microsoft.Net.Http.Headers.HeaderNames에서 사용할 수 있는 모든 공통 헤더를 노출하는 새 API를 추가했습니다. 이들 API는 사용하기가 더 쉬어졌습니다. 예를 들어 다음 코드의 인라인 미들웨어는 새 API를 사용하여 요청 헤더 및 응답 헤더를 가져오고 설정합니다.

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Use(async (context, next) =>
{
    var hostHeader = context.Request.Headers.Host;
    app.Logger.LogInformation("Host header: {host}", hostHeader);
    context.Response.Headers.XPoweredBy = "ASP.NET Core 6.0";
    await next.Invoke(context);
    var dateHeader = context.Response.Headers.Date;
    app.Logger.LogInformation("Response date: {date}", dateHeader);
});

app.Run();

구현된 헤더의 경우 get 및 set 접근자는 필드로 직접 이동하고 조회를 우회하여 구현됩니다. 구현되지 않은 헤더의 경우 접근자는 구현된 헤더에 대한 초기 Dictionary<string, StringValues> 조회를 무시하고 직접 조회를 수행할 수 있습니다. 조회 결과를 방지하면 두 시나리오 모두 액세스 속도가 더 빨라집니다.

비동기 스트리밍

이제 ASP.NET Core는 JSON 포맷터의 컨트롤러 작업 및 응답에서 비동기 스트리밍을 지원합니다. 작업에서 IAsyncEnumerable을 반환하면 응답 콘텐츠가 전송되기 전에 더 이상 메모리에 버퍼링되지 않습니다. 버퍼링을 사용하면 비동기적으로 열거할 수 있는 대규모 데이터 세트를 반환할 때 메모리 사용을 줄일 수 있습니다.

Entity Framework Core는 데이터베이스 쿼리를 위한 IAsyncEnumerable 구현을 제공합니다. .NET 6의 ASP.NET Core에서 향상된 IAsyncEnumerable 지원 기능을 사용하면 EF Core를 ASP.NET Core에서 보다 효율적으로 사용할 수 있습니다. 예를 들어 다음 코드는 응답을 보내기 전에 더 이상 제품 데이터를 메모리로 버퍼링하지 않습니다.

public IActionResult GetMovies()
{
    return Ok(_context.Movie);
}

그러나 EF Core에서 지연 로드를 사용하는 경우 데이터를 열거하는 동안 동시 쿼리 실행으로 인해 이 새로운 동작에 오류가 발생할 수 있습니다. 앱은 데이터를 버퍼링하여 이전 동작으로 되돌릴 수 있습니다.

public async Task<IActionResult> GetMovies2()
{
    return Ok(await _context.Movie.ToListAsync());
}

이러한 동작 변경에 대한 자세한 내용은 관련 공지를 참조하세요.

HTTP 로깅 미들웨어

HTTP 로깅은 헤더 및 전체 본문을 포함하여 HTTP 요청과 HTTP 응답에 대한 정보를 로그하는 새로운 기본 제공 미들웨어입니다.

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();
app.UseHttpLogging();

app.MapGet("/", () => "Hello World!");

app.Run();

위의 코드를 사용하여 /로 이동하면 다음 출력과 비슷한 정보가 로그됩니다.

info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
      Request:
      Protocol: HTTP/2
      Method: GET
      Scheme: https
      PathBase: 
      Path: /
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
      Accept-Encoding: gzip, deflate, br
      Accept-Language: en-US,en;q=0.9
      Cache-Control: max-age=0
      Connection: close
      Cookie: [Redacted]
      Host: localhost:44372
      User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30
      sec-ch-ua: [Redacted]
      sec-ch-ua-mobile: [Redacted]
      sec-ch-ua-platform: [Redacted]
      upgrade-insecure-requests: [Redacted]
      sec-fetch-site: [Redacted]
      sec-fetch-mode: [Redacted]
      sec-fetch-user: [Redacted]
      sec-fetch-dest: [Redacted]
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
      Response:
      StatusCode: 200
      Content-Type: text/plain; charset=utf-8

위의 출력은 다음 appsettings.Development.json 파일로 사용하도록 설정되었습니다.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
    }
  }
}

HTTP 로깅은 다음의 로그를 제공합니다.

  • HTTP 요청 정보
  • 일반 속성
  • 헤더
  • 본문
  • HTTP 응답 정보

HTTP 로깅 미들웨어를 구성하려면 HttpLoggingOptions를 지정합니다.

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
    // Customize HTTP logging.
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("My-Request-Header");
    logging.ResponseHeaders.Add("My-Response-Header");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;
});

var app = builder.Build();
app.UseHttpLogging();

app.MapGet("/", () => "Hello World!");

app.Run();

IConnectionSocketFeature

IConnectionSocketFeature 요청 기능은 현재 요청과 연결된 기본 수락 소켓에 대한 액세스를 제공합니다. 이 소켓은 HttpContextFeatureCollection을 통해 액세스할 수 있습니다.

예를 들어 다음 앱은 수락된 소켓에서 LingerState 속성을 설정합니다.

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureEndpointDefaults(listenOptions => listenOptions.Use((connection, next) =>
    {
        var socketFeature = connection.Features.Get<IConnectionSocketFeature>();
        socketFeature.Socket.LingerState = new LingerOption(true, seconds: 10);
        return next();
    }));
});
var app = builder.Build();
app.MapGet("/", (Func<string>)(() => "Hello world"));
await app.RunAsync();

Razor의 제네릭 형식 제약 조건

Razor에서 @typeparam 지시문을 사용하여 제네릭 형식 매개 변수를 정의할 때 이제 표준 C# 구문을 사용하여 제네릭 형식 제약 조건을 지정할 수 있습니다.

크기가 작아진 SignalR, Blazor Server 및 MessagePack 스크립트

SignalR, MessagePack 및 Blazor Server 스크립트는 이제 크기가 상당히 줄어 다운로드 용량이 감소하고, 브라우저에 의한 JavaScript 구문 분석 및 컴파일이 축소되고 시작이 더 빨라졌습니다. 크기 축소:

  • signalr.js: 70%
  • blazor.server.js: 45%

스크립트 크기 축소는 커뮤니티 멤버 Ben Adams의 기여 덕분입니다. 크기 축소에 대한 자세한 내용은 Ben의 GitHub 끌어오기 요청을 참조하세요.

Redis 프로파일링 세션 사용

커뮤니티 멤버 Gabriel Lucaci의 기여로 Redis 프로파일링 세션에서 Microsoft.Extensions.Caching.StackExchangeRedis를 사용할 수 있습니다.

using StackExchange.Redis.Profiling;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddStackExchangeRedisCache(options =>
{
    options.ProfilingSession = () => new ProfilingSession();
});

자세한 내용은 StackExchange.Redis 프로파일링을 참조하세요.

IIS의 섀도 복사

애플리케이션 어셈블리 섀도 복사에 대한 지원을 추가하기 위해 실험적 기능을 IIS용 ANCM(ASP.NET Core 모듈)에 추가했습니다. 현재 .NET는 Windows에서 실행되는 경우 애플리케이션 이진 파일을 잠가 앱이 실행 중일 때 이진 파일을 대체할 수 없게 합니다. 권장 사항은 앱 오프라인 파일을 사용하는 것이지만, 일부 시나리오(예: FTP 배포)에서는 이것이 불가능하다는 것을 Microsoft도 인지하고 있습니다.

이러한 시나리오에서는 ASP.NET Core 모듈 처리기 설정을 사용자 지정하여 섀도 복사를 사용하도록 설정합니다. 대부분의 경우 ASP.NET Core 앱에는 수정할 수 있는 web.config 체크 인 소스 컨트롤이 없습니다. ASP.NET Core에서 web.config는 일반적으로 SDK에 의해 생성됩니다. 다음 샘플 web.config를 사용하여 시작할 수 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <!-- To customize the asp.net core module uncomment and edit the following section. 
  For more info see https://go.microsoft.com/fwlink/?linkid=838655 -->

  <system.webServer>
    <handlers>
      <remove name="aspNetCore"/>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified"/>
    </handlers>
    <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout">
      <handlerSettings>
        <handlerSetting name="experimentalEnableShadowCopy" value="true" />
        <handlerSetting name="shadowCopyDirectory" value="../ShadowCopyDirectory/" />
        <!-- Only enable handler logging if you encounter issues-->
        <!--<handlerSetting name="debugFile" value=".\logs\aspnetcore-debug.log" />-->
        <!--<handlerSetting name="debugLevel" value="FILE,TRACE" />-->
      </handlerSettings>
    </aspNetCore>
  </system.webServer>
</configuration>

IIS의 섀도 복사는 실험적 기능으로, ASP.NET Core의 일부로 포함된다는 보장이 없습니다. 이 GitHub 이슈에서 IIS 섀도 복사에 대한 피드백을 남겨 주세요.

추가 리소스