주말 아침 - 주간 닷넷 #36


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


:pushpin: .NET 11 Preview 5 탐구 — Process API의 교착 상태 해결

  • 저자: Andrew Lock
  • 태그: #dotnet11 #processapi #concurrency

주요 내용

  • 기존 stdout/stderr 순차 읽기 방식에서 버퍼 오버플로우로 교착 상태가 발생하는 메커니즘
  • 신규 API ReadAllText(), ReadAllLines(), ReadAllBytes(), RunAndCaptureText()의 동기/비동기 지원 추가
  • Windows에서는 겹친 I/O, Unix에서는 비블로킹 poll 기반 멀티플렉싱으로 양쪽 파이프를 병렬 드레인
  • Datadog의 실시간 프로세스 출력 처리 사례
  • 동기 API는 스레드를 블록하며 타임아웃 미설정 시 무한 대기 가능

:pushpin: 실행 중인 .NET 프로세스에 C# REPL 주입하기

  • 저자: Will Fuqua
  • 태그: dotnet #repl #debugging

주요 내용

  • csharprepl이 시작 훅(startup hook)과 격리된 어셈블리 로드 컨텍스트로 실행 중인 .NET 프로세스에 C# 스크립트 엔진 주입
  • 프로세스 중단 없이 라이브 상태에서 캐시·서비스 값을 읽고 쓰는 예제
  • 배열 인덱스 오버플로우 버그를 라이브로 재현하고 #replace, #wrap 명령으로 메서드를 동적 교체
  • dotnet tool install -g csharprepl 설치와 ASP.NET Core 템플릿 적용 절차
  • .NET 10 전용, 제네릭 메서드·포인터 매개변수·단일 파일 배포 미지원 등 제약사항

:pushpin: AI가 작성한 스레드 안전 카운터, CPU가 5배 느리게 만들다

  • 저자: Vasyl
  • 태그: #falsesharing #cachelines #performance

주요 내용

  • AI가 생성한 락 없는 멀티스레드 카운터(long[] counters)가 벤치마크에서 5배 느리게 동작
  • CPU 캐시 라인(x86 64바이트/Apple Silicon 128바이트) 단위 메모리 접근과 거짓 공유(false sharing) 발생 원리
  • [StructLayout(LayoutKind.Explicit, Size=128)] 패딩 구조체로 카운터를 캐시 라인별로 분리하는 해결 코드
  • 인접 배치 464ms/397ms 대 패딩 배치 85ms(4.7~5.4배 차이) 벤치마크 결과
  • 메모리 비용 증가 트레이드오프와 초당 수백만 쓰기가 발생하는 핫 패스로 적용 범위 한정

:pushpin: .NET 호스트 프로세스 — Main() 실행 전과 가끔 멈추는 이유

  • 저자: David (dotNetDave) McCarter
  • 태그: dotnet #hostprocess #benchmarkdotnet

주요 내용

  • dotnet.exe/apphost → hostfxr → hostpolicy → CoreCLR → Main()으로 이어지는 호스팅 파이프라인 구조
  • hostfxr의 런타임 버전 선택과 .deps.json/.runtimeconfig.json 처리 과정
  • BenchmarkDotNet 실행 중 호스트 프로세스가 멈추는 원인들(포그라운드 스레드 잔존, hosted service 미종료, .Result/.Wait() 블로킹 등)
  • DOTNET_HOST_TRACE 환경변수와 Process Explorer를 이용한 디버깅 절차
  • dotNetTips.Spargine.Benchmarking에서 [MemoryDiagnoser] 속성 제거로 hang을 해결한 사례

:pushpin: 관리자 패널에 감사 추적을 추가한 이유와 놓칠 뻔한 허점

https://medium.com/@nickzdanovych/why-i-added-an-audit-trail-to-our-admin-panel-and-the-gap-i-almost-missed-17ab89■■4da2

  • 저자: Nick Zdanovych
  • 태그: #efcore #auditing dotnet

주요 내용

  • EF Core의 SaveChanges 파이프라인에 Audit.NET을 연동해 필드 단위 변경 diff와 요청자 정보를 자동 기록
  • ExecuteDeleteAsync/ExecuteUpdateAsync 등 대량 작업이 변경 추적기를 우회해 감사 기록이 남지 않는 문제 발견 경위
  • 소스 코드를 정규표현식으로 스캔해 미감시 대량 작업 호출을 탐지하는 테스트 작성
  • SQL Server temporal tables, Audit.NET, 수동 구현 사이의 선택 기준과 옵트인 방식 감시 대상 관리

:pushpin: EF Core의 N+1 쿼리 문제

  • 저자: Chris Woodruff
  • 태그: #efcore #n1query #performance

주요 내용

  • 부모 행 로드 1회 후 관련 값을 위해 N번 추가 쿼리가 실행되는 N+1 문제의 발생 원인
  • 지연 로딩 루프, 명시적 쿼리 루프, 직렬화 중 쿼리, 쓰기 작업 N+1의 4가지 유형 분류
  • DbCommandInterceptor로 쿼리 수를 계산하고 통합 테스트에 쿼리 예산을 설정하는 탐지 방법
  • Include/ThenIncludeAsSplitQuerySelect 투영 순서의 3단계 해결책
  • 대량 리스트 조회 등 특정 상황에서만 외부 도구를 제한적으로 활용하는 기준

