한 주 동안 .NET 생태계에서 있었던 주요 이슈와 아티클, 기술 트렌드를 정리해 소개합니다.
C# 15의 조용한 확장 — collection expression with(...)와 union 키워드
https://medium.com/@Rajdip27/c-15-quietly-expanded-and-its-a-bigger-deal-than-you-think-73c7c32d253f
- 저자: Santanu Chandra
- 태그: #csharp15 #collectionexpressions #uniontypes
주요 내용
- 컬렉션 표현식 인자(
with(...)절): 생성자 인자(capacity, comparer 등)를 컬렉션 표현식 안에서 직접 전달 with(...)는 표현식의 첫 요소 위치에 와야 한다는 제약union키워드 도입으로 합 타입(sum type) 선언, 패턴 매칭 시 컴파일러가 망라성(exhaustiveness) 강제- 값 타입의 union 사용 시 박싱 오버헤드 트레이드오프
- 짧은 코드 샘플(List with capacity, Pet union/switch) 시연
EF Core 페이지네이션 후속편 — Keyset, 정렬 그리드, htmx, 인덱싱 비용
- 저자: Chris Woodruff
- 태그: #efcore #pagination #htmx
주요 내용
- Keyset 페이지네이션 채택 조건을 “큰 테이블 AND 쓰기 빈도 높음 AND 사용자 노출” 세 가지로 좁힘
- 고정 정렬은
(CreatedAt, Id)복합 커서/인덱스로 단순하지만, 동적 정렬은SortColumn/Direction/KeyValue/Id커서와 switch 디스패치(4컬럼 기준 약 80줄)로 비용 증가 - 모든 keyset 정렬 컬럼은 PK로 끝나는 커버링 복합 인덱스 필요. 1천만 행·8컬럼 시나리오에서 4개 인덱스가 약 1GB 차지, 쓰기 증폭 발생
- htmx의
hx-trigger="revealed"센티넬 행과?handler=Sort핸들러로 무한 스크롤·정렬 변경 구현, 커서는 불투명 토큰으로 인코딩 - ~5만 행 미만, 관리자 UI의 “N페이지로 점프”, 정적 데이터, 12개 이상 동적 정렬 컬럼에서는 offset이 더 적합
Dapper at Scale — 저장 프로시저로 오후를 날린 5가지 교훈
- 저자: Tim Turner
- 태그: #dapper #storedprocedures #datalayer
주요 내용
- 인라인 SQL과 SP 혼용보다 SP로 완전 통일 권장 (반쪽짜리 마이그레이션의 위험성)
- 시드 데이터 멱등 배포: 고정 데이터셋은 블록 단위 가드, 증가 데이터셋은 행 단위 가드
- 모든 SP가 출력 파라미터(
@ErrorMessage,@ErrorFound)로 에러 보고하는 표준화된 규약 IDapperBase추상화로 파라미터 바인딩/출력 파라미터 처리 보일러플레이트 제거- 패턴 이식 시 암묵적 전제(예: SP의 NULL 기본값 vs
DBNull명시 전달) 확인의 중요성
C# 구조체에서 강타입 제로카피 뷰까지
https://medium.com/@zabavnov/from-structs-to-strongly-typed-zero-copy-views-in-c-2119a8dab661
- 저자: Vadim Zabavnov
- 태그: csharp #refstruct #zerocopy
주요 내용
- 값 의미론 관점에서
ref,in,ref readonly매개변수의 차이를 정리 ref struct가 스택에만 존재하도록 강제되는 제약이 안전성을 보장하는 핵심 이유- ref 기반 추상화는 상속이 아니라 provider/cursor/projection/bounds/driver로 분리한 컴포지션 권장
- Sudoku 풀이(행/열/블록 통합 로직), 다차원 디바이스 메모리 검사(5차원 커서를 flat 버퍼에 매핑)를 사례로 사용
- API 복잡도 증가, 수명 제약, 힙 기반 다형성 상실, 인지 부담 등 트레이드오프 명시
팬아웃 동시성 포스트모템 — Task.WhenAll이 1,400 RPS를 5,600 RPS로 증폭시킨 사례
- 저자: Bhautik Kapadiya
- 태그: #concurrency #postmortem #resilience
주요 내용
- 음식 배달 플랫폼 주문 집계 서비스가 트래픽 피크에서 120ms → 4,800ms 레이턴시로 악화된 사례
- 요청당 4개 다운스트림 병렬 호출(
Task.WhenAll)이 1,400 RPS를 5,600 RPS로 증폭시켜 커넥션 풀 고갈 - 근본 원인 4가지: 무제한 트래픽 증폭, bounded concurrency 부재, 글로벌 deadline 부재, async/await의 자동 scalable 오해
- 해결책:
SemaphoreSlim으로 동시 호출 제한,CancellationToken글로벌 deadline, Polly로 retry/circuit breaker, 비핵심 호출 graceful degradation
AutoStack.Identity — 무의존성 .NET 10 SAML 2.0 / JWT / XML 서명 라이브러리 만들기
주요 내용
- 헬스케어 SSO 통합 시 Microsoft.Identity.Web의 SAML 미지원, 서드파티 SAML의 미들웨어 결합·테스트 난이도, 보안 감사에서 발견된 토큰 리플레이 취약성이 자체 구현 동기
- JWT(RS/ES/HS 256·384·512), SAML 2.0 SP/IdP 플로우, 임의 XML 디지털 서명 검증 세 가지 핵심 기능
IJwtSigner/IJwtVerifier인터페이스로 프로토콜과 암호 연산 분리,TimeProvider주입으로 만료 테스트 결정성 확보- 표준 충실 구현(RFC 7518 ECDSA의 IEEE P1363 포맷, HMAC 타이밍 안전 비교)과 자체 구현 유틸(Base64URL) 트레이드오프
- XML 정규화에서 공백·네임스페이스 처리가 서명 검증에 미치는 민감성
.NET 백엔드의 멱등성 설계 — 키, 해시, DB 제약, Outbox까지
- 저자: Oshadha Thrimavithana
- 태그: dotnet #idempotency #backend
주요 내용
- 재시도, 메시지 재전송 등으로 발생하는 중복 처리 문제와 멱등성 정의
Idempotency-Key헤더 + 요청 페이로드의 SHA-256 해시 저장으로 오용 감지- 애플리케이션 레벨 체크만으로는 동시성에서 부족 — DB에
(Key, Operation)유니크 제약 권장 - 비즈니스 변경과 멱등성 레코드를 단일 트랜잭션 안에서 원자적으로 커밋
- Inbox/Outbox 패턴을 결합해 at-least-once 메시지 전달 환경에서 안전성 확보
Task를 ValueTask로 교체했더니 — 핫패스에서 0 byte 할당 경험
- 저자: Serkan Özbey Kurucu
- 태그: #valuetask #performance async
주요 내용
Task<T>는 동기 완료 경우에도 힙 할당, 고처리량 시 GC 압박ValueTask<T>는 struct로 동기 완료 시 스택 보관, 진짜 비동기일 때만 Task 래핑- 95% 캐시 적중 메서드 벤치마크에서 ValueTask는 0 byte 할당, Task는 지속적 할당
- 적합: 캐시 조회, 커넥션 풀, 프로듀서-컨슈머 같은 동기 완료 빈도 높은 핫패스 / 부적합: 공개 API, 다중 await, 네트워크/디스크 I/O
ValueTask<T>는 단 한 번만 await 가능
OpenTelemetry 로그에 Serilog 스타일 destructuring 도입하기
- 저자: Sébastien de Salvador
- 태그: #opentelemetry #serilog #logging
주요 내용
- Serilog → OpenTelemetry 마이그레이션 시 잃게 되는 자동 객체 destructuring(중첩 속성을 쿼리 가능한 필드로 평탄화) 문제 제기
- Serilog의
@prefix 구문이 OpenTelemetry에는 기본 미제공 SerilogLikeDestructuringProcessor를 파이프라인에 끼워@접두 attribute를 감지해 JSON(camelCase) 직렬화 후 교체- 실패 시
ToString()으로 fallback - 기존 Serilog 코드 패턴과 관측성 투자를 보존하면서 OpenTelemetry로 점진 전환 가능
.NET 현대화 Part 26 — ASP.NET Core Rate Limiting 미들웨어로 40초 → 1초
- 저자: Michael Kopt
- 태그: aspnetcore #ratelimiting #middleware
주요 내용
- 무제한 동시 요청 시 40초+ 응답 스파이크가 PermitLimit 25 적용 후 1초 미만으로 감소한 사례
- 시간 윈도우가 아닌 Concurrency Limiter 전략을 채택해 스레드풀 고갈 방지
PartitionedRateLimiter.Create<HttpContext, string>기반 구체 코드 — PermitLimit, QueueLimit, FIFO 큐 설정UseRateLimiter()를 라우팅 뒤, 인가 앞에 배치하라는 파이프라인 가이드- PermitLimit 10~25에서 시작, 피크 시 CPU 70% 미만 유지 권장
Shiny.DocumentDb v6 — 벡터 검색과 전역 쿼리 필터
- 저자: Allan Ritchie
- 태그: #documentdb #vectorsearch dotnet
주요 내용
- 벡터/ANN 검색 추가: pgvector, SQL Server 2025
VECTOR_DISTANCE, Cosmos DiskANN, MongoDB Atlas$vectorSearch, DuckDBvss로 네이티브 변환 ReadOnlyMemory<float>와Microsoft.Extensions.AI.Embedding통합- EF Core
HasQueryFilter형식의 전역 쿼리 필터 — 읽기·단건·대량·체인지 스트림에 일괄 적용, 명명 필터는 선택적 비활성화 가능 CreateIndexAsync<T>(ctx.User, u => u.LastName, u => u.FirstName)형태의 복합 JSON 인덱스 지원- PostgreSQL/MySQL/SQL Server에서 세마포어 직렬화를 제거하고 ADO.NET 드라이버 풀링 사용, AOT 호환 유지
가벼운 읽을거리
후보 항목 중 이슈로 선정되지 않은 가벼운 읽을거리들
.NET 개발자를 위한 Python — 타입, 클래스, 레코드, 인터페이스 매핑
- Python의 동적 타이핑과 C# 정적 타이핑,
self/__init__명시,new키워드 부재 같은 차이를 한쪽씩 매핑 - C# record ↔ Python
@dataclass, 인터페이스의 ABC(명목) vs Protocol(구조) 두 접근 비교
Dapper로 EF Core 없이 낙관적 동시성 구현하기
LastUpdatedDateTime 컬럼을 동시성 토큰으로 사용, UPDATE의 WHERE 절에 타임스탬프 비교 추가- 영향 행 수 0이면 충돌로 판정해 HTTP 409 반환, 클라이언트에
LastUpdated를 함께 반환하는 읽기-수정-쓰기 3단계 패턴
ConsoleLogStreaming — SSE로 분산 앱 콘솔 실시간 스트리밍
AddConsoleLogStreaming()+UseConsoleLogStreaming()미들웨어 등록만으로 콘솔 출력을 REST API로 노출- 브라우저는 EventSource(SSE)로
/console-logs구독, 워크플로 디자이너·디버깅 UI 같은 라이브 출력 대시보드용
ToLookup() — 가장 저평가된 LINQ 기능
- 1:N 관계에서
Dictionary<TKey, List<TValue>>대신ILookup<TKey, TValue>활용, 즉시 실행 후 메모리 캐싱 - 반복 조회 시
Where()재스캔(O(n))을 O(1) 인덱스로 대체, 존재하지 않는 키 접근 시 빈 컬렉션 반환
ToList()의 숨겨진 비용
- 1000만행 운영 환경에서
ToList()가 즉시 메모리 할당과 GC 압박을 유발,Where()로 메모리 필터링하는 안티패턴 - SQL 단에서 미리 필터링하고
Select()로 필요한 컬럼만 가져오는 패턴 권장, lazy loading과 결합 시 N+1 위험
JetBrains Rider 2026.2의 WPF Hot Reload
- Rider 2026.2 EAP 2부터 디버거 실행 중 XAML 편집을 실시간 반영, 대상 TFM은 .NET 9.0-windows / .NET 10.0-windows / .NET Framework
- NuGet 추가, 새 컨트롤/윈도/페이지 추가,
x:Class·루트 타입 변경, 런타임 리소스/테마 사전 변경 시는 재시작 필요
ReflectionIT.PropertyThrowGenerator — partial property에 가드 절 자동 주입
[ThrowIfNull],[ThrowIfGreaterThan(...)],[ThrowIfNegative]등 속성 부착만으로 setter 검증 코드를 Roslyn 소스 생성기가 생성- 내부적으로 .NET 8의
ArgumentException.ThrowIf...헬퍼 호출, C# 14 / .NET 8 이상 필요
Windows 11 WinUI 전략 변화 — 네이티브 앱 권장과 셸 재작성
- "WinUI 3"에서 버전 표기를 제거하고 그냥 "WinUI"로 리브랜딩, 향후 대규모 breaking change 없음을 시사
- Windows 11 셸과 시작 메뉴를 React Native에서 네이티브 WinUI로 재작성, 엔터프라이즈용 DataGrid·Charting 컨트롤 추가 예정
