| name | code-search-efficient |
| description | 코드 분석/탐색 시 토큰을 최소화하면서 정확도를 최대화하는 도구 선택과 검색 전략. ast-grep(sg)
구문 인식 검색, ripgrep, fd, LSP, Glob의 우선순위·조합 가이드. 코드 검색, 심볼 탐색,
리팩토링, 패턴 찾기, "어디서 쓰이는지", "구현체 찾아줘" 등의 요청 시 자동 적용.
출처: msbaek/dotfiles `<tool_preferences>` 패턴을 로컬 환경에 어댑테이션.
|
Efficient Code Search
도구 우선순위 (Decision Tree)
질문이 들어옴
│
├─ 언어가 Java인가? ──── YES ──► jdtls LSP (rules/java-lsp-exploration.md)
│
├─ 언어가 Kotlin(.kt/.kts)인가? ──── YES ──► kotlin-lsp (rules/kotlin-lsp-exploration.md)
│
├─ 구조적 매칭 필요? (메서드 시그니처, 데코레이터, ──► sg (ast-grep)
│ JSX props, 함수 호출 패턴 등)
│
├─ 단순 텍스트 검색? ────────────────────────────────► rg (Grep tool)
│
├─ 파일명 패턴? ────────────────────────────────► fd / Glob tool
│
├─ 큰 파일 구조 파악? ────────────────────────────────► LSP documentSymbol
│ → fallback: Read offset/limit
│
└─ 백링크/문서 그래프? (마크다운/노트) ────────────────► markdown-oxide LSP / obsidian-vault skill
sg (ast-grep) 사용법
sg는 AST 패턴 매칭 도구. 정규식보다 정확하고 짧으며 오탐이 거의 없다.
핵심 메타변수
| 변수 | 의미 |
|---|
$NAME | 단일 노드 (식별자, 표현식 등) 1개 |
$$$NAME | 여러 노드 (가변 인자, 본문 statement 묶음) |
$_ | 임의의 단일 노드 (이름 없음) |
$$$_ | 임의의 다수 노드 (이름 없음) |
Java 예시
sg --lang java -p '@Transactional
public $RET $METHOD($$$ARGS) { $$$ }'
sg --lang java -p '$LIST.stream().filter($$$).collect($$$)'
sg --lang java -p 'throw new $EXCEPTION($$$ARGS)'
sg --lang java -p 'public $RET $METHOD($$$) { $$$ }' \
--globs '**/*Service.java'
TypeScript / React 예시
sg --lang tsx -p 'useEffect(() => { $$$ }, [])'
sg --lang ts -p 'console.log($$$)'
sg --lang tsx -p '<UserCard $$$ />'
sg --lang ts -p 'axios.$METHOD($URL, $$$)'
Python 예시
sg --lang python -p '@$DEC
def $FN($$$): $$$'
sg --lang python -p 'try: $$$
except Exception: $$$'
sg --lang python -p 'print($$$)'
리라이트 (sg --rewrite)
sg는 검색뿐 아니라 AST 기반 일괄 변환도 가능. Edit 도구로 100번 수정할 일을 한 번에.
sg --lang ts -p 'console.log($$$ARGS)' --rewrite 'logger.debug($$$ARGS)'
sg --lang ts -p 'console.log($$$ARGS)' --rewrite 'logger.debug($$$ARGS)' --json
fd 사용법
find 보다 빠르고 직관적. .gitignore 자동 존중.
fd -e java -e kt
fd -e ts -e tsx src/
fd '^Test' -e java
fd -t d 'service'
fd --changed-within 1d -e java
fd -e java | xargs wc -l | tail -5
fd -0 -e java | xargs -0 sg --lang java -p '...'
rg (ripgrep) 사용 팁
Claude Code에서는 Grep tool 을 사용 (Bash로 rg 직접 호출 금지). 아래는 사고 모델용.
rg --type java 'Service'
rg -tjava -tkotlin 'PaymentGateway'
rg 'TODO' -A 3
rg -c 'logger\.debug' src/
rg -l 'BeforeCommit' tests/
rg -U --multiline '@Transactional[\s\S]*?public'
LSP First (Java)
Java는 항상 rules/java-lsp-exploration.md 를 우선 적용. 아래는 빠른 매핑:
| 의도 | LSP 함수 | grep으로 했다면 발생할 문제 |
|---|
OrderService.cancel() 정의 | goToDefinition | 동명이인, 인터페이스/구현체 혼동 |
cancel() 사용처 | findReferences | cancel 단어가 들어간 모든 메서드 오탐 |
PaymentGateway 구현체 | goToImplementation | implements 라인만으로는 추상 클래스 누락 |
| 호출 경로 | incomingCalls | 람다·메서드 레퍼런스·SAM 변환 추적 불가 |
토큰 절약 패턴
1. 카운트/통계 먼저, 본문 나중에
rg 'logger.error' src/
rg -c 'logger.error' src/ | sort -t: -k2 -n -r | head -10
2. files-with-matches로 분할 정복
rg -l 'PaymentEvent' src/main/java/
3. 출력 → 임시 파일
대량 결과는 /tmp/ 에 저장 후 필요한 부분만 Read.
sg --lang java -p '...' > /tmp/sg-results-$$.txt
wc -l /tmp/sg-results-$$.txt
4. 큰 파일은 LSP documentSymbol 부터
Read file (3000줄) → 즉시 컨텍스트 폭발
LSP documentSymbol(file) → 50줄 심볼 트리 → 필요한 메서드만 Read offset/limit
Anti-patterns (해서는 안 됨)
- ❌ Java 심볼 탐색을
rg/Grep 으로 (LSP가 있는데도)
- ❌ 1000줄 파일을 통째로 Read 후 "정리해줘"
- ❌ 100개 매치를 그대로 컨텍스트에 받고 AI가 스크롤
- ❌ 정규식으로 메서드 호출 패턴 매칭 ("$x.foo($$$)" 같은 sg 패턴이 정확)
- ❌
find 대신 fd 사용 안 함 (느리고 .gitignore 무시)
- ❌ 파일 일괄 변환을 Edit 도구로 100번 (sg --rewrite 한 번이면 됨)
설치 검증
which sg ast-grep fd rg jdtls
sg --version
fd --version
rg --version