주말 아침 - 주간 닷넷 #26


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


:pushpin: .NET 10.0.7 긴급 보안 업데이트

  • 저자: Rahul Bhandari
  • 태그: dotnet10 #cve #security

주요 내용

  • .NET 10.0.7 OOB(Out-of-Band) 보안 릴리스
  • CVE-2026-40372: Microsoft.AspNetCore.DataProtection이 잘못된 바이트 영역에서 HMAC 검증 태그를 계산
  • 10.0.6 Patch Tuesday에서 주입된 회귀로 복호화 실패 + 권한 상승 가능성
  • 영향 범위: 10.0.0~10.0.6
  • NuGet 패키지와 SDK/Runtime을 즉시 10.0.7로 업데이트 권고

:pushpin: .NET Framework에서 ReadOnlySpan<T>byte[] 할당 제거

  • 저자: Andrew Lock
  • 태그: #performance #readonlyspan #compiler

주요 내용

  • 컴파일러가 byte[] 리터럴을 어셈블리 메타데이터에 임베드하고 ReadOnlySpan<byte>로 노출해 제로 할당 제공
  • System.Memory를 통해 .NET Framework에서도 동작하는 언어/컴파일러 기능 (런타임 의존 아님)
  • .NET 7 이전에는 byte/sbyte/bool만 지원, 다른 primitive는 .NET 7+ 필요
  • static readonly 필드 등 non-const 값에 사용하면 최적화가 무력화되어 매 접근마다 할당 발생
  • collection expression 구문이 일부 unsafe 패턴을 컴파일 시점에 차단하지만 로컬 변수에는 적용되지 않음

:pushpin: .NET Native AOT로 Node.js 애드온 작성하기

  • 저자: Drew Noakes
  • 태그: nativeaot #nodejs #interop

주요 내용

  • C# Dev Kit 팀이 Node.js 네이티브 애드온을 C# + Native AOT로 구현하면서 C++/node-gyp 도구 체인을 대체
  • N-API 안정 C 인터페이스 사용, AOT가 napi_register_module_v1 진입점이 포함된 공유 라이브러리 emit
  • 프로젝트 설정은 PublishAot + AllowUnsafeBlocks 정도로 최소화, 결과물은 .dll/.so/.dylib
  • [UnmanagedCallersOnly] + [LibraryImport]와 커스텀 DLL resolver로 호스트 Node.js 프로세스 익스포트 호출
  • 기여자에게서 Python 의존성 제거, C++에 준하는 성능 + 매니지드 코드 안전성

:pushpin: Postgres를 큐로 그냥 쓰자?

  • 저자: Derek Comartin
  • 태그: #postgres #queue #messaging

주요 내용

  • Postgres를 큐로 사용하려면 가시성 타임아웃, 재시도, DLQ, 순서 보장을 직접 구현해야 함
  • FOR UPDATE SKIP LOCKED로 경쟁 컨슈머 패턴 구성
  • 폴링 빈도와 DB 부하/지연 사이의 트레이드오프
  • 상태와 메시지가 같은 트랜잭션이라 dual-write 문제와 outbox 패턴이 사라지는 장점
  • 직접 만드는 대신 Postgres 기반 메시징 라이브러리 사용 권고

:pushpin: 타 언어 개발자가 .NET 인증을 어려워하는 이유

https://medium.com/@vikpoca/on-why-devs-from-other-languages-find-authentication-in-net-the-most-difficult-part-36dd3cb52cfb

주요 내용

  • .NET은 표준 OAuth2/OIDC를 사용하지만 Microsoft의 SOAP 시대 독자 용어가 그대로 남아 폴리글랏 개발자에게 진입 장벽
  • Passport.js 개념과 1:1로 매핑되는 .NET 용어 (schemes, handlers, ClaimsPrincipal, claims)
  • UseAuthentication(식별)과 UseAuthorization(강제)의 두 계층 미들웨어 모델
  • 흔한 함정: Challenge vs Forbid 혼동, 스킴 명시 누락, 미들웨어 순서
  • "Identity"라는 단어가 ASP.NET Core 생태계에서 4가지 무관한 의미로 쓰이는 점

:pushpin: 언인스톨러의 코드 주입으로 인한 Explorer 크래시

  • 저자: Raymond Chen
  • 태그: windows #internals #debugging

주요 내용

  • 64비트 시스템에서 32비트 Explorer가 크래시되는 원인 분석
  • 서드파티 언인스톨러가 잘못된 호출 규약(__cdecl vs __stdcall)으로 코드 주입
  • 매 호출마다 인자가 두 번씩 pop되며 점진적으로 스택을 손상
  • 결국 SP가 주입된 코드 영역을 가리키며 자기 자신을 덮어쓰고 크래시
  • 이런 Explorer 크래시는 Windows 버그가 아닌 서드파티 주입 신호로 진단

