한 주 동안 .NET 생태계에서 있었던 주요 이슈와 아티클, 기술 트렌드를 정리해 소개합니다.
.NET 11 Preview 3 — StringBuilder.MoveChunks로 ToString 할당 회피
- 저자: Andrew Lock
- 태그: #dotnet11 #performance #roslyn
주요 내용
- 새 static 메서드
MoveChunks는 한 StringBuilder의 내부 버퍼를 다른 인스턴스로 이전하고 원본을 비움 char[]청크 참조만 이동시켜 실제 데이터 복사 없이 동작 — 큰 문자열에서 ToString보다 훨씬 빠름- 주요 용도는 Roslyn 소스 생성기에서
SourceText를 만들 때 발생하는 중간 문자열 할당 제거 - 단순 재할당과 달리 기존 참조 보유자는 불변 스냅샷을 유지해 다운스트림 변조 차단
- .NET 11+ 필요. 소스 제너레이터는 netstandard2.0 타겟이라 호환성 작업이 선행돼야 함
Unity와 부동소수점 — Mono의 float→double 캐스팅이 만든 70배 성능 격차
- 저자: Aras Pranckevičius
- 태그: #unity #floatingpoint #mono
주요 내용
- Unity Mono 런타임이 32비트 float를 내부적으로 double로 변환해 계산하는 역사적 결함
UnityEngine.MathfvsSystem.MathFvsUnity.Mathematics의 어셈블리 수준 코드 생성 차이- 10M 반복 sqrt 벤치: Mathf 282ms / MathF 186ms / Burst+Mathematics 35ms
- Burst는
System.MathF를 지원하지 않아 백엔드별 최적 선택지가 달라지는 파편화 - 향후 CoreCLR 마이그레이션이 가져올 개선 전망
SQL Server에서 UUID v7의 진짜 한계 — 바이트 정렬 심층 분석
- 저자: Pankaj Ikhar
- 태그: #sqlserver #uuidv7 #indexing
주요 내용
- SQL Server의
uniqueidentifier정렬은 바이트 10-15부터, 그다음 8-9, 마지막에 0-5 순으로 비교 - UUID v7은 48비트 타임스탬프를 바이트 0-5에 두므로 SQL Server 인덱스에서는 v4와 거의 동일한 랜덤 패턴
- SQL Server에서는 PostgreSQL/MySQL과 달리 v7 이점이 사라지며 단편화 발생
- 실제 사례에서
Guid.CreateVersion7()로 전환 후 인서트 시간이 20분에서 수 시간으로 증가 - 권장:
NEWSEQUENTIALID()+ 별도 CreatedAt 컬럼, SQL Server 2025도 네이티브 v7 미지원
.NET의 Outbox 패턴 — PostgreSQL + RabbitMQ + MassTransit 구현
- 저자: Hamed Salameh
- 태그: dotnet #messaging #outboxpattern
주요 내용
- DB와 메시지 브로커 간 원자적 트랜잭션 부재로 인한 메시지 유실 문제 정의
- 비즈니스 상태와 outbox 레코드를 단일 트랜잭션에 기록, 별도 디스패처가 비동기 발행
- at-least-once 전달을 보장. 순서 보장은 분리된 관심사로 명시
- .NET 10, PostgreSQL, RabbitMQ, MassTransit 조합으로
FOR UPDATE SKIP LOCKED폴링 디스패처 구현 - 포이즌 메시지 처리(5회 실패 후 중단), 행 잠금 기반 수평 확장, 처리완료 메시지 정리, lag/dead 메트릭 관측 등 운영 고려사항
메시지 펌프는 트랜잭션 디테일에서 실패한다
- 저자: Daniel Marbach
- 태그: #messaging #nservicebus #transaction
주요 내용
- 메시지 펌프는 브로커 ack, DB write, outgoing send 조율 과정에서 안전성과 처리량의 트레이드오프 발생
- RabbitMQ, Azure Storage Queues 등 receive-only 트랜잭션: ack가 애플리케이션 효과와 분리되어 중복 처리 또는 ghost message 위험
- 클라우드 큐의 visibility timeout 갱신 책임을 펌프가 떠안게 되며 복구 속도와 중복 처리 간 균형 필요
- read-deserialize-dispatch 루프가 logging, retry, DI, middleware 등으로 확장되며 플랫폼화
- 자체 구축 vs 채택 결정 — 프로덕션급 메시지 펌프는 NServiceBus 같은 기성 솔루션이 합리적
저장된 JSON을 마이그레이션하지 않고 C# 타입 진화시키기
- 저자: Egil Hansen
- 태그: #json #systemtextjson #migration
주요 내용
Egil.SystemTextJson.Migration라이브러리: 역직렬화 시점에 자동 타입 마이그레이션 수행[JsonMigratable]어트리뷰트와IMigrateFrom<TFrom, TTo>인터페이스로 타입 진화 선언- 사용 사례: 저장 데이터, 컨트랙트 라이브러리, 블루/그린 배포, 버전 관용 API
- 빅뱅 DB 마이그레이션, 수동 read-side 변환, 커스텀 JsonConverter, 버전 엔드포인트와의 비교
- 브라운필드 도입 경로와 성능 트레이드오프
줄바꿈은 \r과 \n만이 아니다 — 유니코드 줄바꿈 처리
- 저자: Gérald Barré (meziantou)
- 태그: dotnet #strings #unicode
주요 내용
- 유니코드는
U+0085,U+2028,U+2029도 줄바꿈으로 인식 Regex.Split+(?>\r\n|[\n\v\f\r ])패턴 사용string.ReplaceLineEndings()활용- .NET 9의
Regex.EnumerateSplits()로 할당 최소화 - Meziantou.Framework
SplitLines()의ReadOnlySpan<char>활용
리라이트 없이 레거시 .NET 애플리케이션 현대화하기
- 저자: Adrian Bailador
- 태그: dotnet #legacy #modernization
주요 내용
- .NET Upgrade Assistant로 .NET Framework에서 .NET 9 LTS로 점진적 이동, Testcontainers 기반 characterization 테스트로 동작 검증
- EF6 EDMX에서 EF Core Code First로 스키마/저장 프로시저 매핑 유지하며 마이그레이션
- 정적 서비스 로케이터를 ASP.NET Core 생성자 주입 DI로 교체, 동기 I/O를 async 전체 스택으로 변환
- Serilog 구조화 로깅, Polly v8 resilience pipeline(retry/circuit breaker/timeout) 적용, liveness/readiness 헬스 체크 분리
- Strangler fig 패턴과 anti-corruption layer로 새 엔드포인트를 레거시와 병행 운영하며 feature flag로 점진 전환
듀얼 모드 Windows GUI/콘솔 애플리케이션 만들기
주요 내용
- Windows PE 헤더는
WinExe혹은Exe둘 중 하나만 가능해 동시 동작이 까다로움 - 방법 1: GUI 앱이
AttachConsole/FreeConsoleP/Invoke로 콘솔에 연결 — GUI가 즉시 프롬프트로 복귀하며 출력이 어색하게 끊김 - 방법 2: 콘솔 앱이 GUI를 띄우는 방식 — 항상 콘솔 창이 잠깐 표시되고 깜빡임 발생
- 방법 3: GUI/CLI를 별도 실행파일로 분리하고 비즈니스 로직은 공유 라이브러리로 — 빌드는 복잡해도 가장 깔끔
- Strahl의 결론은 실용성/유지보수성 측면에서 별도 실행파일 분리가 최선
EF Core in Clean Architecture, 실용적 접근
- 저자: Anton Martyniuk
- 태그: #efcore #cleanarchitecture #ddd
주요 내용
- 전통적 Repository 래핑은 "추상화 위 추상화"로 메서드 폭발과 책임 모호화를 초래
- Application 계층이
Microsoft.EntityFrameworkCore/DbContext에 직접 의존하되 Domain은 프레임워크 무관 유지 - “DB 교체” 명분은 실제로 거의 발생하지 않으며 발생해도 Repository로 보호되지 않음
- 모킹 대신 Testcontainers + 실제 DB(PostgreSQL/SQL Server)로 쿼리 변환 이슈를 조기 포착
- 재사용은
IQueryable<T>확장 메서드나 Specification 패턴으로 가볍게 처리
VS Code가 5만 번 평가에서 배운 것 — 모델별 토큰 사용량 70배 차이
- 저자: VS Code Eval Team
- 태그: #vscode llm #eval
주요 내용
- 30개 모델에 대해 동일한 smoke test(
say_hello, 5글자 파일 생성)를 6개월간 50,974회 실행 - 동일 결과를 내면서도 모델별 출력 토큰 사용량이 55 ~ 3,676 토큰으로 약 70배 차이
- 오버헤드 패턴 분류: 과도한 계획(52~99%), 워크스페이스 탐색(56~96%), 장황한 narration, 잘못된 도구 선택, API 대신 터미널 명령 사용
- 모델 크기와 효율성 무관 — mini 모델이 오버헤드 1위인 반면 큰 모델이 절제된 토큰 사용을 보임
- 권장: pass rate만이 아닌 도구 호출 시퀀스를 캡처하는 가벼운 baseline eval 운영
가벼운 읽을거리
후보 항목 중 이슈로 선정되지 않은 가벼운 읽을거리들
내가 본 가장 비싼 C# 4줄 — 빈 catch 블록이 만든 11개월 은폐 장애
- 결제 재시도 핸들러의 빈 catch 블록이 인증서 회전 실패를 11개월간 은폐, 6시간 다운타임과 38,000건 주문 손실
throw ex;는 스택 트레이스를 리셋하므로throw;를 써야 하고, 광범위 예외 처리는 모니터링이 장애를 감지하지 못하게 만듦
LINQ의 All·Any·Contains — 도메인 진실을 표현하는 방법
Any()는 존재성 + 단락 평가,All()은 빈 컬렉션에서true를 반환하는 “공허한 참” 함정 (KYC 사례)Contains()의 HashSet O(1) vs List O(n) 차이와 커스텀IEqualityComparer로 도메인 동등성 정의
Microsoft.UI.Reactor로 파일 기반 WinUI 앱 만들기
- 단일
App.cs파일에#:디렉티브로 의존성·SDK·타겟 프레임워크를 선언해 프로젝트 파일 없이 동작 - 콘솔 모드로 기본 동작하고 필요 시 네이티브 WinUI 창을 띄우는 하이브리드 구조, 유틸리티·프로토타입에 적합
sqlite-utils 4.0rc1 — 마이그레이션과 중첩 트랜잭션
- 데코레이터 함수로 스키마 변경을 정의하고 CLI/Python API로 실행하는 마이그레이션 시스템 통합
db.atomic()컨텍스트 매니저로 SQLite savepoint 기반 중첩 트랜잭션,INSERT ... ON CONFLICT SET표준 upsert 채택
CancellationToken Async/Await 완전 가이드
- 협력적 취소 모델, 모든 await에 토큰 전파,
OperationCanceledException을 일반 예외와 분리 처리 CancellationTokenSource해제와CreateLinkedTokenSource로 타임아웃/요청중단/앱종료 통합
Durable Functions 오케스트레이션과 체이닝 패턴 입문
- Durable Functions가 상태·Correlation ID·히스토리 테이블을 자동 관리, Orchestrator/Activity/Client 역할 분리
- 결정론 요구사항(
DateTime.UtcNow대신context.CurrentUtcDateTime)과 리플레이/크래시 복구 메커니즘
EF Core 단위 테스트 — InMemory vs SQLite 비교
UseInMemoryDatabase는 FK/UNIQUE/트랜잭션을 강제하지 않아 리포지토리 테스트에 부적합, SQLite in-memory가 실제 SQL 엔진으로 더 적합- SQLite는 마지막 커넥션이 닫히면 DB가 소멸되므로 커넥션 유지 필요,
IDbContextFactory<T>로 작업별 컨텍스트 생성해 ChangeTracker 오염 회피
VS 2026 Theme colors — Fluent 색상 토큰 커스터마이즈
- VS 2026 6월 업데이트에서 Fluent 색상 토큰을 IDE 내장 옵션 페이지로 직접 오버라이드 가능
- 테마별 커스터마이즈가 개별 보존되고 토큰 단위 reset 지원, Classic Blue 재현용 JSON 설정 예시 제공
MSIX 배포 — Add vs Stage+Register 차이
- Windows 패키지 설치는 staging(머신 단위, 디스크 배치)과 registration(사용자 단위, 프로파일 통합) 두 단계로 분리
Add Package는 두 작업을 한 번에 처리, 업데이트 사전 스테이징이나 원본 없이 재등록할 때 분리 호출 사용
