주간 닷넷 - 주말 아침 #21

월요일에 올리는 주말 아침 :joy:

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


:pushpin: C#으로 데이터베이스 엔진을 만드는 이유

  • 저자: Loic Baumann
  • 태그: csharp #database #performance

주요 내용

  • C#으로 1~2마이크로초 트랜잭션 커밋을 목표로 하는 임베디드 ACID DB 엔진 Typhon 개발
  • GC 비결정성, 메모리 레이아웃 제어 불가, JIT 워밍업 등 C#의 한계를 인정 후 unsafe, 고정 메모리, ref struct, 하드웨어 인트린식으로 극복
  • 128바이트 B+Tree 노드(캐시라인 2개)로 삽입 지연 53% 감소, SIMD MRU 캐시, 제로카피 읽기
  • BenchmarkDotNet 측정: CRUD MVCC 1.2μs, B+Tree lookup 267ns, 순차 스캔 2.1ns/key
  • 커스텀 Roslyn 분석기로 [NoCopy], 소유권 추적, Dispose 완전성 검증

:pushpin: C#에서 데이터 그리드를 위한 범용 쿼리 엔진 (파트 1~3)

https://medium.com/@nuthim/a-generic-query-engine-for-data-grids-in-c-1e49790b0773
https://medium.com/@nuthim/a-generic-query-engine-for-data-grids-in-c-part-2-50630721aa3c
https://medium.com/@nuthim/a-generic-query-engine-for-data-grids-in-c-part-3-68eb73a5ca54

  • 저자: Mithun Basak
  • 태그: csharp #efcore #expressiontree #architecture

주요 내용

  • 40개 이상 엔티티에서 엔티티별 필터/정렬 로직의 조합 폭발을 ~15개 파일의 제네릭 파이프라인으로 대체
  • 4단계 파이프라인: 입력 정규화 → DTO 기반 검증(보안 경계) → Expression Tree 합성 → 동적 정렬/페이징
  • 12개 연산자를 커스텀 어트리뷰트로 정의하고, 그리드 모델 DTO 대상 검증으로 미노출 속성 접근 차단
  • PredicateBuilder로 AND/OR 필터 트리 합성, ParameterUpdateVisitor로 파라미터 리바인딩, TypeDescriptor로 Nullable/enum/DateTime 타입 변환
  • 플랫 컬럼명을 깊은 네비게이션 속성 경로(2+ JOIN)로 매핑, EF Core가 SQL로 직접 번역

:pushpin: C# 팁: DateTime, DateTimeOffset, DateOnly, TimeOnly 값의 JSON 직렬화 및 역직렬화 방법

주요 내용

  • System.Text.Json 사용한 DateTime, DateTimeOffset, DateOnly, TimeOnly 기본 직렬화/역직렬화 동작
  • DateTime의 DateTimeKind(Unspecified, UTC, Local)에 따른 직렬화 결과 차이와 라운드트립 보존 여부
  • DateTimeOffset에서 DateTime으로 역직렬화 시 시간대 정보 손실과 커스텀 JsonConverter 해결
  • DateOnly/TimeOnly와 DateTime/DateTimeOffset 간 교차 변환 커스텀 컨버터 구현
  • 각 변환 시나리오별 테스트 코드와 예상 동작 실증 제시

:pushpin: MQTT, EMQX, .NET, Angular로 실시간 Pub/Sub 메시징 구축하기

https://mirzaleka.medium.com/build-real-time-pub-sub-messaging-with-mqtt-emqx-net-and-angular-6219bd1d9e2b

  • 저자: Mirza Leka
  • 태그: #mqtt dotnet #angular #pubsub #iot

주요 내용

  • EMQX 클라우드 브로커 설정(인증, 인가, TLS 인증서, 토픽 구성)부터 연결 테스트까지
  • ASP.NET Web API Publisher/Subscriber 구현(MQTTnet, BackgroundService, TLS 인증서 검증)
  • VB.NET WinForms 데스크톱 클라이언트의 MQTT 구독 구현
  • Angular에서 ngx-mqtt를 이용한 WebSocket 기반 Pub/Sub(포트 8084, wss)
  • QoS 레벨(0/1/2), Durable Subscriber(세션 유지), SubTopic 패턴, 재시도 메커니즘

:pushpin: 모던 C#에 맞지 않는 클린 코드 규칙들

https://medium.com/@wbayrakvlad/clean-code-rules-that-dont-fit-modern-c-c290644ddc61

  • 저자: Vlad Bayrak
  • 태그: csharp #cleancode #bestpractices

