crg)는 Tree-sitter로 내 코드베이스를 통째로 파싱해, 함수·클래스·호출·상속 같은 관계를 SQLite 지식 그래프로 만든다. 그러면 AI 코딩 도구(Claude Code·Codex·Cursor 등)가 리뷰할 때 코드 전체를 다시 읽는 대신, "이 변경이 실제로 건드리는 파일만" 골라 받는다. 저자가 6개 실제 저장소에서 잰 결과 질문당 토큰이 중앙값 82배(최대 528배) 줄었다.
핵심은 blast radius(변경 파장 반경)다. 파일 하나를 고치면 그 파일을 호출·상속·테스트하는 노드들만 그래프에서 골라내, AI가 "정말 봐야 할 최소 집합"만 컨텍스트로 삼게 한다. 여기에 파일 감시·증분 재인덱싱, 30개 MCP 툴, 커뮤니티 검출·시각화까지 하나의 로컬 도구에 들어 있다.
tirth8205/code-review-graph · PyPI code-review-graph · v2.3.7 · Python 3.10+ · Tree-sitter + SQLite · 약 4.2만 줄·70여 모듈 · MCP 툴 30 + 프롬프트 5 · 로컬 전용·클라우드 불필요 · MIT · 클론 소스 직접 분석)
pip install code-review-graph → code-review-graph install(설치된 AI 코딩 툴 자동 감지·MCP 설정 주입) → code-review-graph build(코드베이스 파싱) 세 줄이면 끝이다. 이후 AI가 리뷰할 때, crg가 그래프에서 변경 파장 반경(blast radius)을 계산해 "이 diff가 영향 주는 함수·클래스·테스트"만 추려 넘긴다.
외부 DB도, 클라우드도, 임베딩 서버도 필요 없다. 모든 것이 .code-review-graph/ 폴더 안 SQLite 파일 하나에 들어간다. "코드는 내 컴퓨터를 떠나지 않는다(local-first)"는 게 이 도구의 큰 매력이다.
이 프로젝트가 푸는 문제는 요즘 누구나 겪는 것이다. Claude Code나 Codex 같은 AI 코딩 도구에게 "이 PR 리뷰해줘"라고 하면, 도구는 관련 파일을 반복해서 통째로 다시 읽는다. 큰 저장소일수록 매 질문마다 수십만 토큰이 날아가고, 비용도 시간도 늘어난다. crg의 발상은 "코드를 매번 다 읽지 말고, 한 번 구조를 지도로 만들어 두고, 필요한 조각만 꺼내 쓰자"는 것이다. README의 한 줄 정의를 그대로 옮기면 "MCP와 CLI를 통한 토큰 효율적 코드 리뷰를 위한 local-first 지식 그래프"다.
CALLS(호출)·IMPORTS_FROM(임포트)·INHERITS(상속)·TESTED_BY(테스트됨) 같은 관계다. 이렇게 만들어 두면 "이 함수를 호출하는 게 누구지?"를 파일 전체를 읽지 않고 그래프 질의 한 번으로 답할 수 있다 — 마치 위키백과의 하이퍼링크망처럼, 항목을 다 읽지 않아도 연결을 따라갈 수 있는 것이다.get_impact_radius_tool·query_graph_tool 같은 30개 도구를 AI에게 내민다. AI는 코드를 직접 뒤지는 대신 이 도구들을 호출해 "필요한 조각"만 받아온다. 즉 crg는 AI와 코드베이스 사이에 낀 똑똑한 중개인 역할을 한다.도구는 순수 Python 프로젝트로 약 4.2만 줄, 70여 개 모듈에 테스트 파일만 64개다. 핵심 엔진은 세 개다 — 코드를 파싱하는 parser.py(가장 큰 모듈), 그래프를 저장·질의하는 graph.py, AI에게 도구를 노출하는 MCP 서버 main.py. 여기에 별도의 VSCode 확장과 GitHub Action(PR에 자동 리뷰 코멘트)까지 딸려 있어, "CLI → 에디터 → CI"로 이어지는 삼면 제품이다.
AI에게 코드베이스를 이해시키는 방법은 이미 여럿 있다. ① 파일을 통째로 읽어 컨텍스트에 밀어넣기, ② grep·ripgrep으로 텍스트 검색, ③ 코드를 잘게 쪼개 벡터로 임베딩해 RAG(의미 검색). crg가 이 무리에서 눈에 띄는 지점은 "더 똑똑한 검색"이 아니라 "코드의 구조적 관계를 미리 그래프로 만들어, 변경의 파급 범위를 정확히 계산한다"는 접근이다.
| 축 | 전체읽기 / grep / RAG | code-review-graph |
|---|---|---|
| 코드 이해 단위 | 텍스트 줄·청크(의미 단위 아님) | 구조 단위(함수·클래스·호출·상속) — Tree-sitter AST 기반 |
| "이 변경의 영향" | 사람이 직접 grep 반복 / RAG는 유사 텍스트만 | blast radius로 호출·상속·테스트 관계를 따라 자동 전파 |
| 토큰 비용 | 매 질문마다 관련 파일 재적재(수십만 토큰) | 그래프 질의로 필요 조각만 — 중앙값 82배 절감 |
| 인프라 | RAG는 보통 벡터 DB·임베딩 서버 필요 | 로컬 SQLite 파일 하나, 클라우드 불필요(local-first) |
| 갱신 | 바뀌면 다시 인덱싱(느림) | SHA-256 해시로 바뀐 파일만 증분 재파싱(2,900파일 2초 이내) |
| AI 연동 | 도구마다 수동 설정 | install 한 번에 14종 AI 툴 자동 감지·MCP 주입 |
전체읽기/grep이 "책 전체를 매번 처음부터 훑어 답을 찾는 것"이라면, crg는 "먼저 색인 카드와 상호참조 지도를 만들어 둔 도서관 사서"다. 누가 "3층 A책이 바뀌면 영향받는 책이 뭐냐"고 물으면, 사서는 서가를 다시 안 뒤지고 카드 목록에서 상호참조를 따라 "이 책을 인용한 5권"을 즉시 짚어준다. crg의 blast radius가 정확히 그 상호참조 추적이다 — 코드에서 "이 함수를 고치면 무엇이 깨질 수 있나"를 그래프로 즉답한다.
README가 내세우는 헤드라인은 6개 실제 오픈소스 저장소에서 잰 질문당 토큰 절감 중앙값 ~82배다. 아래는 "코드베이스를 통째로(naive) 넣을 때" 대비 "그래프 질의로 필요한 만큼만" 쓸 때의 토큰 비교다.
| 저장소 | 통째로 넣기(토큰) | 그래프 질의(평균) | 절감 |
|---|---|---|---|
| fastapi | 951,071 | 2,169 | 528.4배 |
| code-review-graph(자기 자신) | 208,821 | 2,495 | 93.0배 |
| gin | 166,868 | 1,990 | 91.8배 |
| flask | 125,022 | 1,986 | 71.4배 |
| express | 135,955 | 3,465 | 40.6배 |
| httpx | 89,492 | 2,438 | 38.0배 |
많은 프로젝트가 최고 수치(fastapi 528배)를 헤드라인으로 뽑지만, crg의 README는 "528배는 단일 최선 사례이고 대표값이 아니다. 대표값은 중앙값 82배"라고 스스로 못박는다. 나아가 impact 정확도(F1 0.714)에 대해서도 "이건 그래프 유래 ground truth를 쓴 구조적 상한선이지 진짜 100% 리콜이 아니다"라고 한계를 자백한다. 이런 정직한 벤치마크 공개가 개발자 커뮤니티의 신뢰를 얻어 트렌딩에 올랐다.
① 구조를 이해한다(텍스트가 아니라). Tree-sitter로 언어별 AST를 뽑아 함수·클래스·호출 관계를 실제로 파악한다. Python·JS·Go·Java뿐 아니라 Laravel(Blade·Eloquent 관계)·Spring(엔드포인트·이벤트)·Vue/Svelte(SFC)·Jupyter 노트북·Terraform까지 프레임워크를 인지하는 파서를 갖췄다.
② blast radius가 핵심 무기. "변경 파일 → 영향받는 함수/클래스/테스트"를 가중 그래프 전파로 계산한다. 단순 "어디서 호출하나"를 넘어, 엣지 종류마다 가중치를 다르게 주고(CALLS 1.0, TESTED_BY 0.7…) 깊이가 멀어질수록 점수를 감쇠시켜 정말 중요한 영향만 추린다.
③ 토큰 절감을 "1급 시민"으로 다룬다. 응답마다 절감 토큰 추정치를 메타데이터로 자동 첨부하고(context_savings), 노출하는 MCP 툴 개수 자체도 필터링해(serve --tools) "툴 설명이 잡아먹는 토큰"까지 70~85% 줄인다. 절감이 부산물이 아니라 설계 목표다.
④ CLI + VSCode + GitHub Action + 에이전트 스킬. 터미널 도구 하나로 끝이 아니라, 별도 VSCode 확장(blast radius 시각화), PR에 스티키 리뷰 코멘트를 다는 GitHub Action(composite), 7종 에이전트 스킬까지 갖춘 완성형 생태계다. 5개월간 30개 릴리스로 개발 속도도 빠르다.
tree-sitter-language-pack으로 한 번에 여러 언어를 지원한다. 편집기(예: Neovim)의 문법 하이라이팅·코드 접기에도 널리 쓰이는, 요즘 코드 분석 도구의 사실상 표준 엔진이다.crg의 기술 선택은 "무거운 외부 인프라 없이, 로컬에서 완결되게"로 요약된다. 벡터 DB도, 클라우드도, 별도 서버도 필요 없고 — SQLite 파일 하나가 그래프이자 검색 인덱스다. 런타임 의존성도 소수만 엄격하게 골랐다.
| 레이어 | 선택 | 비고 |
|---|---|---|
| 언어/런타임 | Python 3.10+ (3.10~3.13) | 빌드 백엔드는 hatchling. 현재 버전 2.3.7(Beta) |
| 파싱 | tree-sitter >=0.23 + tree-sitter-language-pack | 다국어 문법을 번들로. 확장자→언어 매핑으로 디스패치 |
| 저장/검색 | 표준 라이브러리 SQLite + FTS5 | 그래프·전문검색(full-text)을 한 파일에. 외부 DB 없음 |
| MCP 서버 | mcp >=1.0 + fastmcp >=3.2.4 | AI에 도구 노출. 특정 CVE 픽스 버전 명시적으로 핀 고정 |
| 그래프 알고리즘 | networkx >=3.2 | 대체 BFS 엔진(CRG_BFS_ENGINE=networkx). 기본은 SQL 내 전파 |
| 파일 감시 | watchdog >=4.0 | watch/데몬 모드에서 변경 감지 → 증분 재인덱싱 |
| 설정 파싱 | pyyaml, (py<3.11엔) tomli | Ansible/설정 파일·languages.toml 로딩 |
nodes_fts라는 가상 테이블을 만들어 porter unicode61 토크나이저로 키워드 검색을 처리하고, 임베딩이 없을 때의 폴백 검색기로도 쓴다. "검색 인프라까지 SQLite 하나로 끝낸다"는 local-first 철학의 핵심 축이다.| 명령 | 실체 | 용도 |
|---|---|---|
code-review-graph | ...cli:main | 메인 CLI(30여 개 서브커맨드: build·query·install·serve…). 별칭 crg |
crg-daemon | ...daemon_cli:main | 여러 저장소를 동시에 감시하는 멀티레포 데몬 |
uvx code-review-graph serve | .mcp.json | AI 툴이 MCP 서버로 실행하는 진입점(stdio) |
코어는 가볍게 두고, 무거운 기능은 선택 의존성(optional extras)으로 분리했다. 필요 없으면 안 깔아도 되게 한 배려다.
embeddings — sentence-transformers+numpy로 시맨틱(의미) 검색. 없으면 FTS5 키워드 검색으로 폴백google-embeddings — Google 임베딩 제공자 연동communities — igraph로 Leiden 커뮤니티 검출(관련 코드 뭉치 자동 그룹화)enrichment — jedi로 Python 심볼 해석 정확도 향상 / wiki — ollama로 위키 생성| 구성요소 | 스택/형식 | 역할 |
|---|---|---|
code-review-graph-vscode | TypeScript(v0.2.2) | blast radius·트리뷰·D3 웹뷰 시각화 확장 |
action.yml | GitHub Action(composite) | PR에 스티키 리뷰 코멘트 자동 게시(자기 dogfooding) |
skills/ | 7종 에이전트 스킬 | build-graph·review-pr·debug-issue 등 워크플로 번들 |
| 시각화 | visualization.py → D3.js | force-directed 그래프를 단일 HTML로 내보내기 |
crg를 이해하는 핵심 파이프라인은 저장소 → Tree-sitter 파서 → SQLite 그래프 → blast radius → 최소 리뷰 집합이다. 각 단계가 무엇을 하고 어떤 실제 코드가 맡는지 뜯어보자.
CodeParser (parser.py)가장 큰 모듈(약 1.4만 줄)인 parser.py가 코드를 뜯는다. Tree-sitter로 AST를 만든 뒤, 두 종류의 데이터 구조로 낮춘다 — NodeInfo(파일·클래스·함수·타입·테스트)와 EdgeInfo(호출·임포트·상속·테스트 관계). 확장자로 언어를 판별하고, shebang(#!)으로도 감지한다.
단순 파싱을 넘어 프레임워크를 인지하는 게 특징이다. PHP/Laravel의 hasMany·belongsTo 같은 Eloquent 관계, Java/Spring의 REST 엔드포인트·스케줄러·이벤트, Vue/Svelte 단일 파일 컴포넌트(SFC), Jupyter 노트북, Terraform(HCL)까지 전용 파서가 있다. 파싱 후에는 별도 리졸버(spring_resolver·hcl_resolver 등)가 돌며 관계를 더 정확히 잇는다.
GraphStore → SQLitegraph.py의 GraphStore가 노드·엣지를 SQLite에 담는다. 스키마의 핵심은 nodes 테이블(정규화 이름이 UNIQUE, 파일 해시 포함)과 edges 테이블이다. 엣지에는 흥미로운 필드가 있다 — confidence_tier(신뢰도 3단계)다.
테이블은 nodes·edges 외에 metadata·communities·flows(실행 흐름)·community_summaries, 그리고 전문검색용 가상 테이블 nodes_fts가 있다. 스키마 버전은 migrations.py가 관리한다(v5에서 FTS5 추가, v6에서 요약 테이블 추가처럼 점진적 진화).
get_impact_radius_sql)crg의 심장이다. "변경 파일 → 영향받는 노드"를 계산하는데, 놀랍게도 그래프 전체를 Python 메모리에 올리지 않고 SQLite 안에서 전파를 돌린다(대규모 저장소에서 빠른 이유). 변경 파일을 씨앗(seed)으로 삼아, 임시 테이블로 프론티어(경계면)를 넓혀간다.
가중치가 핵심이다. 엣지 종류마다 영향력이 다르다고 보고 IMPACT_EDGE_WEIGHTS로 차등한다: CALLS 1.0(호출은 영향 큼) > INHERITS/OVERRIDES 0.9 > TESTED_BY 0.7 > REFERENCES/DEPENDS_ON 0.6 > IMPORTS_FROM 0.5 > CONTAINS 0.3. 여기에 깊이 감쇠 0.6(멀어질수록 점수↓), 점수 하한 0.05(너무 약하면 잘라냄), 기본 최대 깊이 2·최대 노드 500을 건다 — 전부 CRG_* 환경변수로 조정 가능하다.
blast radius는 "연못에 돌을 던졌을 때 퍼지는 물결"과 같다. 돌이 떨어진 자리(변경 파일)에서 물결이 사방으로 퍼지되, 멀어질수록 약해진다(깊이 감쇠). 그리고 물결이 잘 전달되는 방향(CALLS)과 덜 전달되는 방향(CONTAINS)이 다르다(엣지 가중치). 너무 약해진 물결은 무시한다(점수 하한). 이렇게 해서 "이 변경이 실제로 출렁이게 만드는 범위"만 남긴다 — 그게 AI에게 넘길 최소 리뷰 집합이다.
코드가 바뀔 때마다 전체를 다시 파싱하면 느리다. crg는 git diff --name-only로 변경 파일을 찾고(스테이지/언스테이지 모두, SVN도 지원), 각 파일의 SHA-256 해시를 저장된 값과 비교해 진짜 바뀐 파일만 재파싱한다. 그 파일에 의존하는 노드(dependents)도 엣지를 따라 함께 갱신한다. 파싱은 ProcessPoolExecutor로 병렬화하되, MCP(stdio) 환경에서는 파이프 핸들 상속 데드락을 피하려 스레드 방식으로 전환하는 세심함도 있다. README 주장으로는 2,900파일 프로젝트를 2초 이내 재인덱싱한다.
main.py가 FastMCP 서버로, 30개 @mcp.tool() + 5개 @mcp.prompt()를 등록한다. AI에게 가장 먼저 부르라고 안내하는 진입 도구가 get_minimal_context_tool이다 — 약 100토큰짜리 초압축 요약(그래프 통계·리스크 점수·다음에 부를 도구 추천)을 돌려준다.
주요 도구를 갈래로 보면: 컨텍스트(get_minimal_context·get_impact_radius·get_review_context), 질의(query_graph는 callers_of·tests_for·endpoints_for 등 15개 패턴), 검색(semantic_search_nodes — 임베딩 있으면 의미검색, 없으면 FTS5), 변경 분석(detect_changes), 구조 파악(get_architecture_overview·get_hub_nodes·커뮤니티/플로우 도구들)이다.
보통 "토큰 절감"은 데이터(코드 조각)만 줄인다. crg는 한 겹 더 간다. MCP 툴이 28개+면 그 설명 텍스트만으로도 AI 턴당 ~8k 토큰이 나간다. crg는 serve --tools ...나 CRG_TOOLS로 노출 툴을 5~10개로 줄여 이 설명 토큰을 70~85% 깎는다. 또 응답마다 context_savings 메타데이터로 "이번에 몇 토큰 아꼈는지"를 자동 첨부해, AI가 사람에게 절감량을 바로 보고할 수 있다. 절감이 곳곳에 배어 있다.
code_review_graph/ 패키지 어디부터 열까① pyproject.toml(의존성·진입점으로 전체 구조 파악) → ② parser.py의 NodeInfo/EdgeInfo(그래프의 원자 단위가 무엇인지) → ③ graph.py의 스키마 + get_impact_radius_sql(저장 방식과 핵심 알고리즘) → ④ main.py(어떤 MCP 도구를 AI에 노출하는지 = 이 프로젝트의 표면) → ⑤ incremental.py(어떻게 빠르게 갱신하는지) → ⑥ search.py(FTS5+벡터 하이브리드). 이 순서면 "코드가 그래프가 되어 AI에 전달되기까지"를 완주할 수 있다. docs/architecture.md와 docs/REPRODUCING.md는 저자가 직접 쓴 고신뢰 배경 자료다.
정규식·grep은 "함수 정의"와 "함수 이름이 든 주석"을 구분 못 한다. crg는 Tree-sitter AST로 구문 구조 자체를 다뤄, 노드(함수·클래스)와 엣지(호출·상속)를 정확히 추출한다. tree-sitter-language-pack 하나로 수십 언어를 커버하는 것도 핵심 교훈 — "코드를 분석하려면 먼저 파싱하라, 문자열로 때우지 말라". 린터·코드 검색·리팩터 도구 어디에나 옮겨 쓸 발상이다.
보통 그래프 알고리즘은 전체 그래프를 메모리에 로드한다. 큰 코드베이스에선 이게 부담이다. crg는 SQLite 임시 테이블로 프론티어를 넓히는 bounded relaxation으로 blast radius를 계산해, 그래프를 통째로 안 올리고도 빠르다. "엔드포인트당 최고 점수 1개만 유지"로 순환 그래프의 경로 폭발도 막는다. 재귀 CTE의 함정을 아는 실전 SQL 설계다.
"영향 분석"을 이진(있다/없다)이 아니라 연속 점수로 다룬 게 crg의 정교함이다. 엣지 종류별 가중치(CALLS 1.0…CONTAINS 0.3), 깊이 감쇠(0.6), 점수 하한(0.05), 게다가 엣지마다 confidence_tier로 신뢰도까지. "불확실성을 데이터에 명시하고, 중요도를 수치로 랭킹한다"는 접근은 추천·검색·리스크 스코어링 어디에나 통한다.
전체 재계산은 느리다. crg는 파일 해시를 저장해 두고 바뀐 파일만 재파싱하며, 그 의존자까지 엣지로 추적해 갱신한다. git diff로 변경 후보를 좁히고 ProcessPoolExecutor로 병렬화한다. "결과를 캐시하고 입력 변화만큼만 다시 계산한다"는 증분 계산(incremental computation)은 빌드 시스템·정적분석·재렌더링의 공통 원리다.
키워드 검색(FTS5)은 정확한 이름에 강하고, 벡터 검색(임베딩)은 의미에 강하다. crg는 둘을 RRF(Reciprocal Rank Fusion)로 병합해 각자의 약점을 메운다. 임베딩이 없으면 FTS5로 우아하게 폴백(graceful degradation)하는 것도 배울 점 — 무거운 의존성을 선택으로 두고, 없어도 동작하게 만드는 설계다.
crg는 "얼마나 아꼈나"를 추정해(context_savings.py, cl100k_base 근사) 응답 메타데이터로 자동 첨부하고, 툴 개수까지 필터링해 설명 토큰을 줄인다. LLM 시대엔 토큰이 곧 돈이자 지연시간이다. "핵심 자원(여기선 토큰)을 계측하고, 최적화를 눈에 보이게 만든다"는 태도는 어떤 비용 민감 시스템에서도 값진 습관이다.
crg는 요청을 받아 그래프를 만들고 질의하는 가벼운 로컬 도구다. 무거운 벡터 DB나 클라우드가 필요 없고, 평범한 개발용 노트북이면 충분하다. 유일하게 무거워질 수 있는 부분은 선택 기능인 임베딩(시맨틱 검색)인데, 그마저도 로컬 모델로 CPU에서 돌릴 수 있다.
| 항목 | 요구/권장 |
|---|---|
| Python | 3.10 이상(3.10~3.13). 그 외 런타임 불필요 |
| 설치 | pip install code-review-graph (또는 pipx/uvx) |
| 초기 설정 | code-review-graph install(AI 툴 자동 감지·MCP 주입) → build |
| 저장소(DB) | 프로젝트 안 .code-review-graph/ — SQLite 파일. 외부 DB 없음 |
| OS | 크로스플랫폼(Windows는 SelectorEventLoop 전환 등 전용 처리 있음) |
| GPU | 불필요. 임베딩도 CPU 결정론 모드로 동작(재현성 확보) |
| 선택 의존성 | 시맨틱 검색(embeddings)·커뮤니티(igraph)·위키(ollama)는 필요할 때만 |
| AI 툴 연동 | Claude Code·Codex·Cursor·Windsurf·Zed 등 14종 자동 지원 |
많은 코드 인텔리전스 도구가 코드를 클라우드로 보내 인덱싱한다. crg는 파싱·그래프·검색이 전부 로컬 SQLite에서 일어나 코드가 외부로 나가지 않는다(임베딩도 로컬 모델 선택 가능). 사내 코드·비공개 저장소를 다루는 팀에게 큰 장점이다. MIT 오픈소스라 무엇을 하는지 직접 감사할 수도 있다.
아무 프로젝트 폴더에서 pip install code-review-graph → code-review-graph build를 실행한다. 생성된 .code-review-graph/ 안의 SQLite 파일을 sqlite3로 열어 nodes·edges 테이블을 직접 들여다보라. "내 코드가 몇 개 노드와 엣지로 표현됐는지" 확인하는 것만으로 지식 그래프의 실체가 손에 잡힌다.
code-review-graph install로 Claude Code(또는 Cursor)에 MCP를 자동 주입한 뒤, 실제 변경을 만들고 AI에게 리뷰를 시켜본다. AI가 get_minimal_context → get_impact_radius → get_review_context 순으로 도구를 부르는지, 응답의 context_savings에 절감 토큰이 얼마로 찍히는지 관찰하라 — "필요한 것만 읽는" 흐름을 눈으로 확인하는 과제다.
CLI로 query_graph의 15개 패턴을 하나씩 시험한다: callers_of(누가 이 함수를 부르나)·tests_for(이 함수의 테스트는)·endpoints_for(관련 API 엔드포인트)·importers_of 등. 그리고 파일 하나를 골라 get_impact_radius로 blast radius를 뽑아, "왜 이 노드들이 걸렸는지"를 엣지 가중치와 대조해본다.
docs/REPRODUCING.md를 따라 fastapi·flask 같은 샘플 저장소에서 토큰 절감 벤치마크를 직접 돌려본다. 저자가 주장하는 "중앙값 82배"가 내 환경에서도 나오는지, config가 upstream SHA를 고정하고 Leiden seed를 박아 재현 가능하게 만든 장치들을 확인하라. 벤치마크를 의심하고 검증하는 습관을 기르는 과제다.
custom_languages.py와 languages.toml로 아직 없는 언어를 추가하거나, parser.py의 프레임워크 인지 로직(예: Spring 리졸버)을 참고해 새 프레임워크 관계 추출을 구현해본다. Tree-sitter 문법을 붙이고, 추출한 관계가 edges 테이블에 올바른 kind와 confidence_tier로 들어가는지 검증하라 — 파서 확장성을 몸으로 익히는 과제다.
Tree-sitter 공식 문서로 "쿼리(query)"와 "구문 트리"를 익히고, Python·JS 같은 언어 문법 하나를 붙여 직접 함수·클래스를 추출해본다. crg의 parser.py에서 NodeInfo/EdgeInfo가 만들어지는 지점과 대조하면, "소스 코드 → 구조 데이터" 변환의 실체가 보인다. 정규식으로 코드를 분석하려다 실패한 경험이 있다면 이 주차가 특히 값지다.
노드·엣지·인접 리스트·BFS/DFS·중심성(centrality) 같은 기본 그래프 개념을 정리하고, "그래프를 관계형 DB(SQLite)에 어떻게 저장·순회하는가"를 실습한다. crg의 graph.py 스키마와 get_impact_radius_sql를 교재 삼아, 재귀 CTE의 경로 폭발 문제와 crg가 그것을 "엔드포인트당 최고 점수 1개"로 푸는 방식을 따라가 본다.
FTS5 전문검색, 임베딩 기반 시맨틱 검색, 그리고 둘을 합치는 RRF(Reciprocal Rank Fusion)를 search.py로 익힌다. 이어 context_savings.py를 읽으며 "LLM 토큰을 어떻게 세고 절감을 추정하는가"(cl100k_base 근사)를 배운다. LLM 애플리케이션에서 비용·지연을 관리하는 실전 감각을 기르는 주차다.
main.py의 FastMCP 서버로 "AI에게 도구를 노출하는 법"을 익히고, Model Context Protocol 스펙과 대조한다. 특히 get_minimal_context를 "먼저 부를 진입점"으로 두는 설계, 툴 개수 필터링으로 설명 토큰을 줄이는 기법은 컨텍스트 엔지니어링(에이전트에게 무엇을, 얼마나 주는가)의 좋은 사례다. 직접 간단한 MCP 서버를 만들어 Claude Code에 붙여보며 마무리한다.
tirth8205/code-review-graph, PyPI 패키지명도 동일.get_impact_radius_sql)이 엣지 가중치×깊이 감쇠로 점수를 매겨 "정말 봐야 할 최소 집합"을 추린다.tree-sitter-language-pack으로 다국어를 지원.nodes_fts 가상 테이블로 키워드 검색을 처리하고, 임베딩이 없을 때의 폴백 검색기로 쓴다.git diff로 변경 후보를 좁히고 병렬 파싱. 2,900파일 2초 이내 재인덱싱.pip install code-review-graph)README.ko.md — 한국어 README(용어 대조용)