이야기를 디버깅하는 개발자.

개발과 창작 사이에서, 사람들이 자기만의 이야기를 만들 수 있는 도구와 기록을 만듭니다.

roslyn.dev 자세히보기

개발 노트 84

OpenTelemetry가 기본으로 들어온 시대 — 1인 서비스의 관측 구성 최소안

느리다는 문의를 받고 로그를 열었는데 아무것도 못 찾은 적이 있습니다. 로그에는 요청이 들어왔다는 줄과 응답을 보냈다는 줄이 있었고, 그사이에 무슨 일이 있었는지는 비어 있었습니다. 데이터베이스가 느렸는지, 외부 API가 늦게 답했는지, 제 코드가 오래 걸렸는지 구분할 방법이 없었습니다.로그 도구를 바꾼다고 해결되는 문제가 아니었습니다. 필요한 것은 하나의 요청이 어디를 거쳐 얼마나 걸렸는지 이어 보는 방법이었고, 그게 분산 추적입니다. .NET 11에서는 ASP.NET Core가 OpenTelemetry 태그를 네이티브로 방출하는 방향으로 가고 있어서, 이 부분을 다시 정리해볼 만한 시점이 됐습니다. 아래 .NET 11 관련 내용은 현재 프리뷰 기준이며 GA까지 바뀔 수 있습니다.세 축은 각자 답하는 ..

Next.js Server Actions로 API 레이어 걷어내기 — 전환 기록과 한계

엔드포인트 목록을 열어놓고 하나씩 세어본 적이 있습니다. 화면 하나를 만들려고 라우트 파일을 만들고, 요청 타입을 정의하고, 클라이언트에서 부를 함수를 또 만들고, 응답 타입을 다시 선언하는 일이 반복되고 있었습니다. 실제 로직은 열 줄인데 그걸 감싸는 껍데기가 세 배쯤 됐습니다.Server Actions로 몇 개를 옮겨보기 시작한 건 그 목록을 본 다음이었습니다. 결론부터 말하면 절반쯤 옮겼고 나머지는 그대로 두었습니다. 이 글은 무엇을 옮겼고 무엇을 왜 남겼는지에 대한 기록입니다.옮기면서 실제로 줄어든 것가장 크게 체감한 것은 같은 타입을 두 번 쓰지 않아도 된다는 점이었습니다. 서버 함수를 직접 호출하는 형태가 되니 인자와 반환 타입이 그대로 이어집니다. 필드 이름을 바꿨을 때 컴파일 단계에서 잡히..

React Compiler 도입 후 useMemo·useCallback을 걷어내는 기준

프로젝트에서 useMemo와 useCallback이 몇 개나 쓰이고 있는지 세어본 적이 있습니다. 생각보다 많았고, 더 문제는 그중 상당수가 왜 붙였는지 기억나지 않는 것이었습니다. 언젠가 성능이 걱정돼서 붙였고, 그 뒤로 아무도 건드리지 않은 코드였습니다.React Compiler가 자리를 잡으면서 이 코드들을 어떻게 할지 결정해야 하는 시점이 왔습니다. 컴파일러가 알아서 메모이제이션을 해준다면 손으로 붙인 것들은 중복입니다. 다만 전부 지우면 되는 것도 아닙니다. 여전히 손으로 남겨야 하는 자리가 있고, 그 구분을 모르고 일괄 삭제하면 조용히 느려지거나 이상하게 동작합니다.컴파일러가 해주는 일과 해주지 않는 일React Compiler는 컴포넌트와 훅을 분석해서 렌더 사이에 재사용할 수 있는 값을 자..

Kestrel 개선과 Zstandard 압축 — 응답 크기와 CPU를 같이 줄이기

서버 지표를 보다가 이상한 장면을 만난 적이 있습니다. 트래픽은 그대로인데 CPU 사용률만 눈에 띄게 올라가 있었습니다. 원인을 좁혀보니 압축 설정을 바꾼 배포가 그 시점에 있었습니다. 응답 크기를 줄이려고 켠 옵션이 CPU를 대신 먹고 있었던 겁니다.응답 압축은 켜기만 하면 이득처럼 보이지만 실제로는 거래입니다. 네트워크로 나가는 바이트를 줄이는 대신 프로세서 시간을 씁니다. 이 거래가 이득인지 손해인지는 서비스마다, 심지어 엔드포인트마다 다릅니다..NET 11에서는 Zstandard 압축이 들어옵니다. Brotli에 준하는 압축률을 더 낮은 CPU 비용으로 얻는다는 성격의 알고리즘입니다. 이 글에서는 압축의 기본 거래 구조를 먼저 짚고, Zstandard가 1인 서비스에서 어떤 상황에 실익이 되는지,..

Minimal API 비동기 검증과 OpenAPI 3.2 — .NET 11에서 달라지는 것

"이 이메일은 이미 사용 중입니다." 회원가입 화면에서 이 문구 하나를 띄우려고 코드를 어디에 둘지 한참 고민했던 기억이 있습니다. 형식이 이메일인지 확인하는 건 어트리뷰트 한 줄이면 끝나는데, 이미 가입된 주소인지 확인하려면 데이터베이스를 봐야 합니다. 그리고 이 두 가지는 성격이 전혀 다릅니다.Minimal API를 쓰기 시작한 뒤로 이 구분이 더 선명해졌습니다. 형식 검증은 프레임워크가 알아서 해주는데, DB가 필요한 검증은 갈 곳이 애매해서 결국 핸들러 안으로 들어가곤 했습니다. .NET 11에서는 이 지점이 다뤄질 예정입니다. 다만 현재 프리뷰 기준이며 GA까지 바뀔 수 있습니다. 구체적인 메서드 이름이나 시그니처는 출시 시점의 공식 문서에서 확인하시는 편이 좋습니다.지금까지 검증 코드를 두던 ..