주요 내용

  • 2008년 Java 기반 Clean Code 규칙이 현대 C#에서 맞지 않는 6가지 사례 분석
  • XML 문서화는 IntelliSense/Swagger 생태계 메타데이터로서 선택이 아닌 필수
  • 함수를 과도하게 쪼개면 JIT 인라이닝, Span 최적화에서 성능 저하 발생 가능
  • out 파라미터(TryParse 패턴), named argument/record 등 C# 고유 패턴의 정당성
  • 예외 대신 Result 패턴이 예상 가능한 비즈니스 실패 처리에 더 적합한 이유

:pushpin: 데이터 접근 계층은 데이터베이스를 이해하지 못한다

  • 저자: Pengdows LLC
  • 태그: #database dotnet #entityframework #performance

주요 내용

  • EF Core, NHibernate, Dapper, ADO.NET이 DB별 연결 동작 차이를 모델링하지 못하는 문제 분석
  • SQLite/DuckDB 인메모리 모드의 연결당 별도 DB 생성, 파일 기반 DB의 단일 쓰기 제약, LocalDB 유휴 언로드 등 구체적 사례
  • Connection-per-command 패턴이 임베디드 DB에서 데이터 손실, 락 경합을 야기
  • Intent-Based Routing과 DbMode(Standard, KeepAlive, SingleWriter, SingleConnection, Best) 설정 대안
  • 읽기/쓰기를 구분하는 연결 정책으로 DB 유형별 동작 차이를 접근 계층이 흡수하는 구조

:pushpin: Trupe: Supervisor 구현하기

https://medium.com/@actor-swe/trupe-implementing-supervisor-97e834e32785

  • 저자: Rafael Andrade
  • 태그: #actormodel dotnet #faulttolerance #concurrency

주요 내용

  • Actor Model에서 Supervisor의 역할: 자식 액터 모니터링 및 장애 대응(OneForOne, AllForOne 전략)
  • RestartPolicy(Permanent, Transient, Temporary)와 FailureAction(Restart, Stop, Escalate, Resume) 설계
  • Supervisor, DynamicSupervisor, PartitionSupervisor 세 가지 유형 구현
  • Supervisor 재시작 시 자식 액터 전체 정리 및 IActorReference 무효화 메커니즘
  • PartitionSupervisor는 해시 기반 파티셔닝으로 고정 워커 풀 운영

:pushpin: 프로덕션에서 Supabase 속도 제한을 해결한 방법

  • 저자: Adrian Bailador
  • 태그: dotnet csharp #architecture #caching

주요 내용

  • 프론트엔드에서 Supabase 직접 호출 시 페이지 로드당 4회 요청으로 동시 25명 이상에서 429 에러
  • 쓰기 작업을 .NET 백엔드로 이전하여 서버-서버 단일 연결 전환
  • PostgreSQL RPC로 여러 읽기를 단일 HTTP 호출로 통합(get_user_dashboard 함수)
  • IMemoryCache 서버 측 캐싱 + localStorage TTL 기반 클라이언트 캐싱
  • 결과: Supabase 요청량 85% 감소, TTI 1400ms에서 310ms로 개선

:pushpin: .NET Core 개념 (IoT)

https://medium.com/@meriffa/net-core-concepts-iot-00701ad63d97

주요 내용

  • Raspberry Pi 5에 DietPi OS 설치, SSH 설정, SPI 인터페이스 활성화
  • .NET 10 런타임을 dotnet-install.sh로 ARM64 IoT 디바이스에 설치
  • VS Code 원격 디버깅 설정(vsdbg 배포, launch.json 구성)
  • WS2812B RGB LED Stick을 SPI로 .NET Iot.Device.Bindings 라이브러리로 제어
  • OS 설치부터 LED 제어까지 end-to-end 재현 가능한 단계별 가이드

:pushpin: OrionGuard: .NET 개발자들이 기다려온 Guard Clause 라이브러리

https://medium.com/@tunahan.ali.ozturk/orionguard-the-guard-clause-library-net-developers-have-been-waiting-for-0dd81e983d3a

  • 저자: Tunahan Ali Ozturk
  • 태그: dotnet #validation #library #opensource

주요 내용

  • Ensure.That() 플루언트 API로 null 체크, 범위 검증, 포맷 가드를 체이닝 방식으로 처리
  • GuardResult 패턴으로 여러 검증 에러를 수집 후 한번에 반환(API BadRequest 응답에 적합)
  • 비동기 검증(EnsureAsync), 조건부 검증(When/Unless), 객체 수준 검증(Validate.Object)
  • FastGuard로 핫패스에서 제로 할당/인라인 최적화, ReadOnlySpan 지원
  • 비즈니스 도메인 가드(금융, 이커머스), Luhn 알고리즘 신용카드 검증 등 내장

:bookmark_tabs: 가벼운 읽을거리

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


테스트가 전혀 없는 .NET 코드베이스를 물려받았다. 이제 어떻게?

  • Litmus CLI의 RiskScore = Churn x (1 - Coverage) x (1 + Complexity) 공식으로 테스트 우선순위 산정
  • Roslyn 기반 6가지 의존성 유형 감지로 테스트 용이성 평가

