본문으로 건너뛰기

© 2026 Molayo

Qiita헤드라인2026. 05. 20. 00:28

LLVM(프로젝트 파일 크기 5.8GB)을 57초 만에 해체한다. C++20과 Tree-sitter로 직접 만든 초고속·저메모리 Local

요약

LLM의 컨텍스트 붕괴와 할루시네이션 문제를 해결하기 위해, 5.8GB 규모의 LLVM 프로젝트를 1분 미만의 시간과 1GB 미만의 메모리로 파싱하는 초고속 Local MCP 서버 'mcp-cst-core'를 소개합니다. C++20과 Tree-sitter를 사용하여 불필요한 추상화를 제거하고, 코드의 구조적 지도(CST)를 단계적으로 AI에게 제공함으로써 효율적인 코드 이해를 지원합니다.

핵심 포인트

  • 5.8GB 대규모 코드베이스를 57초 만에 파싱 및 인덱싱 완료
  • 피크 물리 메모리(RES) 사용량을 901MB로 최소화하여 저사양 환경 지원
  • Tree-sitter를 활용해 구문 분석 트리 대신 최소한의 물리 좌표와 원본 소스만 메모리에 유지
  • MCP(Model Context Protocol)를 통해 AI에게 코드의 전체 개요와 상세 슬라이스를 단계적으로 제공
  • C++20 기반의 고성능 멀티스레딩 및 추상화 오버헤드를 제거한 설계

2026년, AI 에이전트나 MCP(Model Context Protocol)의 보급으로 인해 LLM에게 코드베이스를 이해시키는 기회가 폭발적으로 증가하고 있습니다. 하지만 LLM은 통계 계산기이며, 수 기가바이트에 달하는 거대한 리포지토리의 텍스트를 그대로 삼키게 하면 컨텍스트는 순식간에 붕괴하고 할루시네이션(Hallucination, 환각)을 일으킵니다.

AI가 정말로 필요로 하는 것은 텍스트 스트림이 아니라, 코드의 **"올바른 기하학(구조)"**입니다.

그래서 LLVM급의 거대한 코드베이스를 **로컬에서 1분 미만·910MB 이하의 물리 메모리(RES)**로 완전히 파악하여, AI에게 "구조의 지도"를 제공하는 초근육질의 Local MCP 서버인 mcp-cst-core를 C++20과 Tree-sitter로 구축했습니다. SDK조차 사용하지 않는, 해커를 위한 스토익(Stoic)한 구현의 전모를 해설합니다.

거대한 오픈 소스 프로젝트인 llvm-project를 대상으로 일반적인 미니 PC 환경에서 벤치마크를 수행했습니다.

  • 대상 코드베이스 크기: 5.8 GB
  • 전체 파일 파싱(Parsing) & 인덱싱(Indexing) 속도: 57,444 ms (1분 미만!)
  • 피크 시 물리 메모리 사용량(RES): 901 MB

12GB 정도의 여유 메모리밖에 없는 개발 환경에서도 컨텍스트를 넘치게 하지 않고, 백그라운드에서 가상 메모리와 캐시를 오케스트레이션하며 고속으로 해체합니다.

본 시스템이 어떻게 표준 입력(STDIO)을 통해 AI와 대화하고, 멀티스레드(Multi-thread)로 고속 파싱을 수행하고 있는지에 대한 전체상입니다. (※ Qiita의 표준 기능으로 시퀀스 다이어그램으로 렌더링됩니다)

통신의 창구에 불과한 MCP 계층(STDIO / JSON-RPC)의 과도한 클래스 은닉이나 추상화를 철저히 거부했습니다. main()이 직접 표준 입력의 I/O 루프를 스트레이트로 잡음으로써, 불필요한 객체 생성이나 추상화 오버헤드를 제로(Zero)로 만들었습니다.

유일하게 나누는 개념적(Conceptual)인 경계는 통신의 통로(main)와 중후한 해석·메모리 관리를 담당하는 CSTAnalyzer 클래스뿐입니다. 이러한 뺄셈의 미학을 통해 주요 로직을 아름다운 싱글 소스(약 400행)로 구현했습니다.

AI에게 소스 코드를 통째로 삼키게 하는 것이 아니라, 로컬에서 구축한 지도를 단계적으로 AI의 두뇌에 전달하는 완벽한 역할 분담을 가진 인터페이스 설계를 채택하고 있습니다.

  • :CreateCST (메모리 전개와 해석)
    AI로부터 지시받은 프로젝트 경로를 기점으로 10개의 스레드를 폭주시켜 모든 파일을 파싱합니다. 무거운 구문 분석 트리(Syntax Tree)는 즉시 파기하고, 최소한의 물리 좌표(인덱스)와 원본 소스(Raw Source)만을 메모리에 전개·축적합니다.
  • :getProductSummary (전체 파악)
    해석을 통해 만들어진 지도에서 심볼 이름과 파일 이름, 행 수만 포함된 경량 목록을 AI에게 제공하여, 우선 전체의 기하학적 맵(개요)을 파악하게 함으로써 할루시네이션의 굴레에서 해방시킵니다.
  • :getMethodDetail (상세 슬라이스)
    개요를 본 AI가 "이 함수의 구현을 보고 싶어!"라고 지시하는 순간, 보유하고 있는 물리 좌표를 바탕으로 해당 코드의 "살코기(핵심 부분)"만을 밀리초 단위로 핀포인트 슬라이스하여 제공합니다.

