
AI 코드 리뷰는 PR 파일의 90%를 읽을 필요가 없다: KG로 범위 좁히기
요약
지식 그래프(KG)를 활용하여 AI 코드 리뷰 시 불필요한 컨텍스트를 제거하고 효율성을 극대화하는 방법을 다룹니다. KG를 통해 영향 범위를 계산함으로써 토큰 소비량을 7.8배 절감하면서도 버그 검출률을 유지할 수 있음을 실증합니다.
핵심 포인트
- KG 도입 시 투입 파일 중앙값 기준 90.4% 절감 가능
- 토큰 소비량 평균 7.8배 감소 및 리뷰 속도 개선
- Tree-sitter를 활용한 로컬 AST 기반 KG 구축 방법
- 정확도 향상이 아닌 컨텍스트 필터링 도구로서의 KG 활용
먼저 결론부터 말씀드리겠습니다. AI 코드 리뷰에 「변경 파일과 그 주변」을 전부 읽게 하는 것은 대개 과합니다. 제가 실제 PR 30개를 대상으로 테스트한 결과, 지식 그래프 (Knowledge Graph, KG)로 영향 범위를 계산한 뒤 읽게 하는 것만으로도 투입 파일의 중앙값 기준 90.4%를 절감했으며, 토큰 소비량은 평균 7.8배 가벼워졌습니다. 그러면서도 찾아내야 할 문제의 검출률은 떨어지지 않았습니다.
「AI 코드 리뷰가 느리다/비싸다」의 원인은 모델의 성능 문제가 아니라, 컨텍스트 (Context) 설계의 미흡함입니다. 변경 사항이 있는 auth.py 하나를 보기 위해, 만약을 대비해 주변 50개 파일을 전부 집어넣는 운용 방식이 여전히 많습니다. KG를 도입하면 이 「만약을 대비한 50개 파일」이 「정말로 영향을 받는 5~7개 파일」로 줄어듭니다. 이 기사는 그 절차와 실측 기록입니다.
과거에 발표된 유사한 기사들과의 차이점을 먼저 정리해 두겠습니다.
- 「코드베이스를 KG화했더니 AI 리뷰의 정확도가 변했다」: 정확도 개선이 주축
- 「AI 코드 리뷰의 병렬 처리 17종」: 병렬성과 역할 분담
- 본 기사: 읽는 파일의 범위를 좁히는 이야기 — 즉 속도와 비용이 주축
축이 다르기 때문에 KG를 사용하는 용도도 다릅니다. 본 기사에서는 KG를 「정확도를 높이는 장치」가 아니라 「불필요한 컨텍스트를 깎아내는 필터」로 다룹니다.
30개의 PR을 제가 평소 다루는 3개의 리포지토리 (Python x 2, TypeScript x 1)에서 선정했습니다. 선정 조건은 다음과 같습니다.
- 변경 행수 100~800행 사이의 중규모 PR
- 테스트 코드와 프로덕션 (Production) 코드가 혼재
- 1~4개 파일이 직접 변경된 것
비교한 것은 다음 두 가지 방식입니다.
- A. 기존 방식: 변경 파일 +
git blame과 grep으로 찾아낼 수 있는 「관련 있어 보이는」 파일 (경험칙상 최대 50개까지) - B. KG 방식: 변경 파일 + KG의 Blast Radius (폭발 반경)가 가리키는 Hop 0~2의 파일
투입 파일 수, 토큰 소비량, 리뷰 시간, 그리고 「사전에 심어둔 27건의 버그를 얼마나 찾아냈는가 (검출률)」라는 4가지 지표를 측정합니다.
먼저 KG를 만드는 방법을 확인해 두겠습니다. 수중에 있는 리포지토리를 통째로 그래프로 변환합니다. 노드 (Node)와 에지 (Edge)는 다음과 같이 구성했습니다.
- 노드:
File,Class,Function,Module - 에지:
CALLS(함수 호출),IMPORTS(import),INHERITS(상속),CONTAINS(소속),DEPENDS_ON(의존)
파싱 (Parsing)에는 Tree-sitter를 사용합니다. 19개 언어를 지원하며 LLM이 필요 없고, 로컬에서 몇 분에서 십수 분이면 완료됩니다. 제 환경 (13만 행, Python)에서는 약 7분이 걸렸습니다.
# 대략적인 이미지 (구현은 tree-sitter-python 직접 호출)
parser = get_parser("python")
tree = parser.parse(source.encode())
...
시맨틱 (Semantic)까지 파악하고 싶다면 두 번째 패스 (Pass)에서 LLM을 통과시키지만, Blast Radius 계산만 한다면 Pass 1 (AST)만으로도 충분합니다. 파일 내용을 외부에 보내지 않으므로, 기밀 리포지토리에서도 안심하고 돌릴 수 있습니다.
KG 위에서 변경 파일로부터의 홉 (Hop) 수를 계산합니다.
변경: auth.py:validate_token()
Hop 0 (변경 원본): auth.py
Hop 1 (직접 의존): middleware.py, api/login.py, api/register.py
...
저는 Hop 2까지를 「정말로 읽어야 할 범위」로 설정했습니다. Hop 3 이상은 코드의 의미론적 연결이 약해 AI의 판단 정확도에 기여하기 어렵기 때문입니다. 이 부분은 실제 데이터로 경계선을 정했습니다 (나중에 수치를 공개하겠습니다).
처음에는 「그래프가 있으니 Hop 4까지 읽게 하는 편이 안심되겠지」라며 욕심을 내어 돌렸다가, 토큰 사용량이 기존 방식보다 더 많아지는 어처구니없는 결과를 한 번 겪었습니다. KG는 「넓게 읽기 위한 장치」가 아니라 「좁게 다 읽어내기 위한 장치」라는 것을, 이 시점에서 비로소 뼈저리게 깨달았습니다.
Hop의 구분 방식은 언어와 리포지토리 (Repository) 구조에 따라 달라집니다. Python의 DI 컨테이너 (DI Container) 설계가 무겁다면 Hop 1이 넓게 퍼지기 쉬우므로 Hop 1까지, REST API 핸들러가 얇은 Go 설계라면 Hop 2까지와 같이 조정이 필요합니다. 저는 처음 3개의 PR (Pull Request)에서 경계를 결정한 뒤 나머지를 진행했습니다.
먼저 투입 파일 수의 대비입니다.
| 지표 | 기존 방식 (A) | KG 방식 (B) | 절감률 |
|---|---|---|---|
| 투입 파일 수 중앙값 | 47 | 6 | -87.2% |
| ... |
30개의 PR 중 28개에서 KG 방식이 더 낮았습니다. KG 방식이 더 높았던 2개는 리팩터링 (Refactoring) PR에서 import 교체가 광범위하게 일어난 케이스입니다. 이는 KG가 올바르게 "정말로 영향을 받는" 부분이라고 판정했기 때문이므로, 절감되지 않는 것은 사양대로의 결과입니다.
이어서 토큰 (Token)과 리뷰 시간입니다. 사용 모델은 Claude Sonnet 4.6 상당이며, 리뷰 프롬프트 (Prompt)는 고정했습니다.
| 지표 | 기존 방식 (A) | KG 방식 (B) | 절감률 |
|---|---|---|---|
| 프롬프트 토큰 중앙값 | 132,400 | 17,900 | -86.5% |
| ... |
비용 측면에서 7배 가벼워졌습니다. 한 단계 더 중요한 것은 시간의 단축 정도입니다. 74초 → 16초는 개발자의 대기 방식이 바뀌는 차이입니다.
가장 궁금한 질문은 이것입니다. 읽히는 파일을 9할 줄였는데, 리뷰가 느슨해지지는 않을까?
제가 사전에 PR 내에 심어둔 버그는 27건입니다. 내역은 다음과 같습니다.
- N+1 쿼리 (Query): 6건
- 인가 (Auth) 누락: 5건
- 레이스 컨디션 (Race Condition): 4건
- 예외 (Exception) 무시: 5건
- 테스트가 기대와 다른 사양을 작성함: 4건
- 타입 (Type)과 구현의 불일치: 3건
| 지표 | 기존 방식 (A) | KG 방식 (B) |
|---|---|---|
| 검출 버그 수 | 21 / 27 (77.8%) | 22 / 27 (81.5%) |
| 오검출 (False Positive) | 14건 | 6건 |
검출률은 KG 방식이 미세하게 높았습니다. 오검출은 절반 이하로 줄었습니다. 요인은 명확합니다. 무관한 파일이 섞이면 모델의 주의력이 그쪽으로 분산되어 "실제로는 관계없는 서식 스타일"을 지적하게 됩니다. KG로 범위를 좁히면 주의력이 집중되어 지적의 정밀도가 높아지는 방향으로 작용했습니다.
이것은 "30개의 PR 결과"일 뿐, 범용적인 보증은 아닙니다. CI/CD 전체를 교체하는 아키텍처 (Architecture)적인 PR은 폭발 반경 (Blast Radius)이 넓어지기 쉬워 KG를 통한 절감 효과가 작아집니다. "소~중규모의 기능 추가 및 버그 수정 PR"에서 최대의 효과가 나타난다는 것이 저의 해석입니다.
Blast Radius는 MCP 서버로서 공개할 수 있습니다. 절차는 3줄입니다.
pip install code-review-graph
code-review-graph build .
code-review-graph install # Claude Code / Cursor / Windsurf 를 자동 검출
에디터에서 자연어로 "auth.py의 변경 영향 범위를 알려줘"라고 묻기만 하면, KG가 읽히고 Hop 0~2의 파일 리스트와 리스크 스코어 (Risk Score)가 반환됩니다.
사용자: auth.py의 변경이 파급되는 범위를 알려줘
AI (MCP 도구 호출):
→ blast_radius("auth.py", max_hop=2)
...
제가 처음 MCP로 KG를 연결했을 때, auth.py의 영향 범위가 2초 만에 6개 파일로 정리되어 돌아왔습니다. 이전에는 grep과 육안으로 30분을 들여 수행하던 작업과 동일한 결과입니다. "그 30분은 무엇이었나" 싶어 솔직히 웃음이 났습니다.
경쟁사나 인접 도구들도 움직임이 있었습니다. 짧게 요약하겠습니다.
- GitHub Copilot Workspace: PR의 컨텍스트 (context)를 자동으로 좁히려는 움직임. 다만 공개된 정보상으로는 코드 의존성 그래프 (dependency graph)를 명시적으로 가지고 있는 구현은 보이지 않으므로, 정확도와 범위 측면에서는 KG (Knowledge Graph)를 직접 사용하는 편이 방식이 더 명확함.
- Sourcegraph Cody: 심볼 해결 (symbol resolution)과 스코프 (scope) 파악 능력이 강력함. Blast Radius (영향 범위)에 해당하는 거리 지표를 제공하는지는 리포지토리 측의 설정에 따라 크게 좌우됨.
- Aider의 repo-map: 리포지토리 전체를 가벼운 요약 그래프로 만들어 프롬프트 (prompt)에 삽입함. KG보다 거칠지만 도입 비용은 낮음. 우선 repo-map부터 시작하여 범위 축소 효과를 확인한 뒤, KG로 교체하는 단계적 접근이 가능함.
'새로운 무언가'가 아니라, 'AI가 읽는 범위를 의도적으로 좁힌다'는 발상이 2026-07 시점에 여러 도구로 확산되었습니다. KG는 그중에서도 의존 관계를 명시적인 그래프로 가지고 있는 만큼, 축소에 대한 설명 가능성 (explainability)이 높은 선택지입니다.
솔직하게 적어두겠습니다. KG 도입은 무료가 아닙니다.
- 최초 그래프 구축: 수 분 ~ 십수 분 (13만 행의 Python 리포지토리에서 7분)
- 업데이트 전략: 차분 (diff)만 업데이트하는 메커니즘을 CI (지속적 통합)에 구축할 필요가 있음
- 언어 의존성: Tree-sitter로 파싱할 수 없는 DSL (도메인 특화 언어)이나 생성된 코드는 정확도가 떨어짐
- 라이브러리 (site-packages) 측의 에지 (edge)를 어디까지 포함할지에 따라 취급이 달라짐
저는 "site-packages는 노드 (node)만 가져오고 에지는 연결하지 않는다"는 방식으로 운영하고 있습니다. 에지까지 포함하면 Blast Radius가 실질적으로 모든 파일로 퍼지기 쉬워져서, 축소 효과가 사라집니다.
이 부분에서 처음에 실수를 했습니다. 깊게 생각하지 않고 에지를 전부 연결했더니, "변경 1개 파일 → 영향 812개 파일"이라는 결과가 돌아왔고, 모니터 앞에서 "이건 이제 KG가 아니라 전부 읽기 경찰이네"라고 혼잣말을 했습니다. 빠지기 쉽다면 바로 이 지점일 것입니다. site-packages는 우선 "거리를 측정하기 위한 지도"에 포함하지 않는 것부터 시작하는 것이 안전합니다.
- AI 코드 리뷰의 "변경 파일 + 주변 50개"는 대개 과합니다.
- KG (Tree-sitter + 의존 그래프)로 Hop 0~2로 좁히면, 투입 파일은 중앙값 90.4% 감소합니다.
- 토큰 (token) 소비는 7~8배 가벼워지며, 리뷰 시간은 74초 → 16초로 단축됩니다.
- 검출률은 떨어지지 않고, 오탐 (false positive)은 오히려 절반으로 줄어듭니다.
- MCP를 통해 에디터에서 호출할 수 있습니다. 실제 PR에서 "그 30분은 무엇이었나"라며 웃을 수 있습니다.
- 도입 비용은 최초의 그래프 구축과 차분 업데이트 메커니즘입니다.
저는 이번 30개의 PR을 통해, "읽히는 양을 줄이는 것이 리뷰를 더 좋게 만들 수도 있다"는 결론을 확실히 얻었습니다. AI가 똑똑해지기를 기다리는 것보다, 전달할 컨텍스트 (context)를 설계하는 것이 많은 경우 더 빠르고 저렴합니다. 가지고 계신 리포지토리에서 한 번 Blast Radius를 계산해 보시면, 대개 깎아낼 수 있는 파일이 산더미처럼 발견될 것입니다. 재미있게 접근해 봅시다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기