순수 C# BitTorrent/WebTorrent 클라이언트와 서버

  • SpawnDev.WebTorrent 1.0.0: 완전한 BitTorrent 와이어 프로토콜, SHA-1 검증, BEP 10 확장 지원
  • 브라우저(WebRTC)와 데스크톱(TCP) 모두 지원, HuggingFace 통합으로 ML 모델 캐싱

Visual Studio 단축키: 더 빠른 코딩을 위한 완벽 가이드

  • 네비게이션, 편집, 리팩터링, 디버깅 단축키를 15개 이상 섹션으로 체계적 정리
  • VS 2022 17.11+ Command Palette(Ctrl+Shift+P), 사용자 정의 단축키 설정

Windows 11 컴팩트 작업 표시줄 도입 예정

  • Windows 10 스타일의 전체 높이 축소 컴팩트 작업 표시줄 옵션 구현 검토
  • 작업 표시줄 위치 이동, 수동 크기 조절 기능 복원 예정

NtpTick 소개: .NET용 경량 NTP 클라이언트

  • inline arrays, Span, System.Buffers.Binary 등 최신 C# 저수준 기능 활용
  • 의존성 없는 경량 라이브러리로 NuGet v1.0 공개
6개의 좋아요

아이쿠 ㅜㅜ

1개의 좋아요

이 문서는 한번 정독해볼만 합니다. 실제로 저도 이렇게 생각했기 때문인데 역시 좋은건 취하고 방어적으로 볼 부분은 그렇게 보는게 맞다고 보여지네요.

특히 반환보다 예외를 선호하는 것은 현 개발 트렌드에 맞지 않다고 보는 점이 ErrorOr 같은 라이브러리 적용에 필수적인 개념이라고 생각합니다.

요즘 .NET 기술의 OpenSource 기본 기술 Stack으로

  • FluentValidation
  • MediatR
  • (xUnit || nUnit) + (Moq || NSubstitute) + Bogus
  • Newtonsoft.Json(Json.NET)
  • Polly
  • Serilog
  • Scalar
  • Refit
  • Dapper

등이 거의 필수적으로 사용되는 것 같고 분야에 따라서

  • CsvHelper
  • ClosedXml || MiniExcel
  • Hangfire || Quartz.NET
  • AutoMapper || Mapster

저처럼 WPF 개발씬에 계신분들은 추가적으로

  • Prism
  • FlaUI

정도는 사용되는 것 같습니다. 제가 들어보거나 사용한 것들만 나열해서 더 있을 겁니다.

(EF Core나 Generic Host 처럼 Microsoft 에서 개발한 것은 일부러 제외했습니다.)

Exception을 그대로 노출하면서 Message와 stacktrace를 MessageBox에 고대로 노출하는게 아니라 ErrorOr 같이 알아볼 수 있는 Message 를 표시해주는 게 좋을 것 같다는 점에서 되도록 포함되는 게 좋을 것 같다는 의견이라 공감하게 되었습니다.

아마 ErrorOr 같은 게 있는지 몰라서 많이들 그냥 만들어서 쓰실 거 같네요. 저도 있는지 모르고 만들어 썼었고, 지금 회사에서도 만들어 쓰고 있었지만 저의 제안으로 ErrorOr를 점진적으로 도입하기로 했습니다.

4개의 좋아요

Result 패턴은 논란이 많은 패턴임다.

갠적으루 Result 패턴은 필요한 상황에 맞게 쓰는 것을 추천합니다. 그런데 제가 만나는 보통의 상황에서 Result 패턴이 필요한 상황은 그렇게 많지 않은 거 같네요.

지극히 개인적인 생각인데 이것저것 정리하다가 내 생각이 맞나.. 싶어서 그냥 ai 와의 대화를 공유하는 게 더 나은 거 같아서 남겨봅니다.

https://claude.ai/share/194ec3b8-b99b-417d-95b3-1b9dfbf129df

반박시 내말 틀림ㅋ

3개의 좋아요

정독했습니다. 인사이트 감사드립니다.

저도 무차별하게 막 적용하지는 않고 상황에 맞게 적용을 하나…WPF 상황에서는 프로젝트 아키텍쳐를 웹 생태계처럼 복잡하게 구현하지 않기 때문일 수도 있는데 저는 꽤 많이 사용한 것 같습니다. 오히려 복잡해지면 역시 예외로 돌아가거나 다른 대안을 찾아야할 거 같습니다.

코드는 늘 변화하고 사람의 지식도 늘 변화하고 비즈니스도 변화하니까요 ㅎㅎ 이것이라고 딱 찝은 답은 아니었습니다. 하지만 제가봐도 그렇게 써놓은 것처럼 보이네요.

2개의 좋아요