"매 LLM 은 의도 (intent) 를 본다". AST 는 syntax, LLM 은 semantics 와 naming, 두 layer 를 합쳐야 진짜 review 가 된다.
매 핵심
매 두 layer
Deterministic (AST/SAST): ESLint, Semgrep, CodeQL — taint, null, type
Probabilistic (LLM): Claude/GPT — naming, design, "이 함수 왜 존재?", architectural smell
둘은 보완. LLM 만으로는 false-positive 폭발, AST 만으로는 의도 못 봄
매 응용
PR review bot: diff → LLM → 댓글
Refactor suggestions: "이 함수 분리해야" 제안
Code search semantic: Sourcegraph Cody, "auth 검증하는 곳" 자연어 검색
Doc generation: 함수 → docstring 자동
Bug hunt: "이 코드에 race condition 있나?"
💻 패턴
Pattern 1: PR review with Claude
# .github/workflows/claude-review.yml triggerimportanthropic,osfromgithubimportGithubdefreview_pr(pr_number):gh=Github(os.environ["GH_TOKEN"])pr=gh.get_repo(os.environ["REPO"]).get_pull(pr_number)diff=pr.get_files()diff_text="\n".join(f"{f.filename}\n{f.patch}"forfindiffiff.patch)client=anthropic.Anthropic()msg=client.messages.create(model="claude-opus-4-7",max_tokens=2000,system="You are a senior reviewer. Comment only on real issues. Skip nits.",messages=[{"role":"user","content":f"Review this diff:\n{diff_text}"}],)pr.create_issue_comment(msg.content[0].text)
Pattern 2: AST + LLM hybrid
importastdeffind_long_functions(src):tree=ast.parse(src)return[nforninast.walk(tree)ifisinstance(n,ast.FunctionDef)and(n.end_lineno-n.lineno)>50]# AST 가 후보 추림 → LLM 이 의도 분석forfninfind_long_functions(open("app.py").read()):snippet=ast.get_source_segment(src,fn)ask_llm(f"Why is this function long? Should it be split?\n{snippet}")
# CLI
cody chat "어디서 user session 검증하는지 찾아줘"# → ranks files by semantic match, not grep
Pattern 5: Cost guard for LLM review
# 큰 PR 은 file-by-file, small 은 한번에defchunk_strategy(diff_lines):ifdiff_lines<200:return"single"ifdiff_lines<1000:return"per_file"return"summary_only"# 대형 PR 은 high-level summary 만
Pattern 6: Prompt for naming smell
You are reviewing variable/function names. Flag ONLY:
- Unclear (data, info, tmp, x)
- Lying (getUser that mutates)
- Inconsistent with rest of codebase
Output JSON: [{file, line, suggestion}]
Pattern 7: Reject auto-merge if LLM finds blocker
- name:LLM gaterun:python review.py --severity-threshold blocker# exit 1 if any "blocker" found
매 결정 기준
상황
Approach
Type/null/taint 검출
AST/SAST (deterministic)
Design / naming / intent
LLM
둘 다 필요
Hybrid (AST 후보 → LLM 분석)
큰 PR (>1k line)
Summary only, per-file 비용 폭발
Security critical
CodeQL primary, LLM secondary
기본값: Semgrep + Claude review bot, blocker 만 PR 차단.