주간 닷넷 - 주말 아침 #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 Likes

아이쿠 ㅜㅜ

1 Like

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

특히 반환보다 예외를 선호하는 것은 현 개발 트렌드에 맞지 않다고 보는 점이 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 Likes

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

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

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

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

반박시 내말 틀림ㅋ

3 Likes

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

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

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

2 Likes