- Published on
모던 .NET 2026 — .NET 9 / .NET 10 LTS / Aspire / Blazor United / MAUI / Avalonia 11 / FastEndpoints 심층 가이드
- Authors

- Name
- Youngju Kim
- @fjvbn20031
프롤로그 — "Java가 아닌 또 하나의 엔터프라이즈"
2026년 5월. 어떤 시니어 엔지니어가 농담처럼 말했다. ".NET을 안 쓴다고 말하는 사람은 많지만, 자기 카드사 백엔드가 .NET 위에서 돌고 있다는 걸 모르는 사람도 많죠." 농담이지만 진심이 절반 정도 섞여 있다.
웹 트렌드 컨퍼런스의 무대 위는 여전히 TypeScript, Go, Rust가 차지하지만, 실제로 결제·은행·제조·공공·게임 백엔드의 한 축은 .NET이다. 그리고 .NET 본인도 2020년 .NET 5 통합 이후 매년 11월마다 새 메이저를 내며 부지런히 모양을 바꿔왔다.
2024-2026년 사이에 일어난 일을 정리하면:
- .NET 9 (2024년 11월) — STS(Standard Term Support, 18개월). 성능·CLR 개선 중심.
- .NET 10 (2025년 11월, LTS) — Long Term Support 3년. 새로운 기본값.
- ASP.NET Core 10 — Minimal API의 성숙, OpenAPI 내장.
- Aspire (2024년 11월 GA) — 클라우드 네이티브 오케스트레이션 + 텔레메트리.
- Blazor United — Server / WASM / SSR / streaming을 하나의 모델로.
- .NET MAUI — 안정화. iOS/Android/Mac/Windows 단일 코드.
- Avalonia 11 — Linux 포함 진정한 크로스 플랫폼 데스크탑.
- EF Core 9 — JSON, complex types, primitive collections.
- C# 13 (2024) — params collections, lock object, escape sequences.
- C# 14 (2025) — field accessor, partial members, null-conditional assignment.
이 글은 2026년 .NET 진영의 지도를 한 번에 정리한다. 어떤 버전을 골라야 하나, ASP.NET Core 10과 FastEndpoints 중 무엇을 쓰나, Aspire는 정말 필요한가, MAUI vs Avalonia 11, EF Core vs Dapper, MediatR이 유료화된 뒤의 CQRS 패턴, NativeAOT의 실제 한계 — 그리고 누가 .NET을 골라야 하는가까지.
먼저 한 가지만 미리 말해두자. .NET은 죽지 않았다. 그리고 죽기는커녕, 한국·일본의 enterprise·금융·정부 시스템에서는 오히려 점점 더 깊이 자리 잡고 있다. JVM·Go·Node와는 다른 결의 도구이고, 그 결이 잘 맞는 도메인이 분명히 존재한다.
1장 · 2026년 .NET 지도 — 한 장의 그림
| 영역 | 2026년의 사실상 표준 | 비고 |
|---|---|---|
| 런타임 | .NET 10 LTS (2025-11) | .NET 9는 2026-05 EOL 임박 |
| 언어 | C# 13 / C# 14 | F# 9, VB는 stable 유지 |
| 웹 백엔드 | ASP.NET Core 10 + Minimal APIs | + FastEndpoints / Carter |
| 데이터 | EF Core 9 / Dapper / Marten | 선택 폭 큼 |
| 메시징 | MassTransit / NServiceBus / Wolverine | MediatR 유료화 영향 큼 |
| CQRS | Wolverine / Brighter / 직접 구현 | MediatR 8.x는 paid |
| 클라우드 오케스트레이션 | .NET Aspire | Bicep + OTel 내장 |
| 웹 UI | Blazor United | Server + WASM + SSR |
| 모바일 / 데스크탑 | .NET MAUI | iOS/Android/Mac/Win |
| 크로스 플랫폼 데스크탑 | Avalonia 11 | Linux 포함 |
| 게임 | Unity (.NET 8 기반), Stride, MonoGame | Unity는 자체 런타임 |
| 배포 | Container + NativeAOT | self-contained 줄어듬 |
| 패키지 | NuGet 6 + Central Package Management | global.json 표준화 |
| 분석 | Roslyn analyzers + StyleCop + Sonar | nullable enforcement |
핵심만 골라 한 줄로 요약하면:
- 런타임의 자리는 .NET 10 LTS로 굳었다. .NET 9는 짧게 쓰고 떠나는 STS다.
- 웹은 Minimal APIs가 default가 되었지만, FastEndpoints / Carter가 "조금 더 구조적인 Minimal API"로 자리 잡았다.
- Aspire는 .NET 진영의 docker-compose + Kubernetes + OpenTelemetry 통합 도구가 되었다.
- UI는 셋으로 갈라졌다. 웹은 Blazor United, 모바일/데스크탑은 MAUI, Linux 포함 진정한 크로스 플랫폼은 Avalonia 11.
- CQRS 진영은 MediatR 유료화 이후 Wolverine / Brighter / 직접 구현으로 흩어졌다.
2장 · .NET 10 LTS (2025-11) — 플래그십 릴리스
.NET 10은 2025년 11월에 GA가 됐고, Long Term Support 3년이다. 즉 2028년 11월까지 패치 지원. .NET 6 (2021-11), .NET 8 (2023-11) 다음으로 오는 정식 LTS이며, .NET 9는 그 사이의 STS였다.
핵심 변경점:
- CLR / GC: DATAS(Dynamically Adapting To Application Sizes) GC가 default로. 메모리 footprint가 작은 서비스에서 30-40% 줄어듬.
- JIT: PGO(Profile-Guided Optimization) on by default. devirtualization과 inlining이 한 단계 더 적극적.
- NativeAOT 성숙: 더 많은 framework 라이브러리가 AOT-safe. ASP.NET Core minimal API + EF Core 일부가 AOT 가능.
- JSON: System.Text.Json이 polymorphism, snake_case naming, IAsyncEnumerable streaming을 정식 지원.
- threading: TimeProvider, PriorityQueue 개선. async LINQ가 stable.
- C# 14 동시 발매: field accessor, partial properties/methods, null-conditional assignment.
- NuGet 6 + Central Package Management: 솔루션 전체의 패키지 버전을 Directory.Packages.props 하나로 통일.
- dotnet CLI 통합:
dotnet run app.cs단일 파일 실행이 정식 지원.
LTS의 의미는 단순히 패치 기간이 길다는 것이 아니라, 에코시스템 라이브러리가 가장 잘 따라온다는 것이다. EF Core 10, ASP.NET Core 10, Aspire의 안정 채널, MassTransit, MediatR fork들 — 거의 모든 메이저 라이브러리가 .NET 10을 first-class target으로 잡고 있다.
업그레이드 권장:
- .NET 6 (LTS, 2024-11 EOL): 즉시 .NET 10으로.
- .NET 8 (LTS, 2026-11 EOL): 천천히 .NET 10으로. EF Core, MediatR 등 라이브러리 호환성 체크 후.
- .NET 9 (STS, 2026-05 EOL): 빨리 .NET 10으로. 어차피 곧 끝난다.
3장 · .NET 9 (2024-11) — STS와의 비교
.NET 9는 STS, 즉 18개월 지원이라 2026년 5월에 끝난다. 이 글이 쓰이는 시점이 정확히 그 무렵이다. .NET 9는 "다음 LTS인 .NET 10을 위한 실험판" 같은 역할을 했다.
.NET 9에서 들어왔다가 .NET 10에서 다듬어진 것들:
- DATAS GC — .NET 9에서 opt-in, .NET 10에서 default.
- System.Text.Json polymorphism — .NET 9에서 alpha, .NET 10에서 stable.
- OpenAPI 내장 — .NET 9에서 Swashbuckle 의존을 떼고
Microsoft.AspNetCore.OpenApi로 들어왔으나, .NET 10에서 UI까지 통합. - Kestrel HTTP/3 — .NET 9에서 production-ready.
- NativeAOT 확장 — .NET 9에서 더 많은 라이브러리 지원.
요점: .NET 9를 운영하는 팀은 2026년 중반까지는 .NET 10으로 이동해야 한다. 8 (LTS)로 돌아가는 건 의미가 없다 — .NET 8도 2026년 11월에 끝난다.
LTS / STS의 패턴은 이제 분명하다:
- LTS — 짝수 메이저(8, 10, 12...), 3년 지원, 엔터프라이즈 기본값.
- STS — 홀수 메이저(7, 9, 11...), 18개월, 빠른 실험.
엔터프라이즈는 STS를 건너뛰는 게 일반적이다. 즉 .NET 6 → 8 → 10이 정상 경로다.
4장 · C# 13 / C# 14 — params collections, field accessor
C#은 매년 11월 .NET과 같이 새 메이저를 낸다. C# 13은 2024년, C# 14는 2025년에 .NET 10과 함께 발매됐다.
C# 13의 핵심:
- params collections —
params Span<int>,params IEnumerable<int>등 컬렉션 타입에 params 가능. 더 이상params int[]만이 답이 아니다. - lock object 전용 타입 —
System.Threading.Lock이 들어와lock(myLock)에 적합한 모나딕 사용. 일반 object를 lock으로 쓰는 패턴을 분석기가 경고. - 새 escape sequence
\e— ANSI escape (ESC 0x1B). 터미널 ANSI 색 코드 작성이 깔끔해짐. - partial properties — partial method에 이어 partial property도 가능. source generator 친화.
fieldkeyword 미리보기 — getter/setter 안에서 backing field에field로 직접 접근.
C# 14의 핵심:
fieldkeyword 정식 — getter/setter 안에서field로 자동 backing field 접근. 명시적 backing field 선언이 사라짐.- partial members 확장 — 생성자, 연산자, 인덱서까지 partial 가능.
- null-conditional assignment —
obj?.Prop = value— obj가 null이면 할당 안 함. - 확장된 nameof — 미해결 타입 인자를 받아도 nameof 가능.
- 확장 멤버 진화 — 확장 메서드 외에 확장 프로퍼티 미리보기.
field 키워드를 한 줄로 보면:
// 전통 방식 — backing field 명시
private string _name = string.Empty;
public string Name
{
get => _name;
set => _name = value?.Trim() ?? throw new ArgumentNullException();
}
// C# 14 — field로 직접
public string Name
{
get;
set => field = value?.Trim() ?? throw new ArgumentNullException();
} = string.Empty;
_name을 손으로 선언하지 않아도 컴파일러가 만들어준다. 더 이상 _camelCase 백킹 필드의 네이밍 디베이트가 필요 없다.
5장 · ASP.NET Core 10 — performance + DX
ASP.NET Core 10은 .NET 10과 함께 나왔다. 2026년 5월 현재, 모던 .NET 웹의 기본형은 다음과 같다.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();
builder.Services.AddDbContext<AppDbContext>(opts =>
opts.UseNpgsql(builder.Configuration.GetConnectionString("Default")));
var app = builder.Build();
app.MapOpenApi(); // /openapi/v1.json
app.MapScalarApiReference(); // Scalar UI 통합
app.MapGet("/users/{id:guid}", async (Guid id, AppDbContext db) =>
{
var user = await db.Users.FindAsync(id);
return user is null ? Results.NotFound() : Results.Ok(user);
})
.WithName("GetUser")
.WithOpenApi();
app.MapPost("/users", async (CreateUserDto dto, AppDbContext db) =>
{
var user = new User(dto.Name, dto.Email);
db.Users.Add(user);
await db.SaveChangesAsync();
return Results.Created($"/users/{user.Id}", user);
});
app.Run();
달라진 점:
- OpenAPI 내장 — Swashbuckle을 따로 안 깐다.
Microsoft.AspNetCore.OpenApi가 default. - Scalar UI 통합 — Swagger UI보다 가볍고 깨끗한 OpenAPI viewer.
- JSON streaming — IAsyncEnumerable이 chunked transfer encoding으로 자연스럽게 흐름.
- HTTP/3 default — Kestrel이 production-ready로 HTTP/3 지원.
- Compiled routing — endpoint dispatch가 reflection 대신 compile-time 코드 생성.
- OpenTelemetry first-class —
AddOpenTelemetry()가 표준 패턴.
성능 수치 (TechEmpower 류 마이크로벤치마크 기준):
- ASP.NET Core 10 Minimal API + Kestrel: 700k+ req/s (Plaintext)
- ASP.NET Core 10 + EF Core 9 + Postgres: 80-100k req/s (Fortunes)
- 동급 Go (net/http): 600k req/s
- 동급 Node (Fastify): 200k req/s
즉 ASP.NET Core는 2026년에도 가장 빠른 메인스트림 웹 프레임워크 중 하나다.
6장 · Aspire (2024-11 GA) — 클라우드 네이티브 오케스트레이션
Aspire는 2024년 11월에 GA가 된 .NET 진영의 클라우드 네이티브 오케스트레이션 + 로컬 개발 환경 + 텔레메트리 통합 도구다. 이름은 거창하지만 본질은 단순하다.
Aspire가 해결하는 문제:
- 로컬에서
docker-compose up대신 .NET 코드로 의존성 정의. - 마이크로서비스 여러 개 + Postgres + Redis + RabbitMQ를 한 솔루션으로.
- OpenTelemetry 자동 주입 + 대시보드 내장.
- 클라우드 배포 시 Bicep / Terraform / Kubernetes 매니페스트 자동 생성.
AppHost 프로젝트의 모양:
var builder = DistributedApplication.CreateBuilder(args);
var postgres = builder.AddPostgres("db")
.AddDatabase("appdb");
var redis = builder.AddRedis("cache");
var rabbitmq = builder.AddRabbitMQ("messaging");
var apiService = builder.AddProject<Projects.ApiService>("api")
.WithReference(postgres)
.WithReference(redis)
.WithReference(rabbitmq);
builder.AddProject<Projects.WebFrontend>("web")
.WithReference(apiService);
builder.Build().Run();
이 코드를 dotnet run하면:
- Postgres / Redis / RabbitMQ 컨테이너가 자동으로 뜬다.
- API 서비스와 Web Frontend가 .NET 프로세스로 시작된다.
- 연결 문자열은 environment variable로 자동 주입.
- OpenTelemetry 데이터가 Aspire Dashboard로 흐른다.
- 분산 trace, log, metric이 한 화면에서 보인다.
Aspire Dashboard:
- 분산 trace (waterfall view)
- 구조화된 로그
- 메트릭 (CPU, memory, request rate, latency)
- 컨테이너 / 프로세스 상태
- 환경 변수 inspector
클라우드 배포:
- Azure Container Apps에
azd up한 줄로 배포 가능. - 다른 클라우드는 Aspire 매니페스트 → Kubernetes / Bicep / Terraform 변환.
도커 컴포즈 vs Aspire:
| 기준 | docker-compose | Aspire |
|---|---|---|
| 정의 언어 | YAML | C# |
| 디버깅 | 컨테이너 attach | .NET 프로세스 직접 디버깅 |
| 텔레메트리 | 별도 설치 | 내장 |
| 클라우드 배포 | 변환 도구 별도 | 내장 generator |
| .NET 외부 서비스 | 잘 됨 | 잘 됨 (Postgres, Redis, OS image 등) |
Aspire는 .NET 마이크로서비스를 운영하는 팀에게 사실상 default가 됐다. 단, .NET이 아닌 서비스가 많은 폴리글랏 환경이라면 docker-compose가 여전히 자연스럽다.
7장 · Blazor United — Server + WASM + SSR + streaming
Blazor는 2018년의 WebAssembly hype 이후 8년이 지나 2026년 현재, "한 컴포넌트가 여러 렌더링 모드를 골라 쓸 수 있는" 단일 모델로 정착했다. 이를 Microsoft 공식 문서는 Blazor United라고 부른다.
네 가지 렌더 모드:
- Static SSR — 서버에서 한 번 그리고 끝. 가장 빠름, 인터랙션 없음.
- Streaming SSR — 비동기 데이터 로딩 결과를 chunked로 스트리밍.
- Server interactive — SignalR 기반, 서버에서 이벤트 처리.
- WebAssembly interactive — 클라이언트 WASM, 오프라인 가능.
한 페이지가 컴포넌트 단위로 모드를 섞을 수 있다.
@page "/dashboard"
@rendermode InteractiveAuto
<h1>대시보드</h1>
<StaticSummary />
<InteractiveChart />
InteractiveAuto는 첫 방문 시 Server 모드(SignalR)로 빠르게 뜨고, WASM 다운로드가 완료되면 그 다음부터는 WASM으로 전환한다. 첫 인터랙션 지연을 줄이는 패턴.
Blazor의 강점:
- 풀스택 C#. JavaScript 없이 SPA 가능 (또는 최소화).
- ASP.NET Core와의 통합. 같은 인증, DI, 미들웨어 사용.
- SignalR이 안정적. 양방향 통신이 자연스러움.
- WASM AOT 빌드로 차츰 첫 로드 사이즈 줄어드는 중.
Blazor의 약점:
- WASM 초기 번들 크기는 여전히 1-3MB. Compression 적용 후도 무겁다.
- 생태계는 React/Vue에 비해 작다.
- 모바일 브라우저 WASM 성능은 여전히 데스크탑보다 느림.
- 디자이너 / 컴포넌트 마켓이 부족함.
누가 쓰나: 사내 도구, B2B 어드민, 풀스택 .NET 팀의 SPA가 sweet spot. 공개 마케팅 사이트나 SEO 중심 페이지는 Static SSR로 한정.
8장 · .NET MAUI — 크로스 플랫폼 네이티브
.NET MAUI(Multi-platform App UI)는 2022년 Xamarin.Forms의 후계자로 나와, 2024-2026년 사이에 안정화됐다. iOS / Android / macOS / Windows를 단일 C# 코드로.
MAUI의 구조:
- 단일 프로젝트, 단일 코드베이스.
- XAML 또는 C# 마크업으로 UI.
- 플랫폼별 핸들러로 native control 그림.
- Hot reload 지원.
MAUI Hybrid + Blazor Hybrid:
MAUI 안에서 BlazorWebView를 띄워 Razor 컴포넌트를 native 앱으로 재사용 가능. 즉 웹용으로 만든 Blazor UI를 모바일 앱에도 거의 그대로.
<BlazorWebView HostPage="wwwroot/index.html">
<BlazorWebView.RootComponents>
<RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
</BlazorWebView.RootComponents>
</BlazorWebView>
이 패턴은 풀스택 .NET 팀이 모바일 앱까지 갖출 때 매력적이다. React Native보다 빌드 / 배포 파이프라인이 단순하고, Flutter보다 .NET 백엔드와의 통합이 자연스럽다.
MAUI의 약점:
- iOS / Android 네이티브 SDK 진화 속도를 100% 따라가지는 못함.
- Linux 데스크탑은 공식 지원 아님 (커뮤니티 GTK 백엔드 존재).
- 일부 복잡한 애니메이션 / 성능 critical 부분은 여전히 native가 우위.
2026년 권고: 사내 모바일 / 윈도우 데스크탑 한정. 공개 앱스토어용 컨슈머 앱은 Flutter, SwiftUI/Compose, React Native와 비교 후 결정.
9장 · Avalonia 11 — 진정한 크로스 플랫폼 UI
Avalonia는 커뮤니티가 만들고 .NET Foundation에서 운영하는 오픈소스 크로스 플랫폼 UI 프레임워크다. 2023년 11월에 11.0이, 2024-2025년에 11.1 / 11.2 / 11.3이 차례로 나왔다.
MAUI와의 차이:
| 기준 | .NET MAUI | Avalonia 11 |
|---|---|---|
| 거버넌스 | Microsoft | 커뮤니티 + 상용(AvaloniaUI 회사) |
| 플랫폼 | iOS/Android/Mac/Win | iOS/Android/Mac/Win/Linux/WebAssembly |
| 렌더링 | 플랫폼 native 컨트롤 | 자체 렌더링 (Skia 기반) |
| UI 일관성 | 플랫폼마다 다름 | 모든 플랫폼 동일 |
| 디자인 패턴 | XAML + handlers | XAML + 자체 컨트롤 트리 |
| Hot reload | 지원 | 지원 |
| 데스크탑 우선도 | 약함 | 강함 |
Avalonia가 빛나는 경우:
- Linux 데스크탑이 진짜로 필요한 팀. (MAUI는 못 함.)
- 모든 플랫폼에서 픽셀 단위로 같은 UI가 필요한 경우.
- 데스크탑 중심 앱 (IDE, 그래픽 도구, 음악/영상 소프트웨어).
실제 사례:
- JetBrains Rider는 일부 UI에 Avalonia 시도 (전면 채택은 아님).
- WasabiWallet, Camelot, AvaloniaEdit 등 오픈소스 .NET 데스크탑 도구.
- 여러 enterprise 사내 도구가 WPF에서 Avalonia로 이주 중. WPF는 Windows 전용이라 Mac/Linux 클라이언트를 위해.
약점:
- 모바일은 가능하지만 native 느낌이 부족함. MAUI에 양보가 맞다.
- WPF 대비 커뮤니티 컨트롤 마켓이 작음.
2026년 권고: WPF의 자연스러운 후계자. Linux/Mac 데스크탑 .NET 앱이라면 첫 번째 선택지.
10장 · Entity Framework Core 9
EF Core 9는 2024년 11월에 .NET 9와 같이 나왔고, EF Core 10이 2025년 11월에 나왔다. 2026년 5월의 사실상 표준은 EF Core 10이다.
최근 2-3년의 변화:
- JSON columns 정식 지원 — Postgres
jsonb, SQL Server JSON, SQLite JSON. LINQ로 JSON 내부 쿼리. - Complex types — owned types를 더 가볍게. Value object 모델링이 자연스러워짐.
- Primitive collections —
List<int>을 컬럼에 그대로 매핑. - Bulk operations —
ExecuteUpdateAsync,ExecuteDeleteAsync로 N+1 없는 일괄 수정. - Query splitting 기본값 — JOIN 폭발 방지.
전형적인 코드:
public class AppDbContext : DbContext
{
public DbSet<Order> Orders => Set<Order>();
protected override void OnModelCreating(ModelBuilder mb)
{
mb.Entity<Order>(b =>
{
b.ToTable("orders");
b.ComplexProperty(o => o.ShippingAddress);
b.OwnsMany(o => o.Items);
b.Property(o => o.Metadata)
.HasColumnType("jsonb");
});
}
}
// Bulk delete - SQL 한 번
await db.Orders
.Where(o => o.Status == OrderStatus.Cancelled && o.CreatedAt < DateTime.UtcNow.AddYears(-1))
.ExecuteDeleteAsync();
EF Core vs Dapper vs Marten:
| 도구 | 모델 | 강점 | 약점 |
|---|---|---|---|
| EF Core | ORM / Change tracking | 풍부한 LINQ, 마이그레이션, 관계 | 복잡 쿼리는 SQL 가독성 떨어짐 |
| Dapper | Micro-ORM | 빠름, SQL 직접 작성 | 모든 게 수동 |
| Marten | Postgres + Event Sourcing | document DB + event store | Postgres 전용 |
| LinqToDB | SQL-shape LINQ | 성능 + LINQ 표현력 | 학습 곡선 |
2026년의 default는 EF Core + Dapper 혼용이다. CRUD와 도메인 변경은 EF Core, 무거운 보고 / 분석 쿼리는 Dapper.
11장 · MediatR / MassTransit / NServiceBus — CQRS와 메시징
2024년 말, .NET CQRS 진영이 흔들렸다. MediatR이 8.x부터 상용 라이선스로 전환됐기 때문이다. 또한 같은 저자의 AutoMapper도 비슷한 시기에 paid edition을 도입했다. 이 결정은 .NET 커뮤니티에서 큰 논쟁을 일으켰다.
현재의 선택지:
| 도구 | 모델 | 라이선스 | 비고 |
|---|---|---|---|
| MediatR 8+ | in-process mediator | Commercial | 안정. 비용 발생. |
| Wolverine | in-process + messaging | OSS (MIT) | Jeremy D. Miller. CQRS + saga 통합. |
| Brighter | command processor | OSS (BSD) | 메시징 통합. |
| 자체 구현 | DI + interface | n/a | 작은 프로젝트는 충분. |
Wolverine 예시:
// Handler — interface 없이 메서드 시그니처로 인식
public class CreateOrderHandler
{
public async Task<OrderCreated> Handle(CreateOrder command, AppDbContext db)
{
var order = new Order(command.CustomerId, command.Items);
db.Orders.Add(order);
await db.SaveChangesAsync();
return new OrderCreated(order.Id);
}
}
// 호출
var result = await bus.InvokeAsync<OrderCreated>(new CreateOrder(...));
interface 선언 없이 메서드 시그니처를 분석하는 게 Wolverine의 특징. MediatR의 IRequestHandler 보일러플레이트가 사라진다.
메시징 (out-of-process):
| 도구 | 트랜스포트 | 라이선스 | 강점 |
|---|---|---|---|
| MassTransit | RabbitMQ, Azure Service Bus, Kafka 등 | OSS (Apache) → 일부 Pro | 가장 많이 쓰임 |
| NServiceBus | 다양 | Commercial | 엔터프라이즈. saga 강함. |
| Wolverine | RabbitMQ, Kafka, Azure Service Bus | OSS (MIT) | CQRS와 messaging 통합 |
| Rebus | RabbitMQ, Azure Service Bus, etc. | OSS | 가벼움 |
MassTransit의 saga 패턴:
public class OrderSaga : MassTransitStateMachine<OrderState>
{
public State Submitted { get; private set; }
public State Paid { get; private set; }
public State Shipped { get; private set; }
public Event<OrderSubmitted> OnSubmitted { get; private set; }
public Event<PaymentReceived> OnPaid { get; private set; }
public OrderSaga()
{
InstanceState(x => x.CurrentState);
Initially(
When(OnSubmitted)
.Then(c => c.Saga.OrderId = c.Message.OrderId)
.TransitionTo(Submitted));
During(Submitted,
When(OnPaid)
.TransitionTo(Paid));
}
}
2026년 권고:
- 단순한 in-process mediator: 직접 구현 또는 Wolverine.
- CQRS + messaging 통합 필요: Wolverine.
- 엔터프라이즈 + 상용 지원 필요: NServiceBus.
- 이미 MediatR + MassTransit 쓰던 팀: MediatR 8+ 라이선스 비용 계산 후 갈아탈지 결정.
12장 · FastEndpoints / Carter / Minimal APIs
ASP.NET Core 10의 라우팅 스타일은 셋으로 갈렸다.
1. Minimal APIs (default):
app.MapGet("/orders/{id:guid}", async (Guid id, AppDbContext db) =>
{
var order = await db.Orders.FindAsync(id);
return order is null ? Results.NotFound() : Results.Ok(order);
});
장점: 가벼움, 시작이 빠름. 단점: 큰 API에서 Program.cs가 비대해짐.
2. Controllers (전통):
[ApiController]
[Route("orders")]
public class OrdersController : ControllerBase
{
[HttpGet("{id:guid}")]
public async Task<IActionResult> Get(Guid id) { ... }
}
장점: 익숙함, 클래스 단위 조직화. 단점: 보일러플레이트 많음.
3. FastEndpoints / Carter (구조적 미니멀):
FastEndpoints는 "Endpoint per class" 패턴을 강제한다.
public class GetOrderEndpoint : Endpoint<GetOrderRequest, OrderResponse>
{
public AppDbContext Db { get; set; } = null!;
public override void Configure()
{
Get("/orders/{id:guid}");
AllowAnonymous();
}
public override async Task HandleAsync(GetOrderRequest req, CancellationToken ct)
{
var order = await Db.Orders.FindAsync([req.Id], ct);
if (order is null) { await SendNotFoundAsync(ct); return; }
await SendAsync(new OrderResponse(order), cancellation: ct);
}
}
Carter는 Nancy의 정신적 후계자로, 모듈 단위 라우팅.
public class OrdersModule : ICarterModule
{
public void AddRoutes(IEndpointRouteBuilder app)
{
app.MapGet("/orders/{id:guid}", async (Guid id, AppDbContext db) =>
{
var order = await db.Orders.FindAsync(id);
return order is null ? Results.NotFound() : Results.Ok(order);
});
}
}
비교:
| 기준 | Minimal API | Controllers | FastEndpoints | Carter |
|---|---|---|---|---|
| 보일러플레이트 | 매우 적음 | 많음 | 적음 | 매우 적음 |
| 조직화 | 약함 | 강함 | 강함 (per-class) | 중간 (per-module) |
| 성능 | 가장 빠름 | 약간 느림 | 가장 빠름 (Minimal 위) | 가장 빠름 (Minimal 위) |
| OpenAPI | 자동 | 자동 | 자동 + 풍부 | 자동 |
| 학습 곡선 | 낮음 | 낮음 | 중간 | 낮음 |
| 큰 API 친화도 | 약함 | 강함 | 강함 | 중간 |
권고: 50개 이하의 엔드포인트는 Minimal API, 그 이상은 FastEndpoints 또는 Controllers. Carter는 가볍게 모듈로 나누고 싶을 때.
13장 · NativeAOT — 작은 단일 실행 파일
NativeAOT는 .NET 7에서 GA가 됐고, .NET 9-10에서 성숙했다. 핵심 아이디어는 JIT 대신 ahead-of-time 컴파일로 단일 native 실행 파일을 생성하는 것이다.
장점:
- 시작 시간: 보통 50-100ms (vs JIT의 200-500ms). cold start 민감한 워크로드에 좋다 (serverless, CLI 도구).
- 메모리: 30-40% 작음. JIT 관련 메타데이터 없음.
- 단일 실행 파일: 10-30MB의 stand-alone binary. CoreCLR / framework 동봉 안 함.
- 트림된 바이너리: 사용 안 하는 코드 제거.
제약:
- Reflection 제한: 전통적인 reflection-heavy 라이브러리는 동작 안 함. Serializer, ORM, IoC container가 모두 source generator를 써야 함.
- dynamic 코드 생성 금지: Reflection.Emit이 작동 안 함.
- JIT compilation 없음: 런타임에 새 어셈블리 로드 불가.
AOT-친화 라이브러리:
- System.Text.Json (with source generator)
- Minimal APIs / FastEndpoints
- EF Core 일부 (8+부터 점진적)
- Dapper
- Refit (HTTP client)
- ASP.NET Core RequestDelegateGenerator
AOT-비친화:
- 일부 IoC 컨테이너 (Autofac, Castle Windsor 등)
- Newtonsoft.Json (Reflection 의존)
- MediatR 일부 패턴
- AutoMapper
예시 — AOT minimal API:
<PropertyGroup>
<PublishAot>true</PublishAot>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
dotnet publish -c Release -r linux-x64
# 단일 native 실행 파일 → bin/Release/net10.0/linux-x64/publish/MyApi
# 사이즈: 보통 15-25 MB
언제 쓰나:
- AWS Lambda, Cloud Functions 등 serverless.
- CLI 도구 (dotnet-tool 대안).
- 컨테이너 cold start 민감한 마이크로서비스.
- 시작 시간이 비즈니스적으로 중요한 모든 곳.
언제 안 쓰나:
- Reflection 의존 라이브러리가 많은 레거시.
- 빌드 시간 / 디버깅 편의가 우선인 개발 단계.
- LegacyEF Core / 복잡한 IoC 컨테이너를 쓰는 모놀리스.
14장 · Roslyn analyzers / NuGet / dotnet CLI
Roslyn analyzers:
.NET 분석기는 컴파일 시점에 코드 품질·보안·성능 이슈를 잡는다. 2026년에는 거의 default로 다음을 깐다:
- .NET 내장 분석기 (CA, IDE 룰)
- StyleCop.Analyzers (코드 스타일)
- SonarAnalyzer.CSharp (정적 분석)
- Meziantou.Analyzer (커뮤니티 베스트 프랙티스)
- Roslynator (refactoring + 분석)
- SecurityCodeScan (보안 취약점)
.editorconfig로 룰을 통제:
[*.cs]
dotnet_diagnostic.CA1822.severity = warning # mark members as static
dotnet_diagnostic.IDE0005.severity = error # unused using
dotnet_analyzer_diagnostic.category-Style.severity = suggestion
Nullable enforcement:
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
이 두 줄이 모던 .NET 프로젝트의 가장 큰 차이다. null 안전성을 컴파일러가 강제.
NuGet 6 + Central Package Management:
Directory.Packages.props 한 파일로 솔루션 전체의 패키지 버전 통제:
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="MediatR" Version="8.4.0" />
<PackageVersion Include="EntityFrameworkCore.Sqlite" Version="10.0.0" />
<PackageVersion Include="Serilog.AspNetCore" Version="8.0.3" />
</ItemGroup>
</Project>
각 csproj에서는 버전 없이 <PackageReference Include="MediatR" />만. 버전 충돌이 사라진다.
dotnet CLI 통합:
# 2026년 표준 워크플로
dotnet new aspire-starter -n MyApp # Aspire 솔루션 생성
dotnet add package Serilog.AspNetCore # 패키지 추가 (CPM이면 Directory.Packages.props에 기록)
dotnet ef migrations add InitialCreate # EF Core 마이그레이션
dotnet aspire run # Aspire 앱 실행
dotnet test --collect:"XPlat Code Coverage" # 테스트 + 커버리지
dotnet format # 자동 포매팅
dotnet workload install android ios # MAUI 워크로드
dotnet run app.cs # 단일 파일 실행 (.NET 10)
global.json:
루트에 두면 솔루션이 어떤 SDK 버전을 쓸지 명시.
{
"sdk": {
"version": "10.0.100",
"rollForward": "latestFeature"
}
}
이 한 파일 덕분에 팀원마다 SDK 버전이 다를 때 생기는 미묘한 버그가 사라진다.
15장 · 한국 / 일본 — 토스, 任天堂, ソフトバンク
.NET은 한국·일본 시장에서 흔히 보이지 않는 듯하지만, 실제 enterprise / 금융 / 게임 백엔드에는 광범위하게 깔려 있다.
한국:
- 금융권 백엔드: 신한은행, KB국민카드, 현대카드 등 대형 금융사의 일부 백엔드가 ASP.NET / .NET 8+ 위에 있다. 특히 카드사 / 채권 / 자산관리 시스템.
- 공공 시스템: 행정망 일부, 국세청 시스템 일부, 우체국 일부에서 .NET이 사용된다. (보안 / 감사 관점에서 마이크로소프트와의 장기 라이선스 관계가 크다.)
- 토스 (Toss): 대부분 JVM / Kotlin / Node.js 스택이지만, 일부 어드민 / 사내 도구가 .NET 위에 있다는 사례 보고. 공식 컨퍼런스 발표는 드묾.
- NCSOFT, 넥슨, 펄어비스: 게임 클라이언트는 Unity / Unreal이지만 일부 백엔드 / 사내 도구가 .NET. Unity는 자체 .NET 런타임을 쓰지만 동일한 C# 코드베이스.
- 삼성SDS, LG CNS: SI 프로젝트에서 .NET을 선택하는 경우가 여전히 많다.
일본:
- 任天堂 (Nintendo): 일부 사내 도구 / 백엔드에 .NET. 게임 본체는 자체 엔진이지만 어드민·매니지먼트·온라인 서비스 일부.
- ソフトバンク (SoftBank): 모바일 사업부의 일부 백엔드. 통신 인프라 관리 도구에 .NET이 사용된다는 발표.
- 楽天 (Rakuten): 백엔드의 큰 축은 Java / Python이지만 광고 / 분석 시스템 일부가 .NET.
- NTT データ / 富士通: 일본 SI 대기업이 .NET 기반 정부·금융 프로젝트를 다수 운영.
- サイボウズ (Cybozu): kintone의 일부 서비스, 사내 도구에 .NET 사용 보고.
- メルカリ (Mercari): 대부분 Go 백엔드지만 결제·정산 일부에 .NET 사용.
요약하면: 한국·일본 모두 enterprise / 금융 / 통신 / 정부 영역에서 .NET이 사실상 표준 옵션 중 하나다. 컨퍼런스 무대에 잘 안 보일 뿐, 매출과 시스템 규모로 보면 적지 않다.
16장 · 누가 .NET을 골라야 하나
.NET을 골라야 할 경우:
- 엔터프라이즈 / 금융 / 정부 도메인. 마이크로소프트 ecosystem(SQL Server, Azure AD, Office)과의 자연스러운 통합. 장기 LTS와 감사 친화성.
- 풀스택 C# 팀. Blazor + ASP.NET Core + MAUI로 웹/모바일/데스크탑을 단일 언어로.
- 고성능 웹 백엔드. ASP.NET Core 10 + Minimal APIs는 Go에 근접한 throughput.
- Windows 데스크탑 / .NET 통합 도구. WPF, WinForms, MAUI, Avalonia 중 골라 쓸 수 있음.
- Unity 게임 개발. C# 단일 언어로 클라이언트·서버 통일.
- AWS Lambda / Cloud Functions 워크로드 (NativeAOT). cold start 우수.
.NET을 피해야 할 경우:
- PaaS / serverless heavy 환경에서 JS / Python 우선. Vercel / Cloudflare Workers 같은 환경.
- 데이터 사이언스 / ML 우선 팀. Python 생태계가 압도적.
- 모바일 우선 (소셜 / 컨슈머 앱). SwiftUI / Compose / React Native / Flutter가 더 자연스러움.
- JVM 라이브러리 자산이 많은 조직. Kafka, Spark, Hadoop, Flink 등이 1순위라면 JVM이 자연스러움.
- 극단적 시스템 프로그래밍. Rust / C++ / Go가 더 잘 맞음.
의사결정 트리 (단순화):
Q1. 도메인은?
├── 엔터프라이즈 / 금융 / 정부 / 보험 / Windows 통합
│ └── .NET 10 + ASP.NET Core 10 + EF Core 10
├── 공개 컨슈머 웹 / SEO 중심
│ └── Next.js / Remix / SvelteKit 우선 검토
├── 게임 (Unity)
│ └── C# (.NET 호환 런타임)
└── 모바일 앱 (컨슈머)
└── Native 또는 Flutter / RN 우선
Q2. 팀 언어는?
├── C# 강함 → .NET
├── Java/Kotlin 강함 → Spring / Quarkus
├── TS/JS 강함 → Node / Deno
└── Python 강함 → FastAPI / Django
Q3. 배포 환경은?
├── Azure / On-prem Windows → .NET 자연스러움
├── AWS / GCP / K8s → .NET 가능, 단 OpenTelemetry · Aspire 활용
└── Vercel / Cloudflare / Edge → .NET 안 맞음
한 줄 권고 (2026년 5월 기준):
- 엔터프라이즈 / 금융 / 통신 / 정부 신규 시스템: .NET 10 LTS + ASP.NET Core 10 + EF Core 10 + Aspire.
- 사내 도구 / 어드민 풀스택: Blazor United.
- 모바일이 .NET 팀의 추가 부담: MAUI + Blazor Hybrid.
- 진정한 크로스 플랫폼 데스크탑: Avalonia 11.
- 작은 API: Minimal APIs. 50개 이상 엔드포인트: FastEndpoints.
- CQRS는 Wolverine, 메시징은 MassTransit.
- 단일 실행 파일 / cold start 우선: NativeAOT.
가장 중요한 메타-권고: .NET을 안 쓰는 게 합리적인 도메인도 분명히 있다. 하지만 자기가 그 도메인에 있다고 단정하기 전에, 한 번쯤은 모던 .NET이 어디까지 왔는지 직접 측정해볼 가치가 있다. 2026년의 .NET은 2018년의 .NET과 거의 다른 도구다.
참고 / References
- .NET 공식 — https://dotnet.microsoft.com/
- .NET 10 발표 — https://devblogs.microsoft.com/dotnet/announcing-dotnet-10/
- .NET 9 발표 — https://devblogs.microsoft.com/dotnet/announcing-dotnet-9/
- .NET 릴리스 정책 (LTS / STS) — https://dotnet.microsoft.com/platform/support/policy/dotnet-core
- C# 13 새 기능 — https://learn.microsoft.com/dotnet/csharp/whats-new/csharp-13
- C# 14 새 기능 — https://learn.microsoft.com/dotnet/csharp/whats-new/csharp-14
- ASP.NET Core 10 — https://learn.microsoft.com/aspnet/core/release-notes/aspnetcore-10.0
- .NET Aspire — https://learn.microsoft.com/dotnet/aspire/
- Aspire GA 발표 — https://devblogs.microsoft.com/dotnet/dotnet-aspire-general-availability/
- Blazor — https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor
- .NET MAUI — https://dotnet.microsoft.com/apps/maui
- Avalonia UI — https://avaloniaui.net/
- Entity Framework Core — https://learn.microsoft.com/ef/core/
- EF Core 9 발표 — https://devblogs.microsoft.com/dotnet/announcing-ef9/
- MediatR — https://github.com/jbogard/MediatR
- MediatR 상용화 발표 — https://www.jimmybogard.com/automapper-and-mediatr-going-commercial/
- MassTransit — https://masstransit.io/
- NServiceBus — https://particular.net/nservicebus
- Wolverine — https://wolverinefx.net/
- FastEndpoints — https://fast-endpoints.com/
- Carter — https://github.com/CarterCommunity/Carter
- Minimal APIs 개요 — https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis/overview
- NativeAOT 가이드 — https://learn.microsoft.com/dotnet/core/deploying/native-aot/
- Roslyn analyzers — https://learn.microsoft.com/dotnet/fundamentals/code-analysis/overview
- NuGet Central Package Management — https://learn.microsoft.com/nuget/consume-packages/central-package-management
- dotnet CLI — https://learn.microsoft.com/dotnet/core/tools/
- Marten (Postgres + Event Sourcing) — https://martendb.io/
- Dapper — https://github.com/DapperLib/Dapper
- TechEmpower Web Framework Benchmarks — https://www.techempower.com/benchmarks/
- Cybozu Tech Blog — https://blog.cybozu.io/
- Mercari Engineering — https://engineering.mercari.com/