
TS 컴파일러 그래프 MCP 제작: Claude Code에서 토큰 사용량 10배 절감
요약
TypeScript 컴파일러의 인덱스를 활용한 MCP 도구인 @ttsc/graph를 소개합니다. 에이전트가 파일을 일일이 검색하는 대신 그래프 구조를 통해 코드베이스를 파악하게 함으로써, Claude Code 등에서 토큰 사용량을 약 10배 절감합니다.
핵심 포인트
- TypeScript 컴파일러 기반의 그래프 인덱스를 MCP로 제공
- 에이전트의 불필요한 grep 방식 탐색을 방지하여 토큰 비용 10배 절감
- 정확한 file:line 정보를 제공하여 답변의 신뢰도 유지
- 코드베이스의 구조적 질문에 대한 효율적인 대응 가능
요약 (TL;DR)
codegraph, codebase-memory-mcp, 그리고 serena는 모두 코딩 에이전트가 grep(텍스트 검색)을 멈추고 MCP를 통해 코드 지능을 전달받을 수 있도록 먼저 구현되었습니다. 하지만 저의 개방형 질문(open-ended questions)에서는 토큰 비용이 줄어들지 않았습니다. 에이전트가 계속해서 grep 방식으로 회귀하려 했고, 아무리 강한 프롬프팅(prompting)을 사용해도 이를 막을 수 없었습니다. 그래서 저는 @ttsc/graph를 직접 만들었습니다.
이 도구는 강제된 사고 사슬(chain-of-thought)을 가진 단일 도구를 통해, 소스 코드 본문이 아닌 TypeScript 컴파일러가 이미 해결한 인덱스를 에이전트에게 제공합니다. "이게 어떻게 작동하나요?"와 같은 질문에 대해 토큰 사용량을 대략 10배 정도 줄여주며, 답변의 질은 떨어지지 않습니다. 이 수치는 중앙값(median)이며, 매우 보수적으로 잡은 수치입니다.
- 저장소(Repository): https://github.com/samchon/ttsc
- 벤치마크(Benchmark): https://ttsc.dev/docs/benchmark/graph
1. 서문
1.1. @ttsc/graph란 무엇인가
왼쪽에서 에이전트는 수십 단계의 점선 화살표를 쫓으며 파일 미로 속에서 길을 잃고 있습니다. 오른쪽에서 에이전트는 노드(nodes)와 엣지(edges)로 구성된 컴파일러 빌트 그래프(compiler-built graph)를 읽고 있으며, 열어서 확인할 수 있는
file:line앵커(anchors)를 가지고 있습니다.
당신은 새로운 TypeScript 저장소(repo)에 들어왔고, 에이전트에게 가이드를 요청합니다. 공개 API부터 실제 작업을 수행하는 코드까지의 주요 런타임 흐름(runtime flow)은 무엇인지, 그리고 무엇을 가장 먼저 읽어야 하는지 묻습니다. 과정은 뻔합니다. 에이전트는 파일을 하나 열고, 다른 파일의 import를 따라가고, 또 다른 파일을 따라갑니다. 그렇게 수십 개의 파일을 거친 후에야 답변을 내놓습니다.
@ttsc/graph는 그러한 탐색 과정을 단축합니다. MCP (Model Context Protocol)를 통해, 이 도구는 컴파일러가 직접 그린 TypeScript 코드베이스의 그래프를 에이전트에게 전달합니다. 즉, 무엇이 무엇을 호출하는지, 무엇이 무엇에 의존하는지, 그리고 각 조각이 어디에 위치하는지를 알려줍니다. 에이전트는 파일을 일일이 뒤지는 대신 그래프에서 직접 구조적인 질문에 답변하며, 에이전트가 내놓는 모든 주장은 컴파일러가 해결한 정확한 파일:줄(file:line) 번호를 가리킵니다. 지어낸 것은 아무것도 없으며, 사용자가 직접 열어서 확인할 수 있는 위치 정보만 제공합니다.
모든 경우에 질문과 에이전트는 동일하지만, 오직 @ttsc/graph만이 저장소(repo)의 크기에 상관없이 일정한 성능을 유지합니다. 나머지 세 가지인 codegraph, codebase-memory, serena는 성능이 크게 요동치며, 일부는 기준점(baseline)보다 더 많은 비용을 소모하기도 합니다.
상세한 내용을 확인하고 싶다면, 모든 모델, 이 공유 프롬프트와 함께 사용된 저장소별 프롬프트, 그리고 전체 방법론이 대화형 벤치마크 페이지에 공개되어 있습니다.
1.2. 코드 그래프(Code Graph)란 무엇인가
도시 지도는 모든 거리와 건물을 표시합니다. 지하철 노선도는 그중 대부분을 버리고 당신에게 필요한 연결 정보만을 남깁니다.
그렇다면 "코드 그래프"란 무엇일까요? 한 번도 가본 적 없는 도시에 떨어졌을 때, 모든 거리 표지판을 순서대로 읽지는 않습니다. 대신 지하철 노선도를 훑어보죠. 노선도는 건물과 거리, 거리(distance) 정보는 버리고 당신에게 필요한 단 한 가지, 즉 무엇이 무엇과 연결되어 있는지를 남깁니다. 덕분에 5초 만에 전체를 파악할 수 있습니다.
코드 역시 동일한 형태를 가집니다. 노드(node)는 함수, 클래스, 파일이며, 엣지(edge)는 이들 사이의 호출(call), 임포트(import), 상속(inheritance)입니다. 이 모든 것을 그려내면 무엇이 무엇을 호출하는지에 대한 인덱스인 코드 그래프(code graph)가 완성됩니다. 에이전트(agent)는 모든 길을 직접 헤매는 대신, 이 인덱스에 단 한 번만 쿼리(query)하면 됩니다.
1.3. 소스 인라이닝(Source Inlining)이 아닌 인덱스(Index)
이것이 첫 번째 진정한 갈림길입니다. @ttsc/graph는 소스 본문(source bodies)을 전혀 반환하지 않습니다. 대신 이름(names), 엣지(edges), 시그니처(signatures), 그리고 스팬(spans)만을 반환하며, 그 이상은 제공하지 않습니다.
중요한 부분은 스팬(span)입니다. 인덱스가 인용하는 모든 범위는 컴파일러가 보증한 좌표이므로, 만약 답변이 의심스럽다면 정확히 그 지점을 열어서 확인할 수 있습니다. 저를 안심시키는 것은 이 도구가 파일을 읽지 않았다는 사실이 아니라, 항상 검증할 수 있는 위치가 함께 제공된다는 점입니다.
응답의 크기가 리포지토리(repo)의 크기에 의존하지 않기 때문에 토큰(token) 사용량은 일정하게 유지됩니다. 프로젝트가 10만 줄이든 1만 줄이든, 하나의 질문에 대해 유사한 크기의 인덱스 청크(chunk)가 반환됩니다. 왜 다른 도구들은 소스 코드를 쏟아내는지에 대한 사후 분석(autopsy)은 §2에서 다룹니다.
1.4. 작동 원리 요약
짧게 요약하자면: 이 도구는 TypeScript 컴파일러가 이미 해결(resolve)한 프로그램으로부터 인덱스를 읽어오며, 에이전트가 길을 잃지 않도록 단일 MCP 도구에 강제된 사고 사슬(chain-of-thought)을 제공합니다. 그게 전부입니다.
이 글의 나머지 부분은 이러한 주장들을 뒷받침합니다. §2는 기존 도구들이 왜 토큰 비용을 줄이지 못하는지에 대한 사후 분석을, §3은 이 도구가 어떻게 이를 수행하는지를, §4는 직접 실행하는 방법을 다룹니다. 먼저, 제가 왜 이것을 만들었는지부터 시작하겠습니다.
2. 제작 이유
2.1. 약속
솔직히 말해서, 이 모든 것은 제 아이디어가 아니었습니다. codegraph가 MCP를 통해 에이전트(agent)에게 코드 그래프(code graph)를 가장 먼저 제공했고, codebase-memory-mcp도 158개 언어에 걸쳐 거의 동일한 작업을 수행합니다. serena는 정적 그래프(static graph)를 구축하는 대신, 라이브 언어 서버(IDE에서 사용하는 것과 동일한 LSP 백엔드)를 시맨틱 툴킷(semantic toolkit)으로 래핑(wrapping)하여 다른 각도에서 접근합니다. 제가 이 접근 방식을 처음 보았을 때 진심으로 우아하다고 생각했고, 지금도 그렇게 생각합니다.
이 포스트의 벤치마크(benchmark)에서는 두 가지 프롬프트(prompt) 제품군, 즉 공통 온보딩 질문과 codegraph 자체의 리포지토리별 질문을 대상으로 세 가지 모두를 @ttsc/graph와 비교 실행합니다. (codebase-memory-mcp는 이식 가능한 재현 가능한 질문을 제공하지 않으며, serena는 재현 가능한 평가를 게시하지만 고정된 질문 세트가 아닌 사용자의 코드에서 직접 실행하는 방식이므로, 두 가지 모두 비교 가능한 세 번째 제품군을 제공하지는 못합니다.)
그리고 이들 모두의 핵심 주장은 타당합니다. 적은 바로 에이전트의 grep-찾기-읽기(grep-find-Read) 크롤링 루프(crawl loop)입니다.
GPT-5.5 상의 zod. 세 가지 도구(
codegraph,codebase-memory,serena) 모두 MCP가 전혀 없을 때보다 에이전트가 더 많은 비용을 쓰게 만들었습니다. +22%에서 +27% 사이입니다.@ttsc/graph는 기준점(baseline)의 6% 수준이었습니다. 이것은 제가 발견한 가장 극명한 리포지토리(repo)이지만, 이 패턴은 매트릭스 전체에서 동일하게 나타납니다.
- 토큰(tokens)이 실제로 줄어들지는 않았습니다. 도구 호출(tool-call) 횟수는 감소했지만, 실제로 비용을 지불하게 되는 요소인 토큰은 변하지 않았습니다. 일부 셀에서는 기준점보다 결과가 더 나빴습니다:
codegraph는 최대 47% 더 많이 사용했고,codebase-memory-mcp는 최대 66%,serena는 최대 93% 더 많이 사용했습니다. - Claude Code와 Codex는 더 정확하게 답변한 것이 아니라, 오히려 덜 정확하게 답변했습니다. 제가 실제로 요청한 내용을 계속 놓쳤습니다.
- 추가적인 MCP 호출이 스스로 실행되어 제가 원하는 작업의 완료를 지연시켰습니다.
- 단순히 자연어로 물어볼 수도 없었습니다. 모든 쿼리(query)를 수동으로 구성해야 했습니다.
codebase-memory-mcp의 가장 강력한 도구들은 Cypher 쿼리나 정확한qualified_name을 요구하며,codegraph는 흐름(flow) 내의 심볼(symbols) 이름을 지정하기를 원하고,serena는 프로젝트를 활성화한 다음 아직 가지고 있지 않은 정확한name_path를 전달하기를 요구합니다. 이러한 수동 구성(hand-shaping)에 드는 시간만으로도 도구가 돌려준 시간보다 더 많은 비용이 들었습니다.
따라서 제 종류의 질문에 대해서는, 세 가지 도구 모두 설치하기 전보다 상황을 더 악화시켰습니다. 두 가지 사실이 동시에 존재합니다: 이 도구들은 제가 문제를 인지하기 전에 이미 문제를 파악한 사람들이 만든, 해당 분야에서 가장 강력한 도구들이라는 점; 그리고 개방형 질문(open question)에 대해서는, 모든 도구가 아무것도 없을 때보다 에이전트가 더 많은 비용을 쓰게 만들었다는 점입니다. 바로 그때 저는 파헤치기 시작했습니다.
2.3. 본문(Bodies), 그리고 매몰된 그래프(Buried Graph)
첫 번째 원인은 각 도구가 이미 가지고 있는 것을 어떻게 처리하느냐에 있습니다.
codegraph는 전체 소스 바디(source bodies)를 반환합니다. 자체 설명에 따르면, 출력값은 "Read 도구가 반환하는 것과 바이트 단위로 동일(byte-for-byte identical)"하며, 에이전트에게 "각 블록을 이미 수행한 Read로 취급하라"고 지시합니다. 이는 편집 중일 때는 괜찮은, 당신을 대신해 수행된 Read입니다. 하지만 "이것이 어떻게 작동하는가?"와 같은 광범위한 질문에 대해서는, 이 바디(body)가 토큰 폭탄(token bomb)이 됩니다. 파일이 몇 개를 넘어서면 한계치에 도달하며, 초과분은 "추가적인 관련 파일(표시되지 않음)(additional relevant files (not shown))" 목록으로 붕괴됩니다. 이 목록은 당신에게 직접 Read 하지 말라고 알려주며, 결과적으로 당신은 codegraph_explore를 다시 호출하여 더 많은 바디를 받게 됩니다.
codebase-memory-mcp는 내부적으로는 올바른 아이디어를 가지고 있기 때문에 더 흥미로운 사례입니다. 이 도구는 제가 최종적으로 만든 것과 매우 유사하게, 사물들이 어디에 있는지뿐만 아니라 서로 어떻게 호출하고 의존하는지를 추적하는 실제 관계 그래프(relation graph)를 구축합니다. 문제는 그 앞의 인터페이스(surface)입니다. 그 기능은 14개의 MCP 도구에 분산되어 있으며, 실제로 관계 데이터에 도달하는 도구들은 Cypher 쿼리나 정확한 qualified_name과 같은 정밀한 입력을 요구합니다. (자연어 검색 기능도 있지만, 쿼리 도구들처럼 그래프를 건드리지는 않습니다.) 14개의 도구와 쿼리 언어에 직면한 에이전트는 관계 데이터에 거의 도달하지 못했습니다. 제가 측정한 실행 결과에서 에이전트는 MCP를 단 한 번도 호출하지 않았고, 매번 셸(shell)로 회귀했습니다. 에이전트는 포기하고 grep을 사용했습니다. 그래프는 바로 그곳에 있었지만, 인터페이스가 그것을 매몰시켰습니다.
serena는 이 두 가지를 동시에 해냅니다. 언어 서버(language server)를 기반으로 하기 때문에 심볼(symbols)이 적절히 해석되어 나오지만, 여전히 요청에 따라 소스 바디를 제공하며, 프로젝트를 활성화하고 언어 서버의 콜드 스타트(cold-start)를 기다린 후에야 에이전트가 도달할 수 있는 약 50개의 도구 뒤에 이를 배치합니다. 이 모든 상황을 고려할 때, serena 역시 셸로 회귀하기 전까지 MCP 호출 횟수의 중앙값이 0에서 1회에 불과할 정도로 grep을 사용했습니다.
어떤 것은 너무 많은 것을 돌려주고, 다른 하나는 에이전트가 찾을 수 없는 문 뒤에 올바른 것을 숨겨두며, 세 번째는 이 두 가지를 모두 저지릅니다. 그들 중 어느 것도 토큰 비용을 줄이지 못합니다.
2.4. 지침 (The Instructions)
두 번째 원인은 지침 (Instructions)이며, 여기서 세 가지 도구는 제각기 다른 방향으로 흩어집니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기


