로컬 인덱싱으로 도구 호출과 토큰 사용량 줄이기

Local Indexing to reduce tool calling and token usage

tedhaley.ca ▲ 119 댓글 49 TedHaley

요약

맥의 파일·코드·에이전트 세션을 로컬에서 인덱싱해 에이전트의 도구 호출과 토큰을 줄이는 무료 앱입니다.

개발자 테드 헤일리가 만든 오픈소스 맥 앱 Pensieve의 소개 페이지입니다. 코딩 에이전트가 디스크 전체를 grep으로 뒤지는 대신, 뜻으로 찾는 검색 한 번으로 필요한 대목에 닿게 하자는 취지입니다.

왜 중요한가

  • 에이전트가 grep과 파일 읽기를 되풀이하며 쓰는 호출 횟수와 비용을 검색 도구 하나로 줄일 수 있다는 주장입니다.
  • 인덱싱과 검색을 모두 기기 안에서 처리해, 코드를 클라우드로 보내지 않고도 의미 검색을 쓸 수 있다는 점을 내세웁니다.

핵심 내용

  • 개발자 자체 측정에서 조회 한 번에 드는 도구 호출이 3.4회에서 2.0회로 약 43% 줄었습니다.
  • 같은 측정에서 조회당 비용은 약 18% 낮아졌고, 맞는 파일을 찾은 횟수도 144회 중 123회에서 131회로 늘었습니다.
  • MCP(에이전트가 외부 도구를 부르는 표준 규약)로 Claude Code, Codex, Cursor 등에 붙고 "grep 전에 먼저 검색하라"는 지침을 넣습니다.
  • git blame으로 영역별 담당자를 보여 주고, 주 작성자가 떠난 지식 공백 영역도 짚어 줍니다.
  • 전체 기능은 Apple Silicon 맥과 macOS 14 이상에서 돌아가며, MIT 라이선스로 무료입니다.

HN 반응

  • grep은 빠르고 늘 최신인데 인덱스는 브랜치를 바꿀 때마다 낡은 결과를 준다는 반론이 많았고, Cursor의 숨은 인덱스가 자주 낡았다는 경험담도 나왔습니다.
  • 비슷한 도구가 매달 나온다는 지적과 함께, 에이전트에게 스크립트를 curl로 받아 bash로 돌리게 하는 설치 방식을 꼬집는 댓글도 있었습니다.

댓글

