
Claude 토큰을 낭비하지 마세요: 코드를 먼저 탐색하는 무료, 로컬, 보안 방식
요약
Claude나 ChatGPT의 토큰 낭비를 줄이기 위해 로컬에서 코드베이스를 탐색할 수 있는 오픈소스 도구 'talk-to-your-code'를 소개합니다. Ollama를 활용해 로컬 모델로 코드 인덱싱과 질문 답변을 수행함으로써 비용을 절감하고 보안을 강화합니다.
핵심 포인트
- 로컬 인덱싱을 통해 클라우드 API 비용 및 토큰 소모 절감
- Ollama를 사용하여 로컬 모델로 무료 및 보안 환경 제공
- 코드베이스 청킹 및 로컬 DB 저장을 통한 빠른 컨텍스트 구축
- Claude 사용 전 코드 구조 파악을 위한 사전 탐색 도구로 활용
Claude나 ChatGPT를 익숙하지 않은 코드베이스(codebase)에 연결하고 "인증 로직(auth logic)이 어디에 있나요?"라고 물을 때마다, 여러분은 단순히 방향을 잡기 위해 실제 비용과 컨텍스트(context)를 소모하고 있습니다.
모델은 한 번도 본 적 없는 파일을 읽고 구조를 추측해야 하며, 여러분은 고도의 추론(reasoning) 문제가 아닌 본질적으로 Google Maps 수준의 질문을 위해 API 토큰을 지불하거나(또는 메시지 제한을 소모하거나) 하고 있습니다.
talk-to-your-code는 이를 위한 깔끔한 해결책입니다. 이는 여러분의 로컬 머신에서 코드베이스를 인덱싱(indexing)하고, 클라우드 API 대신 Ollama를 통해 작은 로컬 모델을 사용하여 일상적인 영어 질문을 던질 수 있게 해주는 작은 로컬 앱입니다.
이 아이디어는 Claude를 대체하려는 것이 아니라, 저렴하고 반복적인 "먼저 주변을 살펴볼게요"와 같은 작업을 로컬에서 무료로 수행하는 것입니다. 이를 통해 Claude와 대화할 때쯤이면 여러분은 이미 어떤 파일이 중요한지 알고 있으며, 날카롭고 좁은 범위의 질문을 던질 수 있게 됩니다.
전체적인 그림: 실제로 일어나는 일
높은 수준에서 보면, 이 앱은 네 가지 작업을 순차적으로 수행합니다:
- 저장소(repo)를 탐색하고 파일을 청크(chunks) 단위로 나눕니다.
- 해당 청크들을 로컬 데이터베이스(database)에 저장합니다.
- LLM이 질문과 관련된 청크가 무엇인지 파악하도록 합니다. (컨텍스트 구축 (Context building))
- LLM이 오직 해당 청크들만을 사용하여 답변하도록 합니다.
> 모든 저장소 수집 (Ingests any repository)
이 작업은 "Ingest"를 클릭할 때 한 번 발생합니다. 그 이후의 실제 대화와 같은 모든 작업은 원본 파일이 아닌 이 로컬 데이터베이스를 대상으로 실행됩니다.
이것이 중요합니다. 앱이 질문을 할 때마다 저장소 전체를 다시 읽지 않기 때문에, 각 질문이 빠르고 저렴하다는 것을 의미합니다.
> 실제로 질문을 할 때 일어나는 일
실제로 각 단계에서 수행되는 작업은 다음과 같습니다:
-
쿼리 계획 수립 (Build a query plan). 사용자의 가공되지 않은 질문이 검색 시스템(retrieval system)이 실제로 사용할 수 있는 형태로 변환됩니다. 즉, 검색할 키워드, 관련성이 있다고 의심되는 파일, 그리고 질문의 유형(설명 요청 vs 디버깅 vs 위치 찾기)을 결정합니다.
-
하이브리드 검색 (Hybrid retrieval). 여기서 "하이브리드"란 관련 청크(chunk)를 찾는 서로 다른 방식들을 결합한다는 의미입니다. 키워드 검색, 심볼 매칭 (예: "authenticate라는 이름의 함수를 찾아줘"에 유용), 그리고 임베딩 유사도 검색 (예: 정확한 문구가 없더라도 "이와 유사한 동작을 하는 코드를 찾아줘"에 유용)을 결합합니다. 이 두 방식을 모두 사용하면 어느 한 방식만 사용할 때보다 더 많은 관련 코드를 포착할 수 있습니다.
-
예산 기반 컨텍스트 빌더 (Context builder with a budget). 이는 화려하지는 않지만 매우 중요한 단계입니다. 매칭된 모든 청크를 단순히 LLM(대규모 언어 모델)에 전달할 수는 없습니다. 컨텍스트 윈도우(context window)는 유한하며, 관련 없는 코드를 채워 넣는 것은 토큰을 낭비하고 모델을 혼란스럽게 만듭니다. 따라서 빌더는 관련성에 따라 청크의 순위를 매기고, 사용자가 제어할 수 있는 문자/토큰 제한(UI의 "컨텍스트 길이 슬라이더") 내에서 가능한 한 많은 청크를 채워 넣습니다.
-
구조화된 답변 생성 (Generate a structured answer). 최종적인 LLM 호출 시 사용자의 질문과 채워진 컨텍스트가 함께 전달되며, 특정 스키마(schema)에 따라 답변을 생성하도록 요청됩니다. [예시]
class StructuredAnswer(BaseModel):
summary: str
relevant_files: list[str]
...
이것이 전부입니다. 일반적인 검색 단계가 중간에 끼어 있는 두 번의 구조화된 LLM 호출로 이루어집니다. 무한히 루프를 도는 에이전트(agent)도, 제한 없는 도구 호출(tool calls)도 없습니다. 의도적으로 작고 예측 가능한 파이프라인입니다.
중요한 세부 사항:
"인증 처리는 어디에서 이루어지나요?"와 같은 질문을 입력할 때, 앱은 단순히 코드를 프롬프트에 쏟아붓고 결과가 잘 나오기를 기도하는 방식이 아닙.
이 앱은 LLM을 두 번 실행하며, 매번 구조화된 생성 (structured generation) (제약된 디코딩 (constrained decoding)이라고도 함)을 사용하여 특정 출력 형태를 강제합니다. 이를 통해 파싱해야 하거나 유효성을 기대해야 하는 자유 형식의 텍스트(free text) 대신, 보장된 JSON 객체를 결과로 받게 됩니다.
Python에서는 해당 스키마(schema)가 일반적으로 다음과 같은 Pydantic 모델 형태입니다: [Example]
from pydantic import BaseModel
class QueryPlan(BaseModel):
keywords: list[str]
...
이 구조화된 데이터를 LLM 호출에 전달하면 API가 응답이 이에 일치함을 보장합니다. 가끔 추가적인 설명이 붙어서 돌아오는 "JSON으로 응답해 주세요"와 같은 프롬프트는 더 이상 필요하지 않습니다.
요약:
이 리포지토리가 깔끔하게 보여주는 몇 가지 사항은, 일단 LLM으로 무언가를 만들기 시작하면 어디에서나 마주하게 될 내용들입니다:
- JSON을 위해서는 프롬프팅보다 구조화된 생성이 더 낫습니다. Pydantic 스키마를 정의하고 이를 호출에 바인딩하는 것이, 프롬프트에 정중하게 요청하고 정규 표현식(regex)으로 응답을 파싱하는 것보다 훨씬 더 신뢰할 수 있습니다.
- "적절한 컨텍스트 찾기"와 "질문에 답하기"를 분리하세요. 검색(retrieval)과 생성(generation)을 하나의 거대한 프롬프트에 묶어버리면, 관련 없는 코드에 대해 환각(hallucination)이 섞인 답변을 얻게 됩니다.
이를 '계획(plan) → 검색(retrieve) → 답변(answer)' 파이프라인으로 나누면 각 단계의 역할이 작아지고 검증 가능해집니다. 최종 답변이 생성되기 전에 UI에서 쿼리 계획(query plan)을 말 그대로 직접 확인할 수 있습니다.
- 컨텍스트 예산(Context budgets)은 선택 사항이 아닙니다. 7B 규모의 로컬 모델을 호출하든 API를 통해 Claude를 호출하든, "실제로 얼마나 많은 양을 보낼 것인가"는 사후 고려 사항이 아니라 실제적인 엔지니어링 결정 사항입니다.
- 로컬 우선(Local-first) 방식은 확실한 사용 사례가 있습니다. 이는 단순히 Claude를 피하기 위함이 아니라, 지루한 1차 질문들을 위해 개인적인 코드베이스를 외부 API에 노출하지 않기 위함이며, 무료 로컬 모델이 이미 답할 수 있는 내용에 대해 API 비용을 지불하지 않기 위함입니다.
이 도구/애플리케이션이 적절한 파일을 찾고 이를 이해하는 데 도움을 주고 나면, 저장소 탐색(repo exploration)에 토큰을 소비하는 대신 실제 수정 사항에 대해 Claude에게 질문할 수 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기