주말 아침 - 주간 닷넷 #41


한 주 동안 .NET 생태계에서 있었던 주요 이슈와 아티클, 기술 트렌드를 정리해 소개합니다.


:pushpin: .NET 11 Preview 7

  • 저자: Jon Galloway
  • 태그: #dotnet11 #preview #runtimeasync nativeaot

주요 내용

  • runtime-async가 계층형 컴파일 경로로 전환되어 TechEmpower 워밍업 할당이 초당 110GB에서 8GB로 감소, tail-await 최적화로 완료된 Task 대기 루프가 191ms→32ms
  • NativeAOT 제네릭 가상 디스패치 2.45ns→1.74ns, AVX-VNNI-512 인트린식, Arm64 SVE에서 Vector<T> 128비트 상한 제거
  • IEEE 754 십진 부동소수점 Decimal32/Decimal64/Decimal128, 제네릭 Complex<T>, HTTP 요청 본문 압축(GZip/Brotli/Zstandard), ZIP 암호 및 AES 암호화 지원
  • Blazor Interactive Server 서킷 자동 일시정지, SSR 서브트리 캐싱용 CacheView 컴포넌트, 검증 지역화 내장
  • SDK: NativeAOT CLI 기본 활성화로 dotnet tool list가 378ms→68ms, MSBuild 서버 기본 활성화, 컨테이너 게시가 플랫폼 네이티브 런타임 우선

:pushpin: .NET 및 .NET Framework 2026년 8월 서비싱 업데이트

  • 저자: Rahul Bhandari, Tara Overfield
  • 태그: #security #cve #servicing

주요 내용

  • CVE 10건 수정, .NET 10.0 / 9.0 / 8.0 전 버전에 영향
  • 원격 코드 실행 2건: CVE-2026-70354(.NET Core RCE), CVE-2026-62897(.NET RCE)
  • 권한 상승 3건(CVE-2026-62886, 62871, 62909), 정보 노출 3건(CVE-2026-62898, 62900, 62902)
  • 보안 기능 우회 1건(CVE-2026-62899), 서비스 거부 1건(CVE-2026-62901)
  • 릴리스 버전 .NET 10.0.11 / 9.0.19 / 8.0.30, 설치 관리자·컨테이너 이미지·Linux 패키지 모두 갱신

:pushpin: .NET 11 Preview 6의 자동 CSRF 보호 — Fetch Metadata 헤더 기반

  • 저자: Andrew Lock
  • 태그: #dotnet11 #csrf aspnetcore

주요 내용

  • ICsrfProtection 인터페이스와 기본 구현 DefaultCsrfProtection, WebApplicationBuilder에 자동 추가되는 CsrfProtectionMiddleware
  • HTTP 메서드, Sec-Fetch-Site 헤더, CORS 정책, Origin 헤더를 순서대로 검사하는 6단계 판정 알고리즘
  • 판정 결과를 요청에 기록하는 IAntiforgeryValidationFeature
  • Minimal API와 Blazor SSR에서 DisableAntiforgery()로 opt-out하거나 AddCors()/UseCors()로 허용 오리진 지정
  • MVC/Razor Pages는 기존 토큰 검증이 병행 적용되며, 폼 데이터를 읽는 엔드포인트에서만 강제되어 오탐을 줄이는 동작

:pushpin: EF Core로 리치 도메인 모델 영속화하기

  • 저자: Milan Jovanović
  • 태그: #efcore #ddd #domainmodel

주요 내용

  • 공개 세터·공개 무인자 생성자 없이 캡슐화된 애그리게이트를 영속화하는 매핑을 Batch 예제로 구성
  • private 무인자 생성자와 백킹 필드 기반 구체화, 파라미터 생성자는 내비게이션 바인딩 불가라는 제약
  • 강타입 ID의 HasConversion + ValueGeneratedNever, 다른 애그리게이트는 내비게이션 없이 ID로만 참조
  • 캡슐화된 컬렉션을 HasMany<T>("_readings") + PropertyAccessMode.Field로 매핑, 프로퍼티 없는 private 필드 질의 시 EF.Property<DateTime?>() 비용
  • 값 객체는 복합 타입(ComplexProperty)으로 인라인 저장, EF Core 8의 v1 제약을 EF Core 10이 해제, 도메인 이벤트는 IgnoreSaveChangesInterceptor로 디스패치

