BETAER_

04 / Notes — 04 fragments

Notes

글이 되기엔 작고 버리기엔 아까운 조각들. 오늘 배운 것을 그대로 남깁니다. 

2026.07.06
RustTree-sitter

Tree-sitter 0.23으로 다국어 파서를 하나의 인터페이스로 묶기

16개 언어를 지원한다고 파서 경로를 16개 만들면 유지보수가 끝장난다. amdb는 공통 심볼 추출 경로 하나를 두고, 언어별 차이는 enricher로만 분기한다. 모든 언어가 지나가는 길은 같다: 소스 → Tree-sitter 파스 → 심볼 노드 수집. is_public 판정이나 시그니처 추출처럼 문법 지식이 필요한 강화만 언어별 enricher(Rust · Python · TypeScript)가 담당하고, enricher가 없는 언어는 심볼 추출까지만 지원한다. 새 언어 추가 비용이 "grammar crate + 쿼리"로 고정되는 것이 이 구조의 핵심이다.

2026.05.21
Search

하이브리드 검색: exact match 우선, vector search는 대체 경로

vector search만 쓰면 authenticate라고 정확히 입력해도 의미상 비슷한 다른 심볼이 위로 올라올 수 있다. 그래서 amdb의 focus 모드는 질의를 심볼 이름에서 먼저 exact match로 찾고, 없을 때만 vector search로 넘어간다. 유사도 임계값은 0.25 — 이보다 낮은 결과는 컨텍스트에 넣지 않는다.

amdb generate --focus "login authentication jwt" --depth 1

찾은 심볼에서 --depth만큼 call graph를 따라가 호출 관계에 있는 코드까지 컨텍스트를 확장한다. 저렴하고 결정적인 경로를 항상 앞에 세우는 것이 원칙이다.

2026.04.02
EmbeddingsLocal-first

로컬 임베딩에 fastembed를 택한 이유

amdb의 전제는 코드가 머신 밖으로 나가지 않는 것이다. 클라우드 임베딩 API는 품질이 좋아도 이 전제를 깨므로 선택지가 아니었다. fastembed는 ONNX Runtime 위에서 임베딩 모델을 온디바이스로 돌린다. API 키도, 요청당 과금도, 네트워크 왕복도 없다. 트레이드오프는 첫 실행 시 모델 파일을 한 번 내려받아야 한다는 것 — 이후에는 완전 오프라인으로 동작한다. 클라우드 인덱싱이 금지된 보안 민감 환경에서는 이 트레이드오프가 사실상 유일한 답이다.

2026.03.12
RustSQLite

rusqlite bundled + bincode로 의존성 없는 로컬 벡터 저장

외부 벡터 DB를 붙이는 순간 "설치 한 번으로 끝나는 CLI"가 아니게 된다. amdb는 심볼, 관계, 임베딩을 전부 SQLite 파일 하나에 담는다. rusqlite의 bundled 피처를 쓰면 SQLite가 바이너리에 정적으로 포함되므로 시스템에 설치된 sqlite 버전을 타지 않는다. 임베딩 벡터는 bincode로 직렬화해 BLOB 컬럼에 넣는다. cargo install amdb 한 줄로 끝나는 배포는 이 두 선택 위에 서 있다.