AI 코딩 컨텍스트를 95% 줄이는 방법
요약
AI 코딩 어시스턴트가 불필요한 파일 전체를 읽어 토큰을 낭비하는 문제를 해결하기 위해, 심볼 단위로 컨텍스트를 제공하는 MCP 서버 'SymbolPeek'을 소개합니다. 이를 통해 코드베이스의 필요한 부분만 정밀하게 추출하여 컨텍스트 크기를 95% 이상 절감할 수 있습니다.
핵심 포인트
- SymbolPeek은 MCP 서버를 통해 심볼 수준의 코드 접근 권한을 제공합니다.
- 파일 전체를 로드하는 대신 함수, 타입, 참조 등 필요한 정보만 선택적으로 전달합니다.
- 실제 개발 환경 테스트 결과, 소스 컨텍스트의 95% 이상을 절감하는 효과를 확인했습니다.
- 단순 텍스트 검색(grep)과 달리 TypeScript 컴파일러의 의미론적 지식을 활용합니다.
대규모 TypeScript 프로젝트에서 AI 코딩 어시스턴트가 작동하는 것을 볼 때마다, 저는 동일한 패턴을 발견했습니다.
어시스턴트는 다음과 같은 간단한 질문에 답하고 싶어 합니다:
- "이 훅(hook)은 어디에 정의되어 있나요?"
- "이 함수를 누가 호출하나요?"
- "이 값의 타입(type)은 무엇인가요?"
단 하나의 심볼(symbol)을 읽는 대신, 어시스턴트는 종종 파일 전체를 열어버립니다.
때로는 단 30줄짜리 함수를 추출하기 위해 50 KB... 때로는 100 KB를 로드하기도 합니다.
코딩 세션 동안 발생하는 수십 개의 요청에 이 수치를 곱하면, 모델이 실제로 필요하지 않은 코드에 수천 개의 토큰(token)을 빠르게 낭비하게 됩니다.
그래서 저는 SymbolPeek를 만들었습니다.
기능
SymbolPeek은 AI 코딩 에이전트에게 코드베이스에 대한 심볼 수준의 접근 권한을 제공하는 MCP 서버입니다.
에이전트는 파일 전체를 요청하는 대신, 정확히 필요한 것만을 요청할 수 있습니다:
- 단일 함수 읽기
- 모든 참조(references) 찾기
- 정의(definitions)로 이동
- 호출자(callers) 및 피호출자(callees) 조사
- 추론된 TypeScript 타입(types) 해결
- 호출 계층 구조(call hierarchies) 조사
- 심볼의 주변 컨텍스트(surrounding context)만 읽기
그 결과, 단순한 텍스트 검색보다 훨씬 더 풍부한 정보를 담으면서도 컨텍스트(context) 크기는 극적으로 줄어듭니다.
예시
거의 1,800줄에 달하는 파일이 있다고 가정해 봅시다.
다음과 같은 방식 대신:
파일 전체를 엽니다.
모델은 단순히 다음과 같이 요청할 수 있습니다:
read_symbol(
path: ".../worker.js",
symbol: "createProject.collectImports"
...
그리고 요청한 함수만을 전달받습니다.
프로젝트 자체의 실제 사례 중 하나를 보면, 65 KB의 소스 파일을 읽는 대신 약 2 KB의 응답을 받았습니다.
모델은 정확히 요청한 것만을 받으며, 그 외의 것은 받지 않습니다.
실제 사용 사례
저는 시맨틱 네비게이션(semantic navigation)이 실제로 LLM의 컨텍스트 소비를 줄이는지 알고 싶었습니다.
그래서 수명 통계(lifetime statistics) 기능을 추가했습니다.
일상적인 개발을 마친 후, 현재 수치는 다음과 같습니다:
Requests: 162
Files avoided: 163
Lines avoided: 352,910
...
이것은 인위적인 벤치마크가 아닙니다.
이 데이터들은 AI 코딩 에이전트(AI coding agents)와 함께 작업하는 실제 개발 과정 중에 수집되었습니다.
각 요청은 의미론적 응답(semantic response)을 관련된 전체 소스 파일을 읽었을 때의 반사실적 상황(counterfactual)과 비교합니다.
그 결과는 제 예상보다 훨씬 놀라웠습니다.
소스 컨텍스트의 95% 이상이 단순히 불필요했습니다.
왜 그냥 grep을 사용하지 않나요?
텍스트 검색은 환상적입니다.
저도 여전히 매일 grep을 사용합니다.
하지만 grep은 다음을 이해하지 못합니다:
- import 별칭 (import aliases)
- 배럴 수출 (barrel exports)
- 추론된 제네릭 타입 (inferred generic types)
- 호출 그래프 (call graphs)
- 정의 (definitions)
- 의미론적 참조 (semantic references)
TypeScript 컴파일러는 이미 이 모든 것을 알고 있습니다.
SymbolPeek은 텍스트를 다시 파싱하는 대신, MCP를 통해 컴파일러의 지식을 단순히 노출할 뿐입니다.
다국어 지원
이 프로젝트는 의미론적 탐색(semantic navigation)이 가장 큰 이점을 제공하는 TypeScript 도구로 시작되었습니다.
현재는 다음 언어들을 지원합니다:
- TypeScript
- JavaScript
- Rust
- Python
- Java
- Go
- JSON
- Markdown
TypeScript와 JavaScript는 의미론적 분석을 위해 공식 TypeScript Compiler API를 사용합니다.
Rust, Python, Java, Go, JSON 및 Markdown은 현재 빠른 구문 인식 탐색(syntax-aware navigation)을 위해 Tree-sitter를 사용합니다.
이는 동일한 MCP 서버가 TypeScript 프로젝트뿐만 아니라 여러 언어가 혼합된 리포지토리(repositories)에서도 유용하게 쓰일 수 있음을 의미합니다.
무엇이 다른가요?
제가 피하고 싶었던 것 중 하나는 "MCP 기반의 grep"을 만드는 것이었습니다.
만약 특정 언어에 이미 의미론적 질문에 답할 수 있는 프로덕션급 컴파일러가 있다면, 왜 그것을 무시하겠습니까?
TypeScript의 경우, SymbolPeek은 컴파일러 자체를 사용하여 다음을 제공합니다:
- 컴파일러가 해결한 참조 (compiler-resolved references)
- 모듈 해석 (module resolution)
- 경로 별칭 (path aliases)
- 배럴 재수출 (barrel re-exports)
- 추론된 제네릭 타입 (inferred generic types)
- 진단 (diagnostics)
- 호출 계층 구조 (call hierarchy)
정보는 이미 존재합니다.
MCP 서버는 단지 이를 AI 코딩 에이전트(AI coding agents)에게 노출할 뿐입니다.
현재 기능
TypeScript 및 JavaScript의 경우:
- 심볼 탐색 (symbol navigation)
- 참조 (references)
- 호출자 (callers)
- 피호출자 (callees)
- 정의 (definitions)
- 진단 (diagnostics)
- 호출 계층 구조 (call hierarchy)
- 타입 검사 (type inspection)
- 문서 개요 (document outline)
현재 지원되는 다른 언어들은 Tree-sitter를 통해 구문 인식 탐색 (syntax-aware navigation) 기능을 제공합니다.
목표
목표는 grep을 대체하는 것이 아닙니다.
소스 파일을 읽는 행위를 대체하는 것도 아닙니다.
이것의 목표는 AI 에이전트가 매일 수행하는 가장 비용이 많이 드는 워크플로 중 하나를 제거하는 것입니다:
단 하나의 선언 (declaration)을 확인하기 위해 거대한 파일을 여는 것.
더 적은 컨텍스트 (context).
더 적은 토큰 (tokens).
더 나은 신호 (signal).
피드백을 기다립니다
특히 다음과 같은 도구를 만들거나 관련 작업을 수행하는 분들의 의견을 듣고 싶습니다:
- Codex
- Claude Code
- Cursor
- Cline
- Roo Code
- Windsurf
- 기타 MCP 지원 에이전트 (MCP-enabled agents)
AI가 단순한 탐색 질문에 답하기 위해 파일을 읽느라 수천 개의 토큰을 소비하는 것을 본 적이 있나요?
현재 여러분은 이 문제를 어떻게 해결하고 있는지 듣고 싶습니다.
GitHub:
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기