코드의 전모는 GitHub 리포지토리에 공개되어 있으나, 5.8GB를 1GB 미만으로 굴복시키는 핵심 부분인 CSTAnalyzer의 병렬 워크 유닛(Parallel Work Unit) 로직과 main 함수의 통신 입구 부분을 발췌합니다.

// 【핵심】 군더더기를 깎아낸 인덱스 구조와 캐시
class CSTAnalyzer {
// 상세(살코기)를 요청받았을 때만, 여기서 코드를 잘라내기 위한 원본 소스 캐시
...

Tree-sitter로 평범하게 파싱하고 생성된 추상 구문 트리(TSTree)를 그대로 메모리에 계속 유지하면, LLVM급의 거대한 코드베이스에서는 순식간에 수십 기가바이트의 메모리를 소비하며 크래시(Crash)가 발생합니다.

본 구현에서는 위의 코드에 명시된 바와 같이, 최소한의 좌표 수치(NodeInfo)만을 추출한 후, 파일 하나마다 ts_tree_delete(lt)로 트리를 즉시 완전히 파기하고 있습니다.

이 철저한 "일회용" 방식과 복사를 발생시키지 않는 std::move를 통한 확장 메모리로의 소스 전송이야말로 압도적인 저메모리 성능을 뒷받침합니다.

이 개발 과정에서 가장 머리를 싸매고 처절하게 싸웠던 부분은 바로 **「물리 메모리(RES)의 철저한 억제」**였습니다.

솔직히 고백하자면, 개발 초기에는 「실행하자마자 OS(OOM Killer)에 의해 프로세스가 순식간에 KILL당하는 절망」을 말 그대로 셀 수 없이 반복했습니다.

Tree-sitter는 매우 빠르고 뛰어난 구문 분석기(Parser)이지만, 무식하게 모든 파일의 추상 구문 트리(TSTree)를 메모리에 계속 유지하려고 하면 LLVM급의 거대 리포지토리에서는 순식간에 수십 기가바이트의 메모리를 집어삼킵니다. 저의 개발 환경(사용 가능 메모리 약 12GB의 미니 PC)에서는 아무리 알고리즘을 고안해도 가차 없이 KILL당했고, 완전히 막다른 길에 다다른 것처럼 보였습니다.

"모든 파일의 구조를 유지해야 한다. 하지만 유지하면 KILL당한다."

이 모순을 굴복시키기 위해, **수십 번의 크래시 끝에 도달한 돌파구(Breakthrough)**가 바로 이번의 금욕적인 메모리 관리 아키텍처입니다.

OS에 의해 KILL당하지 않기 위한 최대의 해답은 이것이었습니다. 각 스레드(jthread)가 파일을 파싱하여 TSTree가 생성되는 순간, 거기서 S-식(S-expression) 쿼리 템플릿을 사용하여 「시작·종료 바이트·행 수」라는 단 몇 바이트의 수치(NodeInfo)만을 추출하고, 직후 몇 밀리초 이내에 ts_tree_delete(lt)로 트리를 흔적도 없이 완전히 파기합니다.

"중후한 트리 구조는 용무가 끝나면 1밀리초도 메모리에 머물게 하지 않는다"라는 설계로 전환함으로써, 마침내 KILL의 루프를 벗어나 물리 메모리를 901MB로 억제하는 데 성공했습니다.

10개의 스레드가 동시에 파싱한 로컬 지도를 전체의 거대한 지도(symbol_index)로 통합할 때, 일체의 문자열 복사(Deep Copy)를 발생시키지 않도록 철저하게 std::move를 통해 메모리의 소유권만을 고속 전송했습니다. 버퍼의 불필요한 중복을 단 1바이트도 허용하지 않는 설계입니다.

C++20의 std::counting_semaphore를 사용하여, 동시에 동작하는 병렬 워크 유닛(Parallel Work Unit)을 하드웨어의 스위트 스팟(Sweet Spot)인 「10」으로 엄격하게 제한했습니다. 이를 수행하지 않으면 스레드가 무한히 생성되어, 일시적인 메모리 전개(src)만으로도 물리 메모리의 한계를 넘어 다시 KILL당하기 때문에 엄격한 문지기로서 기능하게 했습니다.

기술적인 성취 이면에 있는, 이 「계속해서 KILL당했던 절망과 1바이트의 군더기도 허용하지 않는 집념」의 싸움이야말로 mcp-cst-core의 진정한 심장부입니다.

지금은 아직 이 초고속 로컬 인프라의 진정한 잠재력을 완전히 해방할 수 있는 AI 에이전트가 존재하지 않을지도 모릅니다. 하지만 이것은 명확하게 “차세대 AI 에이전트”를 위해 선제적으로 해킹한 구조적 기반입니다.

로컬 분석 우선, 그리고 프라이버시가 안전한 구조 분석이 앞으로의 표준이 될 미래를 향하여.

빌드 방법과 JSON-RPC를 통한 통신 테스트 시퀀스를 포함한 모든 소스 코드는 GitHub에 공개되어 있습니다. 괜찮으시다면 Star를 부탁드립니다!

AI 자동 생성 콘텐츠

본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
1

댓글

0