TrendShift 딥다이브 · 2026-08-10 · Daily #22

code-graph-rag 딥다이브
— 모노레포를 지식 그래프로 통째로 그려, 자연어로 캐묻고 고치는 RAG

vitali87/code-graph-rag(CLI 이름 cgr)는 여러 언어가 섞인 큰 저장소를 Tree-sitter로 파싱해, "어떤 함수가 어떤 함수를 부르고, 어떤 클래스가 무엇을 상속하는가"라는 구조를 Memgraph 그래프 DB에 통째로 저장한다. 그 다음 사용자는 자연어로 "User 클래스를 상속하는 클래스 전부 찾아줘" 같은 질문을 던지고, AI 에이전트가 그걸 그래프 질의어(Cypher)로 번역해 정확히 답한다. 일반 RAG가 임베딩 유사도로 "비슷한 코드 조각"을 찾는다면, 이건 CALLS·INHERITS 같은 명시적 구조 엣지를 가진 영속 그래프라 "이걸 호출하는 곳 전부", "상속 사슬", "데드코드" 같은 다중 홉 질문을 정확히 답한다. 조회에 그치지 않고 AST 기반 외과적 편집(변경 전 diff 미리보기)까지 한다.
(저장소: vitali87/code-graph-rag · Python 3.12+ · MIT · 최신 v0.0.591 · Tree-sitter 13개 언어 · Memgraph 지식그래프 + Qdrant 벡터 · 기본 로컬(Ollama+UniXcoder) · MCP 서버 내장 · ⭐약 2.5k(계정 이슈로 배지 미표시) · 작성자 Vitali Avagyan · TrendShift Daily #22)
목차
  1. 프로젝트 한 줄 요약
  2. 왜 지금 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한 줄 요약

"코드베이스를 지식 그래프로 색인하고, 자연어로 질의·편집·최적화하는 모노레포용 RAG"

code-graph-rag는 두 개의 큰 부품으로 이뤄진다. 하나는 다국어 파서 — Tree-sitter로 소스코드를 훑어 함수·클래스·메서드·모듈과 그 사이의 관계를 뽑아 Memgraph 그래프에 적재한다. 다른 하나는 RAG 시스템 — 사용자의 자연어 질문을 받아 AI가 Cypher(그래프 질의어)로 번역하고, 그래프에서 정확한 답을 길어 올려 설명하거나, 코드를 직접 수정한다.

핵심은 "검색을 유사도가 아니라 구조로 한다"는 것이다. 여러 언어가 섞인 모노레포도 하나의 통합 스키마로 다루기 때문에, Python 서비스가 부르는 Go 핸들러, TypeScript 프런트가 호출하는 Rust 함수를 언어 경계를 넘어 이어서 질의할 수 있다.

한눈에 이해하는 비유

벡터 RAG가 "비슷한 책 페이지 찾기"라면, 이건 "도서관 전체의 인용 지도"다

보통의 코드 검색 AI는 질문과 의미가 비슷한 코드 조각을 임베딩으로 골라 온다. "로그인 관련 코드"를 물으면 로그인처럼 보이는 조각들을 준다. 하지만 "이 함수를 실제로 호출하는 곳이 몇 군데인가", "이 클래스의 상속 사슬 끝은 어디인가"는 유사도로는 못 푼다.

code-graph-rag는 코드를 노드(함수·클래스)와 화살표(호출·상속·정의)로 된 지도로 미리 그려 둔다. 그래서 "A를 호출하는 모든 것", "아무도 안 부르는 죽은 함수"처럼 관계를 여러 번 타고 가는 질문에 정확한 답을 준다. 유사도 검색(시맨틱)은 "의도"를 물을 때 보조로 함께 쓴다.

실제 한 번의 질의는 이렇게 흐른다. 사용자는 Cypher를 몰라도 되고, 오케스트레이터 에이전트가 자연어를 그대로 Cypher 전용 에이전트에 넘긴다.

질문 :  "User 클래스를 상속하는 클래스를 전부 보여줘"
   │   (ORCHESTRATOR 에이전트가 자연어 그대로 CYPHER 에이전트에 위임)
   ▼
Cypher: MATCH (c:Class)-[:INHERITS]->(p:Class)
        WHERE p.name ENDS WITH '.User'
        RETURN c.qualified_name, c.path
   │   (읽기전용 검증 통과 → Memgraph 실행)
   ▼
답변 :  AdminUser   (auth/models.py:14)
        GuestUser   (auth/models.py:41)
        ServiceUser (svc/accounts.py:88)

설계 목표는 "코드베이스를 환각 없이(grounded), 구조에 근거해 다루기"다. LLM이 코드 내용을 지어내지 않고, 실제 그래프에 있는 노드·엣지만 근거로 삼기 때문에 큰 저장소에서도 답이 사실에 붙어 있다.

2왜 지금 주목받는가

"지식 그래프 정확도 + 로컬 우선 프라이버시 + MCP로 Claude Code에 바로 물리기"

비슷한 "코드 챗봇"은 많지만, code-graph-rag는 네 가지가 겹쳐서 트렌딩에 올랐다. 정확도를 구조로 끌어올렸고, API 키 없이 완전 오프라인으로 돌릴 수 있으며, 편집까지 하고, MCP 서버로 다른 AI 도구에 그대로 꽂힌다.

① 벡터 RAG가 못 푸는 "구조 질문"을 정확히 답한다

순수 임베딩 RAG는 "비슷한 조각"만 찾아 큰 코드베이스에서 자주 헛다리를 짚는다. code-graph-rag는 CALLS·INHERITS·DEFINES 같은 명시적 엣지를 가진 영속 그래프라, "몇 개인가", "무엇이 이것에 의존하나", "여기서 도달 가능한가" 같은 다중 홉·집계 질문에 정확하다. 게다가 그래프 검색과 UniXcoder 시맨틱 검색을 함께 쓰는 하이브리드라 구조와 의도를 모두 잡는다.

② 기본값이 완전 로컬 — API 키 0개로 오프라인 구동

아무 설정도 하지 않으면 LLM은 로컬 Ollama(llama3.2), 임베딩은 로컬 UniXcoder, 그래프 DB는 로컬 Memgraph를 쓴다. 즉 코드를 외부로 한 바이트도 보내지 않고 통째로 오프라인에서 색인·질의할 수 있어, 사내 코드·규제 산업에서 그대로 쓸 수 있다(에어갭·온프레미스 상용 옵션도 존재). 원하면 OpenAI·Anthropic·Google·Azure로 스위치만 바꾸면 된다.

③ 읽기만 하는 게 아니라 "고친다"

단순 질의를 넘어 AST 기반 외과적 편집(변경 전 diff 미리보기), ast-grep 패턴 기반 구조적 검색·치환, 언어별 최적화(승인 워크플로), 진입점에서 도달 불가능한 데드코드 탐지까지 한다. "찾아줘"에서 "바꿔줘"로 넘어간 게 차별점이다.

④ MCP 서버 내장 — Claude Code·Cursor에 그대로 꽂힌다

cgr mcp-server 한 줄이면 Model Context Protocol 서버가 떠서, Claude Code·Cursor·Gemini CLI 같은 클라이언트가 이 지식 그래프를 도구로 직접 질의·편집한다. 다른 코딩 에이전트의 "장기 기억"이자 "코드 지도" 역할을 하도록 설계됐다.

도구검색 방식code-graph-rag와의 차이
순수 벡터 RAG임베딩 유사도(비슷한 조각)"몇 개·누가 호출·상속 사슬" 같은 구조 질문에 약함
Cursor / Copilot컨텍스트 윈도우 + 임베딩실시간 보조 중심. 모노레포 전체를 영속 그래프로 색인하지 않음
grep / IDE 검색텍스트·심볼 매칭언어 경계·의미(자연어 의도)를 넘지 못함
code-graph-rag지식 그래프(구조) + 시맨틱(의도)다중 홉 정확도 + 언어 통합 + AST 편집 + 로컬 구동

3기술 스택 전체 지도

"Tree-sitter로 파싱 · Memgraph에 저장 · Qdrant로 시맨틱 · pydantic-ai로 에이전트 · 기본은 전부 로컬"

Python 100%(requires-python >= 3.12) 프로젝트다. 스택은 "코드를 언어 무관하게 뜯는 파서 층", "구조를 담는 그래프/벡터 저장소 층", "질의·편집을 지휘하는 에이전트 층" 세 겹으로 나뉜다. 주목할 점은 기본 구성이 클라우드가 아니라 전부 로컬이라는 것 — Ollama·UniXcoder·Memgraph·Qdrant가 모두 사용자 머신에서 돈다.

코어 · 에이전트 층

패키지역할
pydantic-ai ≥2.0LLM 에이전트 프레임워크. ORCHESTRATOR·CYPHER 두 에이전트와 도구(tool) 정의의 뼈대.
pymgclient ≥1.5.1Memgraph 접속 드라이버(Bolt 프로토콜). 노드·엣지 적재와 Cypher 실행.
tree-sitter 0.25.2언어 무관 파서 런타임. 소스를 AST(구문 트리)로 만든다. 기본은 Python 문법만 포함.
tiktoken ≥0.12토큰 카운트. 질의 결과를 토큰 상한(16000)으로 잘라 컨텍스트 폭주를 막는다.
diff-match-patch코드 편집 시 diff 생성·패치 적용. 외과적 수정의 미리보기 근거.
watchdog ≥6.0파일 변경 실시간 감시. 저장하면 그래프를 증분 갱신(realtime_updater.py).
typer · rich · prompt-toolkitCLI 프레임워크 + 컬러 출력 + 대화형 입력. cgr 명령의 표면.
mcp ≥1.28Model Context Protocol 서버. Claude Code 등 외부 에이전트가 그래프를 도구로 쓰게 노출.
defusedxmlXML 폭탄 방어. 신뢰 못 할 입력을 안전하게 파싱.

LLM — "2-모델" 아키텍처가 핵심

이 프로젝트는 LLM을 역할별로 둘로 나눈다. 도구를 쥐고 대화를 지휘하는 ORCHESTRATOR와, 자연어를 Cypher로 번역만 하는 전용 CYPHER다. 번역은 값싼 빠른 모델에, 지휘는 강한 모델에 배정해 비용을 분리한다.

항목내용
지원 providerollama(기본) · anthropic · openai · google(AI Studio/Vertex) · azure · litellm_proxy · minimax
기본값(무설정)ORCHESTRATOR·CYPHER 모두 로컬 Ollama llama3.2 (API 키 불필요)
지정 방법환경변수 ORCHESTRATOR_PROVIDER/MODEL/API_KEY, CYPHER_PROVIDER/MODEL/API_KEY 또는 CLI 플래그
혼합 예시--orchestrator google:gemini-flash --cypher google:gemini-flash-lite

파싱 · 저장 · 검색 층

구성요소기술
파서Tree-sitter(13개 문법, extras treesitter-full). C++는 선택적 libclang, C#는 선택적 Roslyn 하이브리드로 정밀화. Ruby는 tree-sitter 대신 ast-grep 티어.
그래프 DBMemgraph(MAGE 그래프 알고리즘 포함 이미지). Bolt 7687, Lab UI 3000. 노드는 라벨별 배치 UNWIND + MERGE로 적재.
임베딩기본 UniXcoder(microsoft/unixcoder-base, 768차원, torch/transformers 로컬). 대안으로 OpenAI 호환 엔드포인트(그러면 torch 불필요).
벡터 스토어Qdrant(기본, 로컬 파일 모드 가능) 또는 Milvus Lite(CGR_VECTOR_STORE_BACKEND로 전환).
구조 검색·발견ast-grep로 AST 패턴 검색·치환 + Pattern/CodeSmell/SecurityIssue 발견 노드 생성.
설치 옵션(extras)이 말해 주는 것

기본 설치는 Python 파싱만 켜져 있어 가볍다. 필요에 따라 조립하는 구조다 — treesitter-full(13개 언어 문법), semantic(Qdrant+torch+transformers 시맨틱 검색), milvus(대안 벡터DB), ast-grep(구조 검색+Ruby 지원). 즉 "Python만 쓰는 소형"부터 "다국어 + 시맨틱 + 편집"까지 사용자가 무게를 고른다.

4아키텍처 심화 분석

"3-패스로 그래프를 짓고 → 2-에이전트로 질의하며 → 가드레일이 위험한 쿼리를 막는다"

동작은 크게 두 시기로 나뉜다. 색인 시기(--update-graph)엔 소스를 파싱해 그래프를 짓고, 질의 시기(대화형)엔 자연어를 Cypher로 번역해 답한다. 아래가 전체 데이터 흐름이다.

코드베이스 (여러 언어가 섞인 모노레포) | cgr start --update-graph | GraphUpdater.run() ── 3-패스 인제스션 (graph_updater.py) | | | PASS_1 STRUCTURE PASS_2 FILES PASS_3 CALLS Project/Folder/ Tree-sitter로 파일 간 호출 해소 File/Module 뼈대 함수·클래스 정의 (FunctionRegistryTrie) CONTAINS_* 엣지 DEFINES/IMPORTS CALLS/REFERENCES/INSTANTIATES | | | +-------+-------+--------+-------+ v v Memgraph 지식 그래프 UniXcoder 임베딩 (20종 노드·24종 관계) → Qdrant/Milvus 벡터 | ===============|=============== 질의 시기 (대화형) | 사용자 자연어 질문 → ORCHESTRATOR 에이전트 (도구 12종) | "자연어" 그대로 위임 (에이전트는 Cypher를 직접 안 씀) v CYPHER 에이전트 (자연어 → Cypher 번역 전용) | [가드레일] 읽기전용 검증 · 무한경로 차단 · 허용 프로시저만 CALL v Memgraph 실행 → 결과(행/토큰 상한) → 답변 · 또는 AST 편집(diff)

핵심 ① — 3-패스 인제스션 (graph_updater.py)

그래프는 한 번에 짓지 않고 세 번 훑어 짓는다. 왜 나눌까? 파일 간 호출을 풀려면 먼저 "어떤 함수가 어디 정의됐는지"가 다 있어야 하기 때문이다. 로그 마커도 PASS_1_STRUCTURE / PASS_2_FILES / PASS_3_CALLS로 남는다.

패스하는 일만드는 것
Pass 1 · 구조폴더·파일·모듈·패키지 뼈대 스캔Project/Folder/File/Module 노드 + CONTAINS_* 엣지
Pass 2 · 파일파일별 Tree-sitter 파싱, 정의·import 추출Function/Class/Method/Interface/Enum 노드 + DEFINES/IMPORTS
Pass 3 · 호출파일 경계를 넘는 호출·참조 해소CALLS/REFERENCES/INSTANTIATES 엣지

이후 오버라이드 처리 → 엔드포인트 방출(라우터 프리픽스 해소) → ast-grep 기반 패턴/스멜/보안 발견 → 고아 노드 프루닝 → 시맨틱 임베딩 생성이 이어진다. 두 번째 실행부터는 파일 해시 캐시로 변경분만 재파싱하고, 안 바뀐 파일의 정의는 그래프에서 되살린다(증분 갱신).

핵심 ② — 노드 적재는 파라미터화된 MERGE (cypher_queries.py)

수만 개 노드를 안전하게 넣기 위해, 문자열을 이어 붙이지 않고 파라미터 바인딩 + MERGE(있으면 갱신, 없으면 생성)로 적재한다. 라벨별 유니크 제약으로 중복을 막는다.

# cypher_queries.py — 라벨별 배치 노드 적재 쿼리 생성
def build_merge_node_query(label: str, id_key: str) -> str:
    return f"MERGE (n:{label} {{{id_key}: row.id}})\nSET n += row.props"

# 실제로는 UNWIND $rows AS row 로 감싸 수천 건을 한 번에 MERGE (배치 1000)

핵심 ③ — 2-에이전트 + 안전 가드레일 (services/, prompts.py)

사용자와 대화하는 오케스트레이터는 절대 Cypher를 직접 쓰지 않는다. 자연어 질문을 CypherGenerator(전용 에이전트)에 넘겨 번역만 시키고, 돌아온 쿼리는 실행 전에 세 겹으로 검사한다. 이 검증이 "AI가 실수로 DB를 지우거나 무한 경로로 메모리를 터뜨리는" 사고를 막는다.

async def generate(self, natural_language_query: str) -> str:
    result = await self.agent.run(natural_language_query)
    query  = _clean_cypher_response(result.output)
    _validate_cypher_read_only(query)   # DELETE/SET/CREATE 등 쓰기 키워드 차단
    _validate_no_unbounded_paths(query) # [:CALLS*] 같은 무한 가변경로 → OOM 방지
    _validate_call_procedures(query)    # 허용된 MAGE 프로시저만 CALL 허용
    return query

프롬프트(prompts.py)도 정교하다. Ollama 같은 로컬 모델에는 더 엄격한 규칙(UNION 금지 등)을 주고, 가변 길이 경로엔 반드시 상한을 붙이게([:CALLS*1..6]) 지시하며, 순환 그래프 분석엔 Memgraph의 MAGE 프로시저(pagerank.get, path.expand 등)를 쓰게 한다.

핵심 ④ — 그래프 스키마 (20종 노드 · 24종 관계)

모든 언어를 하나의 스키마로 담는 게 이 프로젝트의 정수다. 코드 노드는 qualified_name(예 Project.folder.ClassNamepath·start_line/end_line 등을 갖는다.

분류대표 요소
구조 노드Project, Package, Folder, File, Module, Class, Function, Method, Interface, Enum, Type
외부·발견 노드ExternalPackage, ExternalModule, Resource(파일/DB/네트워크 I/O), Pattern, CodeSmell, SecurityIssue
구조 관계CONTAINS_*, DEFINES, IMPORTS, EXPORTS, INHERITS, IMPLEMENTS, OVERRIDES
행위 관계CALLS, REFERENCES, INSTANTIATES, READS_FROM, WRITES_TO, FLOWS_TO(데이터흐름 taint), EXPOSES
왜 "무한 경로 차단"이 중요한가
[:CALLS*] 처럼 상한 없는 가변 길이 경로는 큰 그래프에서 메모리를 폭발시킨다

Cypher에서 -[:CALLS*]->는 "호출을 몇 번이든 타고 가라"는 뜻이라, 순환이 있는 코드 그래프에선 경로가 폭증한다. 그래서 code-graph-rag는 LLM이 만든 쿼리에 상한이 없으면 실행 전에 거부하고, 프롬프트에서도 항상 *1..6처럼 깊이를 못 박게 한다. 데드코드 탐지처럼 진짜 전방위 순회가 필요할 땐 Cypher 대신 클라이언트 쪽 BFS로 돌려 DB 타임아웃을 피한다.

5디렉토리 구조 해부

"codebase_rag/ 한 패키지 안에 파서·그래프·에이전트·MCP가 모듈로 갈려 있다"
code-graph-rag/ ├── main.py 진입점 → codebase_rag.cli:app (Typer) ├── realtime_updater.py watchdog 파일 감시 → 그래프 증분 갱신 ├── Dockerfile · docker-compose 스택(Memgraph+Qdrant) 정의 ├── server.json MCP 레지스트리 매니페스트 (uvx 배포) ├── pyproject.toml 의존성·extras·[project.scripts] cgr ├── docs/ (mkdocs) quickstart · installation · architecture · language-support └── codebase_rag/ ★ 본체 패키지 ★ ├── cli.py cgr 서브명령: start/daemon/export/optimize/dead-code/mcp-server/doctor… ├── graph_updater.py ★ GraphUpdater.run() — 3-패스 인제스션의 심장 ├── cypher_queries.py 노드/엣지 배치 MERGE 쿼리 생성 ├── function_registry.py FunctionRegistryTrie — 크로스파일 심볼 이름 해소 ├── embedder.py UniXcoder 시맨틱 임베딩 ├── dead_code.py 진입점 기반 도달 불가 함수 탐지 (클라이언트 BFS) ├── flow_verdict.py 데이터흐름(FLOWS_TO) 판정 ├── schemas.py / schema_builder.py 노드·관계 스키마 정의 ├── prompts.py CYPHER 규칙 · 오케스트레이터 시스템 프롬프트 ├── config.py provider 기본값(무설정=Ollama) · 환경변수 로딩 ├── parsers/ 언어별 Tree-sitter 로더 (+ libclang/Roslyn 하이브리드) ├── analyzers/ ast-grep 발견(Pattern/CodeSmell/SecurityIssue) ├── services/ MemgraphIngestor(배치 적재) · llm(2-에이전트) ├── tools/ 에이전트 도구 12종 (질의·검색·읽기·편집·shell…) ├── mcp/ MCP 서버 + 도구 16종 ├── providers/ LLM provider 어댑터 └── constants/ providers.py(enum) · mcp.py(도구명) 등

구조가 말해 주는 설계 의도는 분명하다. "그래프를 짓는 쪽"(graph_updater·parsers·services)과 "그래프에 묻는 쪽"(tools·prompts·mcp)이 깔끔히 갈려 있다. 새 언어를 추가할 땐 parsers/에 Tree-sitter 문법을 얹거나(cgr language add-grammar) ast-grep YAML 패턴 하나만 추가하면 되고, 새 도구를 붙일 땐 tools/에 함수를 하나 등록하면 오케스트레이터가 그걸 쓸 수 있게 된다. 확장점이 폴더 경계에 그대로 드러난다.

6학습 포인트

"이 저장소 하나로 배우는 것 — 코드 이해 AI의 밑바닥 전 계층"

code-graph-rag는 "요즘 AI 코딩 도구가 안에서 뭘 하는가"를 통째로 보여주는 교재다. 파싱부터 그래프, LLM 에이전트, 안전 검증까지 한 저장소에 다 들어 있다. 계층별로 배울 것을 정리하면 이렇다.

① Tree-sitter로 다국어를 하나의 AST로 파싱

13개 언어를 각각 다른 파서로 다루지 않고, Tree-sitter라는 공통 런타임 위에서 언어별 문법만 갈아 끼운다. "소스 텍스트 → 구문 트리(AST) → 노드 추출"이라는 컴파일러 프런트엔드의 첫 단계를 실물로 배운다. C++의 libclang, C#의 Roslyn 하이브리드를 보면 왜 순수 Tree-sitter만으론 부족한지(매크로·오버로드·partial class)도 알게 된다.

② 코드를 지식 그래프로 모델링하기

"무엇을 노드로, 무엇을 엣지로 둘 것인가"라는 스키마 설계가 이 프로젝트의 지적 핵심이다. 함수·클래스는 노드, 호출·상속·정의는 엣지 — 이 20종 노드/24종 관계 스키마를 뜯어 보면, 도메인을 그래프로 옮기는 감각을 익힌다. 이는 코드뿐 아니라 어떤 복잡한 도메인에도 쓰이는 기술이다.

③ Cypher — 그래프 질의어

SQL이 표(table)의 언어라면 Cypher는 그래프의 언어다. MATCH (a)-[:CALLS]->(b)처럼 "패턴을 그림으로 그려" 질의한다. 가변 길이 경로(*1..6), 집계, MAGE 그래프 알고리즘까지 — 이 저장소의 프롬프트에 담긴 Cypher 규칙만 읽어도 실전 패턴이 손에 잡힌다.

④ LLM 에이전트 오케스트레이션 (pydantic-ai)

"도구를 든 에이전트"가 어떻게 구성되는지 실전 규모로 볼 수 있다. 도구 정의, 재시도 정책, 출력 타입 제약, 그리고 역할을 나눈 2-에이전트(지휘용 강한 모델 + 번역용 값싼 모델) 설계는 비용·정확도를 함께 잡는 실용 패턴이다.

⑤ RAG 하이브리드 — 그래프 + 벡터를 함께

구조 질문은 그래프로, 의도 질문("인증 관련 코드")은 벡터 시맨틱으로 — 두 검색을 언제 어떻게 섞는지 오케스트레이터 프롬프트에 그대로 하드코딩돼 있다. "RAG = 벡터 검색"이라는 통념을 넘어서는 좋은 반례다.

⑥ AI 출력을 신뢰하지 않는 안전 설계

LLM이 만든 Cypher를 실행 전에 검증하고, shell 도구는 allowlist(ls,rg,cat,git,pytest…)로 제한하며, 위험 명령엔 확인을 받는다. "AI가 만든 걸 그대로 실행하지 않는다"는 감각 — 에이전트를 프로덕션에 쓸 때 반드시 필요한 방어를 정확히 짚는다.

7하드웨어 / 시스템 요구사항

"Python + Docker면 끝. GPU는 선택, 무거운 건 Memgraph/임베딩이 아니라 '설정'이다"

거창한 하드웨어는 필요 없다. 진짜 전제조건은 Docker(그래프·벡터 DB를 컨테이너로 띄우기)와 Python 3.12+다. GPU는 로컬 임베딩을 빠르게 하려면 좋지만 없어도 CPU로 돌고, 임베딩을 외부 API로 넘기면 아예 필요 없다.

항목요구 / 참고
Python3.12 이상 (3.12/3.13/3.14 분류자)
Docker & Compose필수. cgr daemon up이 Memgraph + Qdrant 스택을 띄운다(compose 파일 패키지 내장)
빌드 도구cmake(pymgclient 빌드), ripgrep(rg, shell 검색 도구). macOS brew install cmake ripgrep
패키지 매니저uv 권장 (또는 pipx/pip). uv tool install "code-graph-rag[treesitter-full,semantic]"
GPU선택. UniXcoder 임베딩을 CGR_EMBEDDING_DEVICE=cuda/mps/cpu로. 외부 임베딩 쓰면 torch 불필요
LLM완전 로컬이면 Ollama 설치(llama3.2). 클라우드면 해당 provider API 키
보안 기본값 (알아 두면 좋은 것)
스택 포트는 기본적으로 loopback(127.0.0.1)에만 바인딩된다
Memgraph·Qdrant는 기본 무인증이라, code-graph-rag는 이들을 내 컴퓨터에서만 접근되도록 묶어 둔다. 외부 노출이 필요하면 CGR_STACK_BIND_HOST=0.0.0.0을 명시해야 하고, MCP를 비-loopback으로 열면 MCP_HTTP_AUTH_TOKEN이 강제된다. "왜 다른 기기에서 접속이 안 되지?"의 답은 대개 이 기본값이다.

초기 셋업 절차 (요약)

uv tool install "code-graph-rag[treesitter-full,semantic]"  # 설치
cp .env.example .env          # 모델·DB 설정 (무설정이면 Ollama 로컬)
cgr daemon up                 # Memgraph + Qdrant 스택 기동 (Docker)
cgr doctor                    # 의존성·서비스 점검
cgr start --repo-path /my/repo --update-graph   # 그래프에 적재
cgr start --repo-path /my/repo                  # 대화형 질의 시작

여러 저장소를 같은 그래프에 적재하면(레포마다 --update-graph 반복) 그래프를 공유해 크로스 레포 질의가 된다. 프로젝트별 지시문은 .cgr.md, 무시 패턴은 .cgrignore(+ .gitignore 병합)로 준다.

8직접 해볼 수 있는 실습 과제

"cgr를 쓰는 것에서, 그래프 RAG의 원리를 손으로 재현하는 것까지 — 난이도별 5단계"
LEVEL 1 · 입문 내 프로젝트를 그래프로

작은 저장소를 색인하고 세 가지 질문 던지기

가진 파이썬 프로젝트 하나를 cgr start --repo-path . --update-graph로 적재한 뒤, "가장 많이 호출되는 함수", "이 클래스의 메서드 목록", "아무도 안 부르는 함수"를 자연어로 물어본다. Memgraph Lab(localhost:3000)에서 그래프를 눈으로도 본다. 목표: 구조 질의가 유사도 검색과 어떻게 다른지 체감.

LEVEL 2 · 초급 Cypher 직접 써 보기

Memgraph Lab에서 Cypher를 손으로 작성

AI를 거치지 않고 Lab 콘솔에서 직접 MATCH (c:Class)-[:INHERITS]->(p) RETURN c,p, MATCH (f:Function)<-[:CALLS]-(x) RETURN f.name, count(x) ORDER BY count(x) DESC를 실행해 본다. 배우는 것: 그래프 패턴 매칭·집계의 문법, LLM이 무엇으로 번역하는지의 실체.

LEVEL 3 · 중급 미니 파서 만들기

Tree-sitter로 함수 목록을 뽑아 노드로

tree-sitter-python으로 파일 하나를 파싱해 함수·클래스 정의를 찾아 출력하는 40줄 스크립트를 짠다. 여유가 되면 그 결과를 (:Function {name}) 노드로 Memgraph에 MERGE해 본다. 배우는 것: AST 순회 + "코드→노드" 변환의 최소 형태(= graph_updater의 축소판).

LEVEL 4 · 고급 2-에이전트 흉내

자연어 → Cypher 번역기 + 읽기전용 검증기

pydantic-ai(또는 임의 LLM SDK)로 "자연어를 받아 Cypher만 반환하는" 에이전트를 만들고, 반환된 쿼리에 DELETE/SET/CREATE가 있으면 거부하는 검증 함수를 붙인다. 무한 경로(* 상한 없음)도 막아 본다. 배우는 것: 역할 분리 에이전트 + AI 출력 가드레일.

LEVEL 5 · 도전 MCP로 Claude Code에 물리기

cgr를 MCP 서버로 띄워 다른 에이전트가 쓰게

claude mcp add --transport stdio code-graph-rag -- code-graph-rag mcp-server로 등록해, Claude Code가 내 코드 그래프를 도구로 질의·편집하게 만든다. 그 다음 index_repository·query_code_graph 같은 MCP 도구가 실제로 어떻게 호출되는지 로그로 관찰한다. 배우는 것: MCP로 도구를 외부 에이전트에 노출하는 실전 통합.

9관련 기술 심화 학습 로드맵

"code-graph-rag를 '읽고 확장하는 사람'이 되기 위한 6주 코스"
주차주제무엇을 · 왜
1주AST와 Tree-sitter구문 트리의 개념, tree-sitter-python으로 함수·클래스 추출. 파싱이 곧 그래프의 원료임을 이해.
2주그래프 데이터 모델링노드/엣지 스키마 설계, 속성 그래프 개념. "코드를 그래프로 옮기면 무엇이 쉬워지나"를 손으로.
3주Cypher · Memgraph패턴 매칭·집계·가변 경로·MAGE 알고리즘(pagerank/path.expand). Lab으로 시각화.
4주임베딩 · 벡터 검색UniXcoder 같은 코드 임베딩, Qdrant/Milvus 유사도 검색. 그래프와 벡터를 언제 섞나.
5주LLM 에이전트 (pydantic-ai)도구 정의·재시도·출력 타입, 역할 분리 다중 에이전트, 비용/정확도 트레이드오프.
6주MCP · AI 안전 설계MCP로 도구 노출, 생성 쿼리 검증·allowlist·확인 프롬프트. 에이전트를 안전하게 배포하는 법.
추천 학습 순서
"그래프를 짓는 법"을 먼저, "에이전트로 묻는 법"은 나중에

처음부터 LLM 에이전트·프롬프트를 파려 하면 정작 이 프로젝트의 토대(파싱→그래프)를 건너뛰게 된다. 1~3주에 "코드가 어떻게 노드·엣지가 되는가"를 손으로 재현하면(여기서 code-graph-rag의 절반이 이해된다), 4주에 시맨틱을 얹고, 5~6주에 에이전트·MCP·안전 검증으로 넘어가는 순서가 가장 단단하다. 그래프 없이는 RAG도 없다.

10핵심 키워드 사전

code-graph-rag 문서·코드에서 반복되는 용어들
용어
지식 그래프 (Knowledge Graph)
정보를 노드(개체)와 엣지(관계)로 표현한 그래프. 여기선 함수·클래스가 노드, 호출·상속이 엣지다. 유사도가 아니라 명시적 관계로 검색하므로 다중 홉·집계 질문에 강하다.
용어
Tree-sitter · AST
AST는 소스코드의 구문 구조를 나타낸 트리. Tree-sitter는 언어 무관 파서 런타임으로, 문법만 갈아 끼워 여러 언어를 같은 방식으로 AST로 만든다. code-graph-rag의 "코드→노드" 첫 단계.
용어
Cypher
그래프 DB의 질의 언어. MATCH (a)-[:CALLS]->(b)처럼 찾고 싶은 패턴을 그림으로 그려 질의한다. 이 프로젝트에선 사용자가 아니라 CYPHER 에이전트가 자연어를 번역해 만든다.
용어
Memgraph · MAGE
인메모리 그래프 DB(Neo4j 호환 Cypher, Bolt 프로토콜). MAGE는 Memgraph의 그래프 알고리즘 모음(pagerank·강한연결요소·path.expand 등)으로, 순환 그래프 분석에 쓰인다.
용어
RAG · 시맨틱 검색
RAG(검색 증강 생성)는 LLM에 답의 근거를 외부에서 검색해 붙여 주는 방식. 시맨틱 검색은 텍스트를 벡터로 바꿔 의미가 비슷한 것을 찾는다. code-graph-rag는 그래프(구조) + 시맨틱(의도)을 함께 쓰는 하이브리드.
용어
임베딩 · UniXcoder
임베딩은 코드/텍스트를 의미를 담은 숫자 벡터로 바꾼 것. UniXcoder(microsoft/unixcoder-base, 768차원)는 코드 특화 임베딩 모델로, 기본은 로컬에서 실행된다.
용어
ORCHESTRATOR · CYPHER (2-에이전트)
도구를 쥐고 대화를 지휘하는 오케스트레이터와, 자연어를 Cypher로 번역만 하는 전용 에이전트. 강한 모델과 값싼 모델로 역할·비용을 분리한 설계.
용어
pydantic-ai
Pydantic 팀의 LLM 에이전트 프레임워크. 타입 안전한 도구 정의·출력 검증·재시도를 제공한다. code-graph-rag의 두 에이전트가 이 위에서 돈다.
용어
MCP (Model Context Protocol)
AI 클라이언트(Claude Code·Cursor 등)가 외부 도구·데이터에 표준 방식으로 접근하게 하는 프로토콜. cgr mcp-server로 이 지식 그래프를 다른 에이전트의 도구로 노출한다.
용어
ast-grep
AST 패턴으로 코드를 구조적으로 검색·치환하는 도구. 텍스트 grep과 달리 "구문 모양"으로 매칭한다. code-graph-rag는 이걸로 패턴/스멜/보안 발견 노드를 만들고 Ruby도 지원한다.
용어
데드코드 · FLOWS_TO
데드코드는 진입점에서 도달 불가능해 실제로 안 쓰이는 코드. FLOWS_TO는 데이터가 흐르는 경로(taint) 엣지로, 값이 어디서 어디로 가는지 추적해 보안·영향도 분석에 쓴다.

11참고 링크

원본을 직접 확인하고 싶을 때