.NET 11 정식 출시 전 점검 — 실서비스 마이그레이션 체크리스트

달력을 보니 .NET 11 정식 출시까지 세 달 남짓 남았습니다. 예년대로라면 2026년 11월에 GA가 나올 예정이고, 지금은 프리뷰 단계입니다. 저는 이 시기가 되면 늘 같은 고민을 반복합니다. 나오자마자 올릴 것인가, 아니면 몇 달 지켜볼 것인가.회사에서라면 이 결정을 여럿이 나눠 지지만, 메리톡톡처럼 혼자 만들고 혼자 운영하는 서비스에서는 결정도 수습도 제 몫입니다. 그래서 저는 버전을 올리는 일 자체보다 올리기 전에 무엇을 확인해두었는가를 더 중요하게 봅니다. 확인 목록이 부실하면 올린 다음 날 새벽에 로그를 뒤지게 됩니다.이 글에서는 GA 전에 미리 해둘 수 있는 점검을 순서대로 적어보겠습니다. 아래 내용 중 프리뷰 기능에 대한 부분은 현재 프리뷰 기준이며 GA까지 바뀔 수 있습니다. 최종 확..

BFF 구조에서 리액트는 화면에 집중하고 인증은 서버가 맡는 방식

프론트엔드를 리액트로 만들다 보면 어느 순간 인증 처리를 어디까지 맡겨야 하는지 고민하게 됩니다. 화면을 그리는 일은 리액트가 잘합니다. 상태를 다루고, 컴포넌트를 나누고, 사용자와 빠르게 상호작용하는 것도 리액트의 장점입니다. 하지만 인증은 조금 다릅니다. 토큰을 어디에 저장할지, 쿠키는 어떻게 다룰지, API 호출 권한은 어디서 확인할지, 새로고침 후 세션은 어떻게 유지할지 같은 문제들이 따라옵니다. 처음에는 단순해 보이지만, 실제 서비스를 운영하려고 하면 생각보다 신경 쓸 부분이 많아집니다. 그래서 요즘 다시 관심을 두고 있는 구조가 BFF입니다. Backend for Frontend의 줄임말인데, 이름 그대로 프론트엔드를 위한 백엔드 계층을 하나 두는 방식입니다. 저는 이 구조를 “서버사이드가 프..

닷넷 11 프리뷰에서 지켜볼 만한 것들

이 글은 2026년 7월 7일 기준으로 정리한 기록입니다. .NET 11은 아직 프리뷰 단계에 있고, 현재 공개 자료 기준으로는 Preview 5까지 나와 있습니다. 정식 릴리스는 2026년 11월로 안내되어 있으니, 지금 보이는 기능들이 모두 그대로 고정된다고 보기는 어렵습니다. 그래도 프리뷰를 살펴보는 일은 의미가 있습니다. 당장 운영 중인 서비스를 옮기기 위해서라기보다, 앞으로 닷넷 생태계가 어떤 방향으로 움직이는지 미리 감을 잡을 수 있기 때문입니다. 저는 21년차 닷넷 개발자로 일하면서, 요즘은 웹소설 집필 보조 서비스 메리톡톡을 만들고 운영하는 흐름도 함께 고민하고 있습니다. 그래서 새 버전을 볼 때도 “멋진 기능이 나왔는가”보다 “혼자 오래 운영하는 서비스에 어떤 영향을 줄까”를 먼저 보게 ..

닷넷 프로젝트에서 Serilog를 자주 쓰는 이유

닷넷 프로젝트에서 Serilog를 자주 쓰는 이유 닷넷 프로젝트를 만들다 보면 로깅 도구를 고르는 순간이 자주 옵니다. 작은 기능을 만들 때는 Console.WriteLine만으로도 충분해 보이지만, 서비스가 실제로 운영되기 시작하면 이야기가 달라집니다. 문제가 생겼을 때 “어디에서”, “어떤 값으로”, “누가”, “얼마나 자주” 발생했는지 확인할 수 있어야 하기 때문입니다. 저는 닷넷으로 서비스를 만들고 운영하면서 Serilog를 자주 사용합니다. 대단히 특별한 이유라기보다, 혼자서도 상황을 추적하고 정리하기에 현실적인 도구라고 느껴왔기 때문입니다. 로그는 개발 중 확인용 메시지가 아니라, 운영 중인 서비스를 이해하기 위한 기록에 가깝습니다. 그런 관점에서 Serilog는 꽤 오랫동안 손에 익은 선택지..

OIDC와 OPA로 접근 제어를 분리해보는 닷넷 설계 기록

서비스를 만들다 보면 로그인보다 더 오래 고민하게 되는 부분이 있습니다. 바로 “이 사용자가 어디까지 할 수 있는가”를 판단하는 일입니다. 처음에는 닷넷 코드 안에 Admin, Manager, User 같은 역할을 기준으로 조건문을 넣으면 충분해 보입니다. 하지만 서비스가 조금씩 커지고, 조직이나 기능 단위의 규칙이 늘어나면 접근 제어는 금방 복잡해집니다. 저는 이 문제를 보면서 인증과 인가를 조금 더 분리해서 생각해보고 싶었습니다. 사용자가 누구인지 확인하는 일은 OIDC가 맡고, 그 사용자가 특정 자원에 접근할 수 있는지 판단하는 일은 OPA가 맡는 구조입니다. 닷넷 애플리케이션은 두 세계를 연결하는 얇은 통로가 됩니다. OIDC는 사용자가 누구인지 확인합니다 OIDC, 즉 OpenID Connect..

반응형