:pushpin: EF Core 성능 — N+1, Cartesian Explosion 및 해결

https://medium.com/@remigiuszzalewski/ef-core-performance-n-1-cartesian-explosion-and-how-to-fix-both-ee4eb679b0ec

  • 저자: Remigiusz Zalewski
  • 태그: #efcore #performance #nplus1

주요 내용

  • 단일 HTTP 요청에서 1,501개의 SQL 쿼리가 발행된 실제 사례
  • 원인: UseLazyLoadingProxies() + virtual 네비게이션 속성이 만들어내는 침묵 라운드트립
  • Select() 프로젝션으로 단일 JOIN(~230ms)으로 축소 가능하지만 Cartesian Explosion 위험
  • 다중 Include()/컬렉션 프로젝션이 행 폭발과 타임아웃을 유발하는 메커니즘
  • AsSplitQuery()로 컬렉션별 쿼리 분리(~700ms), 일관성 vs 성능 트레이드오프

:pushpin: C#의 DateTime vs DateTimeOffset

https://medium.com/@phuonganhnthi98/datetime-vs-datetimeoffset-in-c-what-you-get-wrong-until-you-dont-ab1bce6f99b1

주요 내용

  • DateTimeKind는 약한 힌트일 뿐, DateTimeOffset은 명시적 UTC 오프셋을 항상 저장
  • DateTime 동등성은 Kind를 무시해 다른 시점도 같다고 판정, DateTimeOffset은 UTC instant로 비교
  • 미지정 KindDateTime이 직렬화될 때 발생하는 모호한 JSON과 DateTimeOffset의 명시적 오프셋
  • DB 저장 차이 (SQL Server datetime2 vs datetimeoffset, PostgreSQL timestamptz)
  • DST 전환에서 로컬 DateTime 기반 스케줄링이 깨지는 사례, 타임존 ID를 별도 저장하는 권장

:pushpin: 코드 품질의 6가지 기둥

https://towardsdev.com/6-pillars-of-code-quality-494eba3526d5

  • 저자: Chatri Ngambenchawong
  • 태그: #quality #design #architecture

주요 내용

  • 가독성: 메서드 ~20줄 미만, 비즈니스 어휘에 정렬된 명명
  • 결정성: DateTime.Now/Random 회피, 가변 상태 격리, 명시적 null 처리
  • 오용을 어렵게 만들기: 타입 시스템 + value object + 불변성으로 컴파일 타임 안전성
  • 모듈화: DDD, 관심사 분리, DI, 복잡도에 맞는 아키텍처 선택
  • 테스트 가능성: 작은 메서드, DI를 통한 모킹, 엣지 케이스, table-driven 테스트

:bookmark_tabs: 가벼운 읽을거리

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


C#의 Record vs Class: 언제 무엇을 쓸 것인가

  • record는 값 동등성 + 불변성, class는 참조 동일성 + 가변성
  • EF Core는 변경 추적 때문에 가변 class 선호, API DTO에는 record 적합

마법사를 넘어: .NET 업그레이드의 새 표준 Modernization Chat

  • VS 2026 / VS Code의 Modernization Chat이 기존 .NET Upgrade Assistant를 대체
  • Assess-Plan-Execute 사이클로 평가/계획 문서 생성, 다단계 변환을 Git에 추적

LINQ GroupBy와 IGrouping

  • GroupBy를 출력 포매팅이 아닌 도메인 모델링 관점에서 활용
  • 단일/복합 키 그룹핑과 지연 평가, 조기 Dictionary 변환의 함정

.NET Feature Management: 타겟팅 필터로 프로덕션 패턴 구성

  • TargetingFilter로 사용자 ID, 그룹, 비율 기반 점진적 롤아웃과 A/B 테스트 구현
  • ITargetingContextAccessor로 인증 시스템과 연동, appsettings.json 구성과 컨트롤러 사용 예제

DI 서비스 클래스에 Primary Constructor 적용

  • Primary constructor로 필드와 생성자 보일러플레이트 제거, 4~5개 의존성의 ASP.NET Core 서비스에 적합
  • 매개변수가 readonly가 아니어서 재할당해도 컴파일러 경고가 없는 함정

C# .NET 컬렉션 내부 — Dictionary

  • buckets/entries 분리 구조와 인덱스 기반 체이닝, 캐시 친화적 next 필드
  • 삭제 Slot 재활용 free list, 임계치 도달 시 두 배 리사이즈, 동시 변경 감지 버전 카운터

C# 코루틴: 협력적 프로그래밍 실용 가이드

  • C#에는 일급 코루틴이 없으며 iterator(yield return)와 async/await가 컴파일러 생성 상태 머신으로 대체
  • iterator의 lazy sequence와 async의 I/O 대기 동안 스레드 해제, Win32 “Co” 접두사가 COM 관련임을 명확화
3개의 좋아요