:pushpin: 내구성 있는 웹훅 전송을 완성하기까지 세 번의 장애

https://topuzas.medium.com/we-broke-webhooks-three-times-before-getting-durable-delivery-right-asp-net-core-447462a98c7a

  • 저자: Ali Süleyman TOPUZ
  • 태그: #webhook #outbox #resilience

주요 내용

  • 세 번의 프로덕션 장애 — 무음 유실(fire-and-forget), 중복 전송(워커 경합), 트랜잭션 분리로 인한 고아 주문
  • 전송 의도를 DB에 기록하고 Postgres SELECT ... FOR UPDATE SKIP LOCKED로 워커 간 행 잠금, 비즈니스 트랜잭션과 동일 트랜잭션에 아웃박스 기록
  • HMAC-SHA256 서명과 Secret/PreviousSecret 유예 기간 로테이션
  • 지터 포함 지수 백오프(최대 1시간), 4xx는 영구 실패로 처리하되 408·409·425·429는 일시 실패, Polly 서킷 브레이커와 테넌트별 동시성 제한
  • Testcontainers + 실제 PostgreSQL로 행 잠금 검증, WireMock.Net으로 수신 측 실패 시뮬레이션, Standard Webhooks 헤더 규약 채택

:pushpin: .NET 11 Runtime Async는 얼마나 빠른가

https://medium.com/@skyake/how-fast-is-net-11-runtime-async-b9■■21529cd5

  • 저자: Kai Sawano
  • 태그: #dotnet11 async #performance #benchmark

주요 내용

  • Runtime Async는 컴파일러의 상태 머신 변환을 대체해 원래 제어 흐름을 유지한 채 JIT가 런타임에 최적화하며, Async Calling Convention이 Continuation 객체를 레지스터로 전달
  • 워밍업 후 각 벤치마크를 1억 회 실행해 .NET 11 Async2와 .NET 10 Async1을 비교
  • 중단이 없는 경우 기존 async 대비 약 20배 빠르고 동기 기준선과 오차 범위 내로 근접, 할당은 연산당 0바이트
  • ThreadPool·TaskCompletionSource 연속 실행은 약 3~4배, 깊은 async 상태 머신 체인은 7.4배 개선
  • 폐기된 Green Threads 실험(1억 회 시스템 콜 300ms→1,800ms)과 대비해 Continuation이 수십 바이트로 Green Thread의 2KB 초기 스택보다 가볍다는 설계 배경

:pushpin: .NET 모듈 경계 강제하기 — 모듈러 모놀리스를 실제로 모듈러하게 유지하는 법

https://medium.com/@nyvarex/enforcing-module-boundaries-in-net-how-to-keep-a-modular-monolith-actually-modular-3a28655eac66

  • 저자: Miraç Aksu
  • 태그: #modularmonolith #architecture #netarchtest

주요 내용

  • 모듈이 소유하는 네 가지(비즈니스 규칙, 데이터, 내부 구현, 작은 공개 계약)를 정의하고 3계층 방어 구조 제시
  • 1계층 컴파일러: 구현 타입 전부 internal, 모듈 간에는 Contracts 프로젝트만 ProjectReference — 위반 시 CS0234 빌드 오류로 차단되고 우회하려면 .csproj diff가 남음
  • 2계층 아키텍처 테스트: NetArchTest로 모듈 간 Internal 참조를 검증하고, GetExportedTypes()로 모듈이 공개 타입을 정확히 하나만 노출하는지 확인
  • 3계층 컨벤션: Modules.X.Contracts / Modules.X.Internal 접두사 분리, 모듈당 하나의 컴포지션 표면, 단일 컴포지션 루트
  • 막지 못하는 것 — 모듈 간 테이블 공유, 리플렉션·복붙, 경계 모델 자체가 틀린 경우. 실행 가능한 예제 저장소와 위반 실습 문서 제공

