2020년 11월, .NET 5.0이 출시되었다. 이는 .NET 생태계 통합 이후의 첫 번째 버전으로, LTS(Long-Term Support)는 아니지만 실제 운영 환경에서 안정적으로 사용 가능하다. Microsoft는 프리뷰 단계부터 Bing.com과 dot.net에서 .NET 5를 운영하며 검증했으며, 기존 .NET Core 버전에서의 원활한 업그레이드 경로를 제공한다.
핵심 개선 사항
생산 환경 검증
Bing.com과 dot.net에서 수 개월간의 실제 운영 테스트를 통해 안정성이 검증되었다.
성능 최적화
다음 영역에서 상당한 성능 향상이 이루어졌다:
- 가비지 컬렉션(GC) 및 JIT 컴파일러
- 정규 표현식 엔진
- 비동기/병렬 처리
- LINQ 및 컬렉션
- 네트워크 스택
- JSON 직렬화
- gRPC
언어 기능 강화
C# 9와 F# 5가 포함되어 있으며, 특히 C# 9의 record, 최상위 문장, 패턴 매칭 개선 등이 주목할 만하다.
플랫폼 통합 비전
Microsoft는 단일 .NET 플랫폼을 통해 Windows, Linux, macOS, iOS, Android, tvOS, watchOS, WebAssembly 등 다양한 플랫폼을 지원하는 것을 목표로 한다. 이를 위해 핵심 코드베이스를 통합 저장소로 모았으며, Mono 런타임의 상당 부분도 포함되었다.
Blazor WebAssembly가 대표적인 사례이다. 서버와 클라이언트 모두 동일한 List<T> 등의 라이브러리 코드를 공유한다.
.NET Framework 현황
.NET Framework 4.8이 최종 버전이며, 새로운 기능 추가는 중단되었다. Windows의 지속적인 지원은 유지되나, .NET의 미래는 통합 플랫폼에 있다.
마이그레이션 권장 사항:
- 클라이언트 애플리케이션: Windows Forms, WPF 지원
- 서버 플리케이션: ASP.NET Core로 전환 필요
- Web Forms: Blazor로 대체 권장
- WCF/Workflow: 커뮤니티 프로젝트 활용
C# 9 언어 혁신
최상위 문장 (Top-level Statements)
기존의 Main 메서드 없이 바로 코드를 작성할 수 있다.
// 이전 방식
using System;
namespace DemoApp
{
class EntryPoint
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
// C# 9 - 최상위 문장
System.Console.WriteLine("Hello World!");
컴파일러가 자동으로 Main 메서드를 생성하는 문법적 편의 기능이다.
향상된 패턴 매칭
and, or, not 연산자로 논리 패턴 매칭이 가능해졌다.
var keyInfo = Console.ReadKey();
if (keyInfo.KeyChar is 'Y' or 'y')
{
Console.WriteLine("확인을 선택했습니다.");
}
// 범위 기반 switch 표현식
int point = 90;
var grade = point switch
{
0 => "0점",
(> 0) and (<= 60) => "합격",
(> 60) and (<= 80) => "우수",
(> 80) and (<= 100) => "최우수",
_ => "알 수 없음"
};
속성 패턴 매칭:
Type t = Type.GetType("System.String");
if (t is not null and { FullName: "System.String" })
{
Console.WriteLine("System.String 타입입니다.");
}
record 타입
값 기반 동등성 비교를 자동으로 제공하는 참조 타입이다.
public record Customer(int Id, string Name, int Age, string Phone);
var first = new Customer(1, "홍길동", 30, "010-1234-5678");
var second = new Customer(1, "홍길동", 30, "010-1234-5678");
Console.WriteLine(first == second); // True - 값 비교
Equals, GetHashCode, ToString 등이 자동 생성되어 데이터 중심 설계에 유리하다.
nullable 참조 타입 강화
라이브러리 전체에 nullable 주석이 적용되었으며, MemberNotNull과 MemberNotNullWhen 특성이 추가되었다.
class CustomerRepository
{
private Customer _currentCustomer;
[MemberNotNull(nameof(_currentCustomer))]
public string FetchCustomerName(string identifier)
{
_currentCustomer = LoadFromDatabase(identifier);
return _currentCustomer.Name;
}
}
개발 도구 변화
Windows Forms 디자이너
Visual Studio 16.8부터 .NET Core 3.1 및 .NET 5.0용 디자이너가 모든 컨트롤을 지원한다. 드래그 앤 드롭, 속성 창 연동, 이벤트 생성 등이 가능하다.
대상 프레임워크 변경
| TFM | 설명 |
|---|---|
net5.0 | 기본 타겟, .NET Core와 .NET Standard 대체 |
net5.0-windows | Windows 전용 기능 포함 (WinForms, WPF, WinRT) |
net5.0-windows7 | 특정 Windows 버전 지정 |
향후 .NET 6에서는 net6.0-ios, net6.0-android 등 플랫폼별 TFM이 확장될 예정이다.
WinRT 상호 운용성 재설계
.NET 5.0부터 기존 WinRT 상호 운용 체계가 제거되었다. CsWinRT 도구를 통해 C# 기반 WinRT 상호 운용 어셈블리를 생성하며, NuGet으로 배포 가능하다. .NET Core 3.x에서 WinRT를 사용하는 프로젝트는 다중 타겟팅이 필요하다.
네이티브 내보내기 (Native Exports)
COM 없이 .NET 컴포넌트를 네이티브 라이브러리로 노출할 수 있다. 크로스 플랫폼 지원이 특징이다.
진단 기능 확장
- 이벤트 파이프라인: 프로파일러가 이벤트를 기록할 수 있게 확장됨
- 덤프 분석: Linux에서 수집한 프를 Windows에서 분석 가능, macOS ELF 덤프 지원
- 런타임 정보 도구:
dotnet-runtimeinfo로 환경 정보 확인
dotnet tool install -g dotnet-runtimeinfo
dotnet-runtimeinfo
런타임 및 라이브러리 개선
RyuJIT 코드 품질
다양한 시나리오에서 생성 코드의 품질이 향상되었다.
GC(가비지 컬렉션) 최적화
| 개선 사항 | 효과 |
|---|---|
| Card mark stealing | Server GC 스레드 간 작업 분산, 짧은 일시 중지 |
| 고정 객체 힙(POH) | 고정 객체 분리 관리, 세대 ힼ 영향 최소화 |
| 백그라운드 GC 중 LOH 할당 | 유휴 리스트 활용, ힼ 사용률 개선 |
| 백그라운드 GC 일시 중지 최적화 | 관리 스레드 중단 시간 단축 |
| 벡터화된 정렬 | 짧은 GC 일시 중지 시간 |
| 세대 인식 분석 | 오래된 객체가 젊은 객체를 유지하는 패턴 분석 |
| 메모리 페이지 해제 최적화 | Server GC "세상 멈춤" 단계 제거 |
Windows Arm64 지원
Surface Pro X 등 Windows Arm64 기기에서 네이티브 실행이 가능하다. x86 에뮬레이션도 지원되나, 네이티브 실행이 성능이 우수하다. 현재 Windows Forms와 WPF는 지원되지 않는다.
P95+ 지연 시간 개선
Stack Overflow의 사례에서 확인된 결과:
- 중앙값: 21ms → 15ms
- 95번째 백분위: ~40ms → ~30ms
- 99번째 백분위: ~60ms → ~45ms
고정 객체 힙(POH) 도입으로 메모리 단편화 문제가 완화된 것이 주요 원인이다.
계층적 컴파일 개선
호출 횟수 기반 재컴파일 메커니즘을 개선하여 시작 단계 성능 변동성을 줄였다. 또한 반복문이 포함된 메서드에 대한 계층적 컴파일 문제를 해결하기 위해 OSR(On-Stack Replacement) 실험 기능을 도입했다. 이는 실행 중인 메서드를 동적으로 재컴파일하는 기술로, 현재 x64에서 선택적 활성화가 가능하다.
System.Text.Json 강화
성능과 신뢰성이 크게 향상되었으며, record 타입의 역직렬화를 지원한다. Newtonsoft.Json에서의 마이그레이션 가이드도 제공된다.
배포 혁신
컨테이너 최적화
- OpenTelemetry 지원으로 분산 추적 및 메트릭 수집 가능
dotnet-monitor도구로 컨테이너 사이드카 패턴 구현- cgroup v2 지원
- Windows Server Core 이미지 추가 및 크기 축소
- 다단계 빌드 시 총 이미지 크기 감소
단일 파일 애플리케이션
애플리케이션과 모든 의존성을 하나의 실행 파일로 패키징한다. Linux를 중심으로 지원되며, 의존성 포함/미포함 두 가지 모드가 있다.
# 프레임워크 의존 (작은 크기, 런타임 필요)
dotnet publish -r linux-x64 --self-contained false /p:PublishSingleFile=true
# 독립 실행 (큰 크기, 런타임 불필요)
dotnet publish -r linux-x64 --self-contained true /p:PublishSingleFile=true
.NET Core 3.1의 방식과 달리 임시 디렉터리 해제 없이 메모리에서 직접 로드하여 성능 저하가 없다.
ClickOnce 지원
.NET Core 3.1 및 .NET 5.0 Windows 애플리케이션에서 ClickOnce 배포가 가능해졌다.