.NET 전용 Claude Code 환경을 구축하며 배운 점: 실제로 중요했던 두 가지 변화
요약
.NET 환경에서 Claude Code의 효율성을 극대화하기 위한 MCP 서버 구축 경험을 공유합니다. 텍스트 기반 검색 대신 Roslyn 컴파일러를 활용한 시맨틱 쿼리를 통해 토큰 소모를 60~80% 절감하고, 거대한 CLAUDE.md 대신 필요한 스킬을 분리하여 컨텍스트를 관리하는 전략을 제시합니다.
핵심 포인트
- 텍스트 검색(Grep) 대신 컴파일러(Roslyn) 기반 시맨틱 쿼리 활용
- 시맨틱 쿼리 도입으로 토큰 사용량 60~80% 절감
- 응답 범위 제한(Bounding)을 통한 컨텍스트 윈도우 폭주 방지
- 거대한 CLAUDE.md 대신 관련 시점에 로드되는 스킬(Skill) 방식 권장
저는 Claude Code가 .NET 작업을 더 잘 수행할 수 있도록 만드는 오픈 소스 키트를 구축해 왔습니다. 현재 47개의 스킬(skills), 10개의 서브에이전트(subagents), 16개의 슬래시 명령어(slash commands), 그리고 하나의 MCP 서버로 구성되어 있습니다. 그중 대부분은 헛수고였습니다. 두 가지가 거의 모든 작업을 수행했으며, 이 두 가지는 어떤 언어에도 적용 가능하기에 정리해 볼 가치가 있다고 판단했습니다.
Grep은 타입이 지정된 언어(typed language)에 적합하지 않은 도구입니다. 첫 번째 버전은 Claude가 기본적으로 수행하는 방식, 즉 코드베이스를 grep으로 검색하고 파일 전체를 읽는 방식에 의존했습니다. 대규모 C# 솔루션에서 이는 매우 가혹한 작업입니다. "이 메서드를 호출하는 곳이 어디인가요?"라고 물으면, 정의, 호출부, 해당 메서드를 언급하는 주석, 테스트 이름, 그리고 이름이 비슷한 관련 없는 세 가지 타입까지 포함된 텍스트 검색 결과가 나옵니다. 그런 다음 Claude는 모호함을 해소하기 위해 파일들을 엽니다. 파일 하나를 읽을 때마다 500에서 2,000개의 토큰이 소모되며, 그중 대부분은 무관한 내용입니다.
해결책은 텍스트를 검색하는 것을 멈추고 컴파일러에 쿼리(query)를 보내는 것이었습니다. C#에는 이미 솔루션의 전체 시맨틱 모델(semantic model)—모든 타입, 모든 참조, 모든 호출 체인이 이미 해결된 상태—을 보유하고 있는 Roslyn이 있습니다. 저는 이를 MCP 서버로 감싸서 Claude가 "이 심볼의 참조를 찾아줘"라고 요청하면 텍스트 매칭 대신 실제 답변을 얻을 수 있도록 했습니다. 이러한 시맨틱 쿼리(semantic query)는 파일을 읽을 때 소모되는 5002,000 토큰 대신 30150 토큰만 사용합니다. 제 측정 결과에 따르면, 코드베이스 탐색 세션 전체에서 토큰 사용량을 대략 60~80% 줄일 수 있었습니다.
단순히 영리한 수준을 넘어 실제로 사용 가능하게 만든 핵심은 모든 응답의 범위를 제한(bounding)한 것입니다. 결과 목록은 상한선(cap)을 두어 실제 총 개수를 보고하도록 했고, 소스 읽기는 문자 제한에서 잘라내도록(truncate) 했습니다. 이것이 없다면 컨텍스트 윈도우(context window)를 다 써버리는 폭주하는 호출이 발생하여 grep을 쓰는 것보다 상황이 더 나빠질 수 있습니다.
만약 실제 언어 서버(language server)나 컴파일러 API가 있는 언어로 작업한다면, 이것이 당신이 얻을 수 있는 가장 큰 승리입니다. TypeScript, Java, Go, Rust 모두 이에 상응하는 기능이 있습니다. 당신은 모델에게 텍스트에서 구조를 추론하도록 요청하는 대신, 해결된 사실(resolved facts)을 전달하는 것입니다. 거대한 CLAUDE.md 파일 하나를 만드는 것은 작은 CLAUDE.md 파일과 스킬(skills)을 조합하는 것보다 좋지 않습니다.
저는 모든 컨벤션(convention), 모든 규칙, 모든 패턴을 담은 하나의 거대한 CLAUDE.md로 시작했습니다. 약 한 시간 정도의 세션 동안은 작동했지만, 그 이후에는 조용히 작동을 멈췄습니다. 텍스트의 벽 속에 파묻힌 지침들은 컨텍스트(context) 내의 다른 모든 요소와 경쟁하게 되며, 세션이 채워질수록 그 경쟁에서 밀려납니다. 이를 분리함으로써 문제를 해결했습니다. CLAUDE.md에는 프로젝트의 구조와 몇 가지 핵심 규칙처럼 모든 프롬프트에 공통적으로 적용되는 사실만을 담았습니다. 그 외의 모든 것은 관련이 있을 때 로드되는 스킬(skill)이 되었습니다. EF Core 쿼리를 작성할 때 배포 컨벤션(deployment conventions)이 컨텍스트에 포함될 필요는 없습니다. Anthropic 또한 7월 말, Opus 5와 Fable 5를 위해 Claude Code 자체의 시스템 프롬프트(system prompt)를 80% 이상 줄였을 때 동일한 방향을 택했으며, 측정 가능한 평가(eval) 손실은 없었습니다. 그들의 설명은 이전 모델에 맞춰 미세 조정된 규칙들이 오버헤드(overhead)가 되었다는 것이었습니다. 이는 제가 훨씬 작은 규모에서 목격한 것과 일치했습니다. 저는 현재 모델이 겪지 않는 문제들에 대해 방어적인 지침을 작성하고 있었고, 매 프롬프트마다 그 비용을 지불하고 있었습니다. 이 실패에 대해 솔직하게 말할 가치가 있습니다. 제가 만든 47개의 스킬 중 대부분은 제 역할을 다하지 못하고 있습니다. 아마 12개 정도만이 정기적으로 사용될 것입니다. 나머지는 모델이 이미 할 줄 아는 내용을 인코딩한 것이었으며, 이는 정확히 Anthropic이 설명한 오버헤드였습니다. 만약 처음부터 다시 시작한다면, 5개만 작성하고 동일한 수정 사항이 두 번 발생할 때만 하나를 추가할 것입니다.
작동하지 않았던 것: 모든 것에 서브에이전트(Subagents) 사용하기. 대부분의 작업을 전문 에이전트(specialist agents)를 통해 라우팅(routing)하려고 시도했지만, 짧은 작업의 경우 설정 비용이 발생하고 메인 스레드(main thread)의 컨텍스트를 잃게 되어 더 느리고 결과도 좋지 않았습니다. 서브에이전트는 기본값이 아니라, diff에 대한 보안 검사와 같이 진정으로 병렬적이거나 진정으로 격리된 작업에서 그 가치를 발휘합니다.
도움이 될 수 있도록 리포지토리(repo)를 공유합니다: https://github.com/codewithmukesh/dotnet-claude-kit - MIT 라이선스이며, 가입이 필요 없고, Claude Code 플러그인으로 작동합니다.
요약(TL;DR): 타입 언어(typed language)의 경우, 컴파일러를 MCP 서버로 래핑(wrapping)하는 것이 grep을 사용하는 것보다 토큰(tokens) 측면에서 60~80% 더 효율적이었습니다. 비대한 CLAUDE.md를 온디맨드(on-demand) 스킬로 분리하는 것이 하나로 유지하는 것보다 나았습니다. 제가 구축한 나머지 대부분은 불필요한 것이었습니다.
다른 언어를 위해 이와 유사한 컴파일러-쿼리 레이어(compiler-query layer)를 구축해 본 분이 계신가요? Roslyn보다 의미론적 모델(semantic model)이 덜 완전한 환경에서도 토큰 절약 효과가 유지되는지 알고 싶습니다. /u/iammukeshm 제출 [link] [comments]
AI 자동 생성 콘텐츠
본 콘텐츠는 r/ClaudeAI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기