
AI 에이전트가 계속 틀린 추측을 하길래, .NET 의존성 그래프를 위한 대화형 HTML 내보내기 기능을 만들었습니다
요약
AI 에이전트가 .NET 솔루션의 의존성을 정확히 파악하지 못하는 문제를 해결하기 위해 Slnmap을 개발했습니다. Roslyn을 사용하여 의미론적 그래프를 구축하고, 이를 MCP를 통해 에이전트에 제공하거나 대화형 HTML로 시각화할 수 있습니다.
핵심 포인트
- Roslyn 기반의 의미론적 그래프 구축으로 정확한 코드 분석 가능
- MCP를 통해 AI 에이전트가 직접 의존성 쿼리 수행 가능
- 전체 의존성 구조를 확인할 수 있는 대화형 HTML 내보내기 기능 제공
- grep 방식의 불완전한 검색을 넘어 인터페이스 호출 지점까지 추적
중규모 .NET 솔루션에서 Claude Code나 Copilot에게 "이 메서드 이름을 바꾸면 무엇이 깨지나요?" 같은 질문을 할 때마다, 이들은 파일들을 grep으로 검색하지만 인터페이스를 거쳐가는 호출 지점(call sites)을 놓치고, 불완전한 답변을 얻기 위해 수많은 토큰을 낭비하곤 했습니다. 수십 개의 프로젝트가 포함된 솔루션의 경우, 이는 느릴 뿐만 아니라 종종 틀린 답을 내놓습니다. 에이전트가 전체 그림을 보지 못하기 때문에 올바르게 추론할 수 없는 것입니다.
이것이 바로 Slnmap이 해결하고자 하는 문제입니다. Slnmap은 Roslyn(실제 C# 컴파일러)을 사용하여 솔루션의 의미론적 그래프(semantic graph)를 구축하고, 이를 SQLite에 로컬로 저장하며, MCP를 통해 노출합니다. 따라서 호환 가능한 어떤 에이전트라도 열려 있는 파일에 의존해 추측하는 대신 직접 쿼리할 수 있습니다.
제가 실제로 가장 많이 사용하는 부분: slnmap viz
도구 호출(Tool calls)은 에이전트에게는 훌륭합니다. 하지만 에이전트에게 코드 변경을 요청하기 전에 생소한 코드베이스가 실제로 어떻게 생겼는지 궁금해하며 앉아 있는 _저_에게는 그리 좋지 않습니다.
그래서 Slnmap은 전체 그래프를 하나의 독립적인 HTML 파일로 내보내는 viz 명령어도 함께 제공합니다. 서버도, 계정도, CDN 호출도 필요 없습니다. 브라우저에서 열고, 팬(pan) 및 줌(zoom)을 하며, 심볼을 클릭하면 그와 연결된 모든 것이 펼쳐지는 것을 볼 수 있습니다.
slnmap viz --project MyProject.csproj
이것이 생각보다 중요한 이유는 다음과 같습니다. 이 전체 워크플로우에서 에이전트만을 위한 것이 아닌 유일한 결과물이기 때문입니다. HTML 파일을 PR(Pull Request) 설명에 넣거나, 리포지토리를 체크아웃하지 않은 팀원에게 보낼 수 있으며, 그들도 당신과 동일한 대화형 뷰를 볼 수 있습니다. 제가 이것을 만드는 동안 살펴본 다른 모든 Roslyn 기반 MCP 서버들은 에이전트가 소비할 데이터를 출력할 뿐이었습니다. 그중 어떤 것도 사용자가 직접 볼 수 있는 무언가를 제공하지 않았습니다.

구체적인 예시
예를 들어, IBasketService를 수정하려 한다고 가정해 봅시다. 다섯 개의 파일을 일일이 grep(grep)으로 검색하며 모든 호출자를 찾기를 기도하는 대신, 에이전트에게 질문하거나 직접 쿼리를 실행할 수 있습니다.
"IBasketService를 변경하면 무엇이 깨지나요?"
Slnmap은 단 한 번의 쿼리로 솔루션 내의 모든 프로젝트에 걸쳐 인터페이스의 호출자(callers)와 구체적인 구현체(concrete implementations)를 모두 추적합니다. eShopOnWeb (10개 프로젝트)에서 18개의 의존성을 가진 인터페이스를 쿼리할 경우, MCP를 통한 엔드 투 엔드(end-to-end) 응답 시간은 약 270ms가 소요됩니다 (3회 실행의 중앙값 — 직접 설정을 확인하고 싶다면 전체 방법론은 BENCHMARKS.md에 있습니다).
도구의 범위를 의도적으로 좁게 유지한 이유
찾아보시면 Roslyn 기반의 다른 MCP 서버들이 몇 개 더 있으며, 일부는 Slnmap보다 훨씬 더 넓은 도구 범위를 가지고 있습니다. 저는 의도적으로 반대 방향을 선택했습니다. Slnmap이 제공하는 모든 도구는 읽기 전용(read-only)이며 범위가 좁습니다 — 심볼(symbol) 찾기, 호출자 추적, 영향도 확인, 구현체 목록 나열 — 이는 에이전트(또는 사람)가 모든 것을 하려는 방대한 API 범위보다, 특정 질문에 잘 답할 수 있는 작은 도구 세트에서 더 큰 가치를 얻을 것이라는 믿음 때문입니다.
솔직히 말씀드리면, 코드베이스와 사용 규모가 커짐에 따라 이 믿음이 유지될지는 아직 저도 모릅니다. 이는 마케팅 문구가 아니라 실제로 열려 있는 질문입니다.
하지 않는 것
Slnmap은 어디로도 데이터를 전송하지 않습니다. Slnmap은 Roslyn을 사용하여 소스 코드를 읽고 하나의 로컬 SQLite 파일을 작성할 뿐, 그 외에는 아무것도 하지 않습니다. 현재 오픈 소스이므로 이는 단순한 주장이 아닙니다. 코드를 직접 읽거나 프로세스를 지켜보며 데이터가 기기를 벗어나지 않음을 확인할 수 있습니다.
또한 추측하지 않습니다. 모든 답변은 소스 텍스트에 대한 문자열 매칭(string matching)이나 휴리스틱(heuristics)이 아니라, 컴파일러가 코드를 이해하는 방식 자체에서 나옵니다. 이것이 grep처럼 놓치는 것이 아니라 인터페이스를 통해 전달되는 호출 지점(call sites)을 잡아낼 수 있는 이유이기도 합니다.
사용해 보기
dotnet tool install --global Slnmap
slnmap analyze path/to/YourSolution.sln
그다음 MCP (Model Context Protocol) 호환 클라이언트(Claude Code, Cursor 등)를 해당 파일로 지정하기만 하면 됩니다. 설정 방법은 README에 안내되어 있습니다.
- Repo: https://github.com/EMahmoudNabil/slnmap
- NuGet: https://www.nuget.org/packages/Slnmap
- Site: https://slnmap.dev
이 프로젝트는 MIT 라이선스를 따릅니다. 만약 여러분도 "grep 대 의미론적 인덱스 (semantic index)" 사이의 트레이드오프 (tradeoff) 문제에 직면했거나, 다른 방향으로 "좁은 도구 대 많은 도구 (narrow-tools-vs-many-tools)" 설계를 시도해 본 적이 있다면, 여러분은 어떻게 접근했는지 진심으로 듣고 싶습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기