:pushpin: 관계형이 유리한 곳은 관계형으로, 불가피한 곳은 JSONB로 — IIIF를 PostgreSQL에

https://ahmadminoo.medium.com/relational-where-it-helps-jsonb-where-it-must-persisting-iiif-presentation-3-in-postgresql-with-32e53b164d0c

  • 저자: Ahmad Minoo
  • 태그: #efcore #postgresql #jsonb

주요 내용

  • 다국어 라벨·메타데이터·polymorphic annotation 그래프를 가진 IIIF Manifest를 통짜 JSON과 관계형 분해 중 어디에 둘지에 대한 하이브리드 설계
  • 안정적이고 쿼리 대상인 부분(라벨, 메타데이터, provider, range)은 관계형 41개 테이블로, Canvas Items·polymorphic body/target·selector·choice는 JSONB로 분리
  • 별도 도메인 모델 없이 SDK Manifest 타입을 EF Core OwnsOne/OwnsMany로 직접 매핑하고 루트에 비정규화 컬럼을 shadow property로 유지
  • PostgreSQL xminIsRowVersion()으로 매핑한 낙관적 동시성, cartesian explosion 방지용 AsSplitQuery()
  • change tracker 초기화 → owned 자식 행 삭제 → 재부착 → 트랜잭션 저장의 aggregate 교체 갱신 전략과 41개 테이블 복잡도·delete-reinsert 비용 등 비용표

:pushpin: TypeDeclaration — JSON Schema 이해를 위한 추상화

  • 저자: Matthew Adams
  • 태그: #jsonschema #codegen #corvus #sourcegenerator

주요 내용

  • JSON Schema 키워드가 코드 패턴으로 직접 매핑되지 않는 문제 — 튜플 판별에 prefixItemsitems: false를 함께 봐야 하고, 수치 텐서 식별에는 중첩 items 체인 추적이 필요
  • Corvus.JsonSchema의 TypeDeclaration은 키워드 대신 capability를 노출하는 중간 표현으로, 어휘마다 다른 키워드를 써도 API는 동일하게 유지
  • 정규화 대상: prefixItems + items: false → 튜플, 중첩 items 체인 → 배열 랭크와 텐서, enum/const를 가진 anyOf → 통합 상수, allOf 합성 → 출처 메타데이터가 붙은 병합 프로퍼티
  • corvusjson CLI, Roslyn 소스 생성기, Blazor 플레이그라운드가 모두 같은 TypeDeclaration 트리를 소비
  • 메타데이터 계층화(코어 분석 → 언어 공급자 어노테이션 → 커스텀 프로세서), JSON Schema Draft 4·6·7·2019-09·2020-12와 OpenAPI 3.0 지원

:pushpin: 아직도 저지르고 있을 C# 고급 실수 15가지

https://truestorydavestorey.medium.com/15-advanced-c-mistakes-youre-probably-still-making-11eafdde5c3a

  • 저자: Dave Storey
  • 태그: csharp #performance #gc

주요 내용

  • ValueTask 의미론 오해, non-readonly struct의 방어적 복사, 제네릭·인터페이스 경계의 숨은 박싱
  • LOH 할당 관리와 ArrayPool, 클로저 캡처로 인한 display class 생성, LINQ 이터레이터 오버헤드와 지연 쿼리 다중 열거
  • 로깅 문자열 보간의 GC 압박과 LoggerMessage 소스 제너레이터, 동등성 계약 위반으로 인한 Dictionary 무결성 문제
  • sealed 미적용에 따른 JIT devirtualization·인라이닝 손실, fire-and-forget async와 Channel<T> 기반 큐
  • 미들웨어의 scoped 의존성 캡처, ConcurrentDictionary 델리게이트 비원자성과 Lazy<Task<T>> 캐시 스탬피드 방지

:pushpin: 소프트 삭제 vs 잊힐 권리 — GDPR 충돌과 익명화 경로