:pushpin: DI 결합 함정 — .NET 라이브러리가 스스로의 기능을 가로막을 때

https://medium.com/@zand.arash83/the-di-coupling-trap-when-net-libraries-block-their-own-capabilities-a8284716706f

주요 내용

  • 공개 API가 IServiceProvider.GetRequiredService<T>()로 의존성을 강제 해결해 DI 컨테이너 없는 사용 시나리오를 차단하는 구조
  • 써드파티 설정, 멀티테넌트, 공유 인스턴스, 테스트 등 4가지 차단 시나리오
  • Polly 라이브러리 사례를 통한 문제-해결 패턴 비교
  • RS0026 분석기 경고 억제 시점과 null 가드 배치 위치 관련 구현 트레이드오프

:pushpin: CQRS 데코레이터 파이프라인 — 핸들러를 건드리지 않고 로깅·캐싱·트랜잭션 처리

https://medium.com/@ivanball76/the-cqrs-decorator-pipeline-logging-caching-and-transactions-without-touching-a-handler-fb7679b8bde8

  • 저자: Ivan Ball-llovera
  • 태그: #cqrs #decoratorpattern dotnet

주요 내용

  • Command/Query별 데코레이터 실행 순서(FeatureGate→Logging→Caching→Validating→Transactional)와 각 계층의 근거
  • ITransactional, ICacheInvalidating, IQueryCacheable 등 opt-in 마커 인터페이스
  • 예외/비즈니스 실패/성공에 따른 트랜잭션-캐시 무효화 동작 정리
  • Scrutor의 TryDecorate가 역순 등록되는 특성 때문에 AddApplicationDecorators()를 마지막에 등록해야 하는 이유

:pushpin: C#의 Discriminated Union, 이번엔 정말이다

  • 저자: Maarten Balliauw
  • 태그: csharp #discriminatedunions #dotnet11 #patternmatching

주요 내용

  • 새로운 union 키워드로 언어 차원의 discriminated union 지원 도입
  • 여러 타입 중 정확히 하나를 나타내는 타입 선언과 exhaustiveness checking(누락 케이스 자동 검출)
  • 암시적 형식 변환으로 보일러플레이트 제거, 패턴 매칭 시 명시적 언래핑 불필요
  • 기존 OneOf 패키지·Results<> 대비 개선점과 null 처리, 메서드/속성 포함 가능
  • 참조 타입이 필요한 경우 [Union] 속성 기반 커스텀 구현 방식

:pushpin: cDAC 방식으로 읽는 CLR 내부 — DAC 대신 계약(Contract)

  • 저자: Christophe Nasarre
  • 태그: #clr #dotnetruntime #diagnostics #internals

주요 내용

  • DAC(Data Access Component)를 대체하는 cDAC(Contract Data Access Component)의 설계 원리
  • DotNetRuntimeContractDescriptor 심볼에서 시작하는 JSON 기반 메타데이터·버전 관리 구조
  • 로컬 프로세스, 원격 프로세스, 메모리 덤프를 동일한 관리 코드로 읽는 통합 방식
  • “Has*” 가드를 통한 필드·계약 버전 하위 호환성 처리와 GC 전용 descriptor 병합 구조
  • ClrMD 없이 구현한 !eeheap 명령 클론 예제와 GitHub 저장소(RuntimeDataContract) 공개

:bookmark_tabs: 가벼운 읽을거리

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


C# 14의 Extension Members — 다음 ‘이게 클린 코드인가’ 논쟁을 일으킬 기능

  • 프로퍼티, 연산자, 정적 멤버까지 확장 가능해진 C# 14의 extension 블록 문법
  • IDE 이동/자동완성에서 예상과 다른 동작, 조용한 멤버 무시 등 찬반 논쟁 근거

Windows 11 레거시 대화상자, WinUI 3로 전환

  • Windows 8 시절 검색 참, “로컬 계정으로 전환” 등 구식 대화상자가 WinUI 3 현대화 대상에 포함
  • Run 대화상자 응답 속도 94ms(신규) vs 103ms(기존) 비교, WinRE 등 추가 대상 예고

Jon Skeet의 C# 매개변수 전달 방식

  • 참조 타입(클래스)과 참조 매개변수(ref)를 구분하고 값/ref/out/params 네 가지 전달 방식 비교
  • string 등 불변 타입이 참조 타입이면서 값처럼 동작하는 이유를 코드 예제로 정리

.NET 10 dnx — 설치 없이 .NET 도구 실행하기

  • npx에 비유되는 dnx로 전역 설치 없이 도구를 다운로드-실행-자동정리
  • dnx dotnetsay, dotnet tool exec pkg@version 등 CLI 명령과 .config/dotnet-tools.json 매니페스트 자동 인식
3개의 좋아요