30개 표시 · 전체 49개
  1. tinthedev HN

    이런 도구들 상당수는 엉뚱한 나무에 대고 짖고 있다는 느낌이 듭니다. 더 깊은 근본 원인의 증상일 뿐인 문제를 풀고 있으니까요. 코드베이스가 너무 커서 grep이 안 되니 인덱스를 만들고, hard_decline을 카드 재시도로 바꿔 말하려고 인덱스를 만들고, 에이전트가 YOLO식으로 검색을 돌려대는 걸 줄이려고 도구 호출을 줄이고, 이런 식입니다.

    나쁜 코드베이스 위생을 도구를 더 얹어서 극복하려는 것, 곰팡이 위에 벽지를 바르는 것처럼 느껴집니다. LLM에게 전부 맡겨 둔 코드베이스는 이 문제가 아주 심각하지만, 조금만 신경 써도 기대 이상의 효과를 얻을 수 있다는 걸 알게 됐습니다. 에이전트가 모든 걸 거대한 코드 덩어리로 뭉개 놓게 두지 마세요. 관심사를 분리하고, 서비스를 만들고, 소프트웨어 설계의 아키텍처 단계를 바이브 코딩보다 조금 더 공들여 하세요.

    좀 푸념이긴 합니다만, 이런 도구가 왜 존재하는지 모르겠습니다(게다가 스크립트를 curl로 받아 bash에 넘기라고까지 하죠). grep이 병목이라면 뭔가 잘못하고 계신 겁니다.

  2. hedgehog HN

    grep으로 충분했다면 LSP는 생기지 않았을 겁니다. 최소한 구조를 인식하는 검색은 필요해요. 사람이 쓰기 편하게 하려는 것만으로도 그렇고, 로봇한테도 마찬가지고요.

  3. CharlieDigital HN

    "인덱싱"은 아주 포괄적인 용어라서, 엉뚱한 나무에 대고 짖는 일이라고는 생각하지 않습니다.

    도서관 카드 목록 시스템도 인덱스입니다. 원하는 책을 빨리 찾게 해 주려고 존재하죠.

    식료품점의 진열대 구분도 인덱스입니다. 제빵 재료와 세제·청소용품을 쉽게 찾게 해 주니까요.

    잘 정리된 코드베이스는 이미 프로젝트별, 폴더 구조별, 명명 규칙별 등으로 인덱스가 되어 있습니다.

    우리는 크든 작든 어디서나 인덱스를 씁니다.

    진짜 문제는 하니스, SDK, API 자체가 처음부터 인덱스를 염두에 두고 설계되지 않은 것처럼 보인다는 점입니다.

  4. bjornroberg HN

    저도 대체로 같은 생각이지만, 실제로 측정해 보면 정말 흥미로울 것 같아요. 예를 들어 품질이 Q1인 코드베이스와 Q2인 코드베이스에서 grep과 시맨틱 검색을 쓸 때 토큰이 각각 얼마나 드는지 같은 거요. 그리고 올바른 네임스페이스에서 올바른 DuplicateSymbolName을 찾았는지도요.

  5. ryuuseijin HN

    저도 slopdex1라는 로컬 인덱스 도구를 만들었습니다.

    아주 단순한 도구입니다. 저장소의 코드와 문서를 treesitter로 파싱해서 인덱싱하고 전부 벡터화한 다음, 코드베이스 지도를 만들거나 시맨틱 검색을 할 수 있게 해 줍니다.

    잘 먹히는 기능 하나는 cross-search 명령인데, 벡터 인덱스로 중복 코드를 검색할 수 있습니다. 많은 LLM이 중복된 헬퍼 함수를 잔뜩 만들어 내는 사각지대가 있는데, 이걸 없애 줍니다. 실제로 꽤 잘 동작합니다.

    아직 다듬는 중인 평가(eval)가 몇 가지 있는데, map 명령을 썼을 때 토큰 사용량은 10% 정도 줄어드는 수준으로 소폭 개선에 그쳤습니다. 다만 작업 유형에 따라 많이 달라질 것 같습니다.

    피드백을 주시면 기쁘겠습니다.

  6. flecomet HN

    좋은 도구네요. qdrant https://qdrant.tech/ 같은 로컬 임베딩 제공자도 지원하나요? 왜 유료 클라우드 임베딩 제공자만 지원하나요?

    ChatGPT는 코드를 수정하지 않아도 동작할 수 있다고 하는데, README에는 그런 얘기가 없어서 이런 선택을 한 이유가 궁금했습니다.

    ChatGPT의 답은 이렇습니다. "Slopdex를 유료 임베딩 API 없이 실행할 수 있을까?

    코드를 수정하지 않아도 가능성이 있다. [...] Slopdex는 사용자 지정 embeddingBaseUrl을 지원하므로, 로컬에서 호스팅하는 OpenAI 호환 임베딩 서버를 호출할 수 있다. 예를 들어 768차원 벡터를 만드는 로컬 모델을 쓰면 다음과 같다. { "provider": "openai", "model": "your-local-embedding-model", "dimensions": 768, "symbolDimensions": 768, "embeddingBaseUrl": "http://localhost:1234/v1" }

    코드는 여전히 OPENAI_API_KEY 값을 요구하지만, 로컬 서버가 인증을 강제하지 않는다면 더미 키로도 동작할 것이다.

    서버는 /v1/embeddings를 구현해야 하고, dimensions 매개변수를 포함한 Slopdex의 요청 형식을 받아들여야 한다. 관련 코드는 vector_openai.rs에 있다."

  7. gandreani HN

    구현이 궁금합니다. 버전 관리되는 코드베이스에서 벡터 검색은 어떻게 동작하나요?

    커밋 A에서 작업을 저장하고 커밋 B로 옮겨 갔을 때, cross-search가 커밋 A에만 있던 코드(즉 지금은 코드베이스에 없는 코드)를 결과로 돌려주지 않는 건 어떻게 보장하나요?

  8. ryuuseijin HN

    인덱스 상태는 커밋 해시에 대응하고, 이게 바뀌면(커밋 B로 이동하면) git으로 바뀐 파일을 비교해서 삭제된 파일과 함수는 인덱스에서 지우고 새 파일은 파싱합니다.

    벡터 임베딩은 캐시해 두지만, 커밋에 맞게 인덱스에 넣고 빼는 건 그대로 합니다.

  9. Ginger-Pickles HN

    저장소와 함께 구현에 얽매이지 않는 자연어 명세를 공개하면, 다른 코딩 에이전트들이 각자 병렬 구현을 만들고 변경할 수 있을 텐데요. 이 아이디어를 어떻게 보시는지 궁금합니다.

  10. ryuuseijin HN

    흥미로운 아이디어네요. 다만 에이전트에게 코드를 직접 보여 줘도 똑같이 잘 될 거라고 생각합니다. 적어도 이 용도로 자연어 명세가 더 낫다는 이유는 잘 모르겠습니다.

  11. striking HN

    https://github.com/huggingface/funes/ 가 (특히 대화 검색용으로) 제가 늘 쓰던 도구입니다. 그래도 이쪽은 세션을 불러와서 알맞은 에이전트를 열어 주는 프런트엔드가 있어서 좋네요. (저는 에이전트를 하나 열었다가 잘못 골랐다 싶으면 다른 걸 또 열었거든요.) 보기 좋습니다. 잘 만드셨어요.

  12. throwaway219450 HN

    보르헤스 인용이 멋지네요. 다만 엉성한 문서 때문에 좀 헷갈립니다("funes makes four deliberate, load-bearing choices"). Claude가 문서를 써 준 프로젝트가 다 그렇듯, 정말 중요한 게 뭔지 파악하기가 어렵습니다. HF에서 나온 거라 평범한 바이브 코딩 결과물보다는 조금 더 믿고 싶긴 합니다.

    제가 의심하는 건, 에이전트 메모리가 만만치 않은 문제라서 그렇지 않았다면 연구소들이 벌써 하니스에 해결책을 넣었을 거라는 점입니다. 모델은 시키면 이전 대화를 기꺼이 확인하지만, 기본값으로 알아서 하는 일은 드뭅니다.

    평문 "일기"의 장점은 사람도 읽을 수 있고, 에이전트가 커밋 해시, 대화 ID, 실험 실행 링크 같은 것도 적어 둘 수 있다는 점입니다. 외부 도구 없이 모델이 달라져도 그대로 쓸 수 있고요.

  13. pcthrowaway HN

    "사용자에게 에이전트한테 스크립트를 curl로 받아 bash로 파이프하라고 시키는 것"이 새로운 "사용자에게 스크립트를 curl로 받아 bash로 파이프하라고 시키는 것"인가요?

    페이지의 나머지 내용이 없었다면 농담인 줄 알았을 거예요.

  14. ramses0 HN

    안녕, 잔인한 세상이여!

  15. swiftcoder HN

    최근 몇 주 사이에 바이브 코딩으로 만든 도구 사이트에서 적어도 대여섯 번은 봤어요.

  16. sheo HN

    이런 종류의 도구를 스무 개쯤 봤는데, 매달 새로운 게 나옵니다. Cursor도 한때 비슷한 걸 갖고 있었어요. 지금은 없앴지만요.

    그래도 다른 세션을 참조한다는 건 좋은 아이디어네요.

  17. TowerTall HN

    Cursor도 한때 비슷한 걸 갖고 있었어요. 지금은 없앴지만요.

    아니요, 없앴다고 하지만 안 없앴습니다. Cursor는 로컬 인덱싱을 접고 "instant grep"이라는 걸로 대체했다고 하는데, 자체 지원팀 말로는 이건 로컬 인덱스를 쓰지 않는다고 합니다. 그리고 인덱스를 다시 만들 수 있게 하던 Cursor 설정의 도구도 없앴고요.

    하지만 Cursor는 여전히 로컬 인덱스를 씁니다. ".git" 폴더 아래 하위 폴더에 숨겨 놨을 뿐이에요. "~/.git/cursor"요.

    이 숨겨진 인덱스는 걸핏하면 낡은 상태가 되어서, 파일을 많이 바꿀 때마다 그 폴더를 날려야 했습니다. 새로운 일도 아닙니다. 공식적으로 로컬 인덱스가 있던 때도 자주 낡아 있었어요. 저는 하루 단위로, 몇 시간마다 돌면서 Cursor의 인덱스가 낡았을 때 알려 주는 스크립트까지 만들었습니다.

    Cursor가 분명히 있는 문서를 갑자기 못 찾는 일이 없는지 계속 지켜봐야 했고, 오래된 내용을 가지고 작업하는 일도 흔했습니다. 참고로 instant grep을 끄면 숨겨진 인덱스가 사라지고 문제도 없어집니다.

  18. boyter HN

    하하, 맞아요. 저도 제 도구를 하나 올려 볼게요. https://github.com/boyter/cs 입니다. 시작한 지 7년이 되어서 다른 도구 대부분보다 훨씬 오래됐어요.

    Cursor는 인덱스를 유지하던 흥미로운 사례였죠. 지금은 다들 인덱스를 유지하지 않는 쪽으로 수렴했다고 생각하고, 저도 거기서 출발해서 BM25에 몇 가지 조정을 얹었습니다.

    이와 관련해서 눈여겨볼 링크가 있습니다. https://www.youtube.com/watch?v=ZnmtJKFonLk 에서 검색 분야에서 유명한 Jo Kristian Bergum이 BM25가 에이전트 워크플로에 좋은 접근이라는 데 동의합니다.

  19. ProblemExplorer HN

    Cursor도 한때 비슷한 걸 갖고 있었어요. 지금은 없앴지만요.

    왜 없앴는지 아시는 분이 있다면 정말 고맙겠습니다. 그 이유에 이 아이디어가 애초에 쓸 만하고 지속 가능한지에 대한 열쇠가 있을지도 모르니까요.

  20. victorbjorklund HN

    많은 사람이 하는 말로는, 실제로는 AI가 그냥 grep을 쓰게 두는 편이 결과가 더 좋았기 때문이라고 해요.

  21. bentt HN

    언젠가는 이런 도구를 홍보하는 첫 화면이 에이전트가 직접 설치하고 쓸지 결정하도록 최적화될 겁니다. 사람은 그냥 "비용을 최적화해 줘"라고만 하고, 에이전트가 이런 걸 찾아서 쓰기 시작하는 거죠. 사람은 알지도 못하고 신경도 쓰지 않는 채로요.

  22. david-gpu HN

    사람도 광고와 선전에 넘어가기는 마찬가지입니다.

  23. s08148692 HN

    LLM이 만든 웹사이트는 한눈에 알아볼 수 있어요.

    바이브 코딩으로 만든 도구는 훌륭합니다. 저도 제 워크플로에 맞춘 도구를 잔뜩 갖고 있어요. AI 덕분에 나만의 도구를 거의 공짜로 만들 수 있게 됐죠. 그런데 공유하거나 배포할 만한 건 거의 없습니다.

  24. GrinningFool HN

    투입한 시간에 따른 곡선이 있다고 생각해요. 아키텍처와 설계에 신경 쓰면서 충분한 시간(몇 주나 몇 달)을 들여 반복하고 다듬었다면 공유할 만할지도 모릅니다. 며칠이나 일주일 만에 끝냈다면 아마 아닐 거고요.

  25. agentdev001 HN

    빨간 점이 찍힌 Lockheed Venture 사진을 여기에 넣어 주세요.

  26. braiamp HN

    그런데 제가 상사에게 저런 모양이 아닌 걸 가져가면 일을 제대로 못 한 게 되는데요. 그러면 LLM이 만든 사이트가 나쁜 걸까요, 아니면 그저 인센티브 구조가 거슬릴 일을 줄이는 쪽으로 최적화된 걸까요?

  27. hanumseous HN

    이 도구는 파일 검색이 얼마나 빠른가요? 퍼지 검색도 지원하나요?

  28. febed HN

    임베딩 모델을 내려받나요? 그렇다면 어떤 모델인가요? 어떻게 동작하는지에 대한 정보가 거의 없네요.

  29. uzerkayat HN

    API 비용이나 에이전트의 토큰 사용 때문에 가장 크게 타격을 입은 곳이 어디였나요?

  30. ltbarcly3 HN

    제 경험상 대체로 grep이 다른 어떤 것보다 낫습니다. 아주아주 빠르고 효율적이고 유연하며, 인덱싱 과정이 필요 없고, 낡은 상태가 될 일이 없으며, 어떤 파일을 검색하게 될지 어떻게 검색어를 처리할지 미리 짐작할 필요도 없습니다.

    "Search your files, repos and agent sessions, locally, and give your agents the best context for the job. One search points them to the few passages that matter, instead of grepping the whole disk."

    ("파일, 저장소, 에이전트 세션을 로컬에서 검색해 에이전트에게 작업에 가장 알맞은 컨텍스트를 주세요. 디스크 전체를 grep하는 대신, 한 번의 검색으로 중요한 몇 개 구절을 가리킵니다.")

    grep도 이미 도구 호출 한 번으로 관련 구절을 검색합니다. 이건 누가 봐도 LLM이 쓴 문구예요. 말이 되는 구석이 하나도 없습니다.

    틱톡에서 계속 보이는 데이팅 앱 광고가 생각나네요. 다른 데이팅 사이트는 "프로필에서 당신이 가장 큰 목소리를 내도록 강요한다"고 하는 광고인데, 말이 되게 해석할 방법이 없고 전형적인 LLM식 헛소리일 뿐입니다.

    로컬 파일을 인덱싱하면 검색이 빨라집니다(이론상으로는요. 빠른 SSD에 수십 GB 이하의 로컬 파일이라면 실제로는 아닐 수도 있고요). 하지만 더 유연해지거나 도구 호출이 줄어들지는 않습니다.

    또 인덱스는 늘 디스크의 실제 상태보다 조금 뒤처지기 마련인데, 활발히 개발 중인 무언가의 모든 참조를 찾거나 브랜치를 바꿀 때는 이게 치명적입니다. 브랜치를 체크아웃하고 이 도구를 호출하면 거짓말을 할 겁니다. 이제는 일치하지 않는 파일에 일치하는 항목이 있다고 LLM에게 말하고, 줄 번호는 틀리고, 다른 파일의 일치 항목은 놓칩니다. 브랜치를 바꿀 때마다 전부 다시 인덱싱한다고 난리가 날 거고요. 그나마 가장 좋은 경우가 grep과 비슷한 성능에, 낡은 데이터에, 검색할지 안 할지도 모르는 파일까지 인덱싱하느라 쓸데없는 일을 잔뜩 하는 것입니다.

    grep은 일반 정규식을 받는데, 정규식은 사실상 인덱싱이 안 됩니다. 그래서 grep보다 더 유연하거나 도구 호출을 더 줄이는 건 거의 없습니다.

    grep은 말도 안 되게 빠르기도 합니다. 얼마나 빠른지 모르신다면, 생각보다 더 빠릅니다. 저는 ripgrep으로 체크아웃해 둔 모든 코드, 대략 11GB 정도를 0.2초에 검색합니다(일반 GNU grep은 .git/ 폴더를 제외하지 않고 프로세서도 하나만 써서 주로 그 때문에 4초가 걸립니다).

      xyz@xx:~% du -sh checkout
      11G checkout
      xyz@xx:~% time rg robotic checkout|wc -l
      19
      rg robotic checkout  1.14s user 1.07s system 1151% cpu 0.192 total
      wc -l  0.00s user 0.00s system 1% cpu 0.192 total
    

Hacker News에서 보기 ↗