https://medium.com/@ivanball76/soft-delete-vs-the-right-to-erasure-the-gdpr-conflict-and-the-erasure-pathway-e1d350007509

  • 저자: Ivan Ball-llovera
  • 태그: #gdpr #softdelete #domaindesign

주요 내용

  • 소프트 삭제는 데이터를 숨길 뿐 제거하지 않아 GDPR/CCPA의 삭제 의무를 충족하지 못함
  • 소프트 삭제는 생명주기 관리용으로 유지하고 삭제 요구는 IAnonymizable 인터페이스로 분리하는 관심사 구분
  • 개인정보를 가진 애그리게이트가 Anonymize()로 필드를 제자리 덮어쓰되 외래키는 보존
  • [Pii] 특성이 붙은 엔티티가 삭제 경로를 구현했는지 검증하는 아키텍처 fitness 테스트
  • OutboxCleanupService의 이벤트 페이로드 보존 기간 정리, SoftDeletedUserMiddleware의 약 30초 내 액세스 토큰 무효화

:bookmark_tabs: 가벼운 읽을거리

후보 항목 중 이슈로 선정되지 않은 가벼운 읽을거리들


ILSpy 11.0 정식 출시 — WPF에서 Avalonia로 전면 이식

  • WPF 프런트엔드를 완전히 제거하고 Avalonia로 이식해 Linux와 macOS에서도 실행 가능, .NET 10 기반 재빌드
  • 실행 중인 프로세스에서 열기, 북마크, 옴니바 검색 바 추가. VS2017/2019 애드인 제거는 breaking change

Polly 복원력 파이프라인을 커스텀 IOptionsMonitor로 확장

  • 기존 EnableReloads가 DI 컨테이너에서만 모니터를 해석해 커스텀 구성 소스와 목 모니터 기반 단위 테스트가 막히던 문제
  • RS0026 분석기 제약으로 오버로드 대신 EnableReloadsWithMonitor<TOptions>() 별도 이름을 채택한 API 설계 과정

룰 엔진으로 비즈니스 로직 확장하기 — NRules

  • 팩트(facts) → 룰(rules) → 추론 엔진(inference engine) 구조와 NRules의 When(), Match(), Then() 문법
  • 물류 도메인 규칙 7가지를 순수 C# 구현과 나란히 비교, 비절차적 실행으로 디버깅이 어렵다는 한계 명시

Autofac과 Scrutor는 지금도 무엇에 쓰이는가

  • 내장 컨테이너가 이미 제공하는 범위(keyed 등록, 세 가지 수명, open generics)와 Microsoft가 구현하지 않겠다고 선을 그은 경계 구분
  • Autofac이 여전히 필요한 지점(속성 주입, child lifetime scope, Owned<T>)과 두 번째 컨테이너 유지 비용으로서 트리밍·Native AOT 호환성 포기

ASP.NET Core의 2FA와 패스키 기반 최신 인증

  • UserManager/SignInManager로 TOTP 인증기 QR 코드 생성과 복구 코드 처리, Fido2 패키지와 WebAuthn API로 패스키 등록·검증
  • 복제 탐지를 위한 signature counter 검사, 세션 challenge 저장은 개발용이며 프로덕션에서는 분산 캐시가 필요하다는 제약

Meziantou.Framework.SnapshotTesting으로 스냅샷 테스팅

  • 첫 실행 출력을 디스크에 직렬화해 저장하고 이후 실행과 비교, *.verified.*는 커밋하고 *.actual.*은 실패 출력으로 분리
  • ScrubGuid()·UseRelativeDateTime() 등 불안정 값 스크러빙, 이미지 SSIM 임계값 비교, 갱신 전략 4종과 CI 환경 변수 제어

MSIX 패키지 수명 — Remove, Deregister, Destage의 차이

  • 스테이징된 패키지는 불변이고 사용자 간 공유되므로 참조가 하나라도 남으면 디스크에서 제거되지 않는 가비지 컬렉션 모델
  • Destage를 막는 강한 참조 목록(프레임워크 의존성, 프로비저닝, 활성 프로세스, 고정 패키지 등)과 리소스 패키지의 약한 참조 구분
2개의 좋아요