jacobhan.me

AI 에이전트 · 코드베이스

에이전트가 길을 잃지 않는 코드베이스, 그리고 토큰 비용을 줄이는 법

코딩 에이전트 실패의 상당수는 코드를 잘못 짜서가 아니라, 올바른 위치를 못 찾아서 생긴다. 탐색에 낭비되는 토큰을 코드 수정 쪽으로 되돌리는 방법과, 늘어나는 토큰 청구서를 관리하는 실전 기법을 정리한다.

2026년 7월 2일

사람은 한 코드베이스에서 한 달쯤 일하면 머릿속에 자연스럽게 지도가 그려진다. 어떤 파일이 진입점이고, 결제 로직이 어디 있고, 어떤 유틸리티가 이미 존재하는지 익숙해진다. 코딩 에이전트에게는 그 익숙함이 없다. 에이전트는 매 세션이 사실상 첫 출근이라고 봐야 한다. 사람이 익숙함으로 메우던 탐색 비용을, 에이전트는 매번 처음부터 새로 치른다.

그래서 기준이 사람보다 빡빡하다. 신규 입사자가 일주일이면 적응하는 코드베이스 품질로는 부족하다. 에이전트가 헛다리를 짚지 않으려면 첫 1분 안에 어디로 가야 할지가 분명해야 한다. 현장에서 에이전트를 굴려 보면 흥미로운 패턴이 보인다. 실패의 대부분은 코드 품질 문제가 아니라 탐색·이해 비용 문제라는 것이다. 잘못된 위치에 도달하고, 이미 있는 유틸리티를 못 보고, 진짜 진입점이 무엇인지 몰라서 실패한다. 이건 모델이 더 똑똑해진다고 저절로 풀리는 문제가 아니다.

비유로 이해하기 — 지침과 지형

에이전트에게 주는 행동 지침 파일(예: Claude Code의 CLAUDE.md)이 '헌법'이라면, 코드베이스는 에이전트가 실제로 걸어 다니는 '지형'이다. 헌법을 아무리 잘 써도 지형이 미로면 길을 잃는다. 좋은 지침과 걷기 좋은 지형은 별개의 문제다.

구체적인 예를 들어 보자. "결제 로직을 수정하라"는 과제를 줬다고 하자. 정리되지 않은 저장소에서는 에이전트가 결제 관련 파일 수십 개를 뒤지면서도 진짜 진입점을 못 찾는다. 중복된 코드 중 어느 것이 실제로 쓰이는지 몰라 엉뚱한 쪽을 고치고, 테스트를 돌리니 다른 곳이 깨져 다시 탐색에 들어간다. 이 과정에서 과제에 쓴 토큰의 상당 부분이 탐색에만 소모되고, 정작 코드 수정에 쓰이는 몫은 얼마 되지 않는다. 그 탐색조차 잘못된 지점에 닿는 경우가 많다. 'AI-Ready 코드베이스'란 이 낭비를 코드 수정 쪽으로 되돌려 놓는 작업이다.

두 단계 — 코드 건강, 그다음 지도

AI-Ready 코드베이스를 만드는 일은 두 단계로 나뉜다. 첫째는 코드가 건강한지 보는 단계다. 테스트 커버리지, 데드코드 제거, 컨벤션의 일관성, 코드 스멜 정리 같은 것들이 여기에 해당한다. 둘째는 그 건강한 지형 위에 에이전트를 위한 지도를 얹는 단계다. 진입점, 의존성 그래프, 도메인 용어집, 자주 빠지는 함정을 문서로 정리해 탐색 비용을 한 번 더 떨어뜨린다.

순서가 중요하다. 건강하지 않은 코드 위에 지도를 그리면 그 지도는 거짓말을 한다. 중복되고 죽은 코드를 그대로 둔 채 경로를 안내하면, 에이전트를 잘못된 길로 더 빠르게 데려갈 뿐이다. 코드가 먼저 건강해야, 그 위의 지도가 신뢰할 수 있다.

AI-Ready 코드베이스 만들기 두 단계 코드베이스를 코드 건강(Sanity) 단계와 지도 제작(Cartography) 단계를 거쳐 에이전트의 탐색 비용을 낮춘다. 에이전트가 길을 잃지 않는 코드베이스 만들기 두 단계 — ① 코드 건강 → ② 지도 제작으로 에이전트의 탐색 비용을 낮춘다 코드베이스 ① 코드 건강 Sanity ② 지도 제작 Cartography 탐색 비용 · 테스트 커버리지 · 데드코드 제거 · 컨벤션 일관성 · 코드 스멜 제거 · 진입점(entry point) · 의존성 그래프 · 도메인 용어집 · 함정(gotchas) 순서가 핵심 — 건강하지 않은 코드 위에 그린 지도는 거짓말을 한다
AI-Ready 코드베이스의 두 단계. 코드 건강(Sanity)으로 지형을 정리한 뒤, 지도 제작(Cartography)으로 진입점·의존성·용어집을 얹어 에이전트의 탐색 비용을 낮춘다.

테스트나 컨벤션, 데드코드 제거가 새로운 이야기는 아니다. 다만 에이전트 시대에는 그 가치의 결이 조금 달라진다. 예전에 테스트 커버리지는 사람을 위한 회귀 방지 장치였다. 에이전트에게 테스트는 자기 검증 신호다. 에이전트는 기본적으로 루프를 돌며 스스로 잘못을 교정하는데, 테스트가 잘 깔려 있어야 자기가 무엇을 망가뜨렸는지 알아채고 되돌릴 수 있다. 컨벤션의 일관성은 에이전트가 같은 패턴을 안전하게 일반화해 쓰게 해 준다. 컨벤션이 여러 갈래면 에이전트가 헷갈려 잘못된 패턴을 택할 확률이 올라간다. 데드코드 제거는 애초에 잘못된 길을 갈 수 없게 막고, 나쁜 코드를 따라 쓰지 않게 한다.

핵심

같은 위생 작업이라도 목적이 바뀐다. 테스트는 에이전트의 자기 검증 신호, 컨벤션 일관성은 패턴 일반화의 재료, 데드코드 제거는 잘못된 경로의 사전 차단이 된다.

코드베이스의 AI 준비도를 점수로

지형을 정리하려면 먼저 현재 상태를 측정해야 한다. 코드베이스가 얼마나 AI-Ready한지 100점 만점으로 채점하고, 여러 카테고리로 나눠 점수를 매기는 방식이 유용하다. 내비게이션이 잘 되는지, 컨텍스트 품질은 어떤지, 암묵지가 문서화돼 있는지, 의존성 매핑이 돼 있는지, 검증과 신선도는 어떤지, 그리고 에이전트의 실제 성과는 어떤지까지 나눠 본다. 결과는 정적 분석 도구(린트)와는 다르다. "이 프로젝트에서 에이전트가 어느 카테고리에서 가장 길을 잃는가"를 보여 주는 진단 리포트에 가깝다.

이때 채점 기준(루브릭)은 절대적인 것이 아니라 팀이 정하는 것이다. 필요 없는 카테고리는 빼고, 팀에 중요한 항목은 더한다. 그리고 한 번 돌리고 마는 리포트는 효과가 없다. 주기적으로(예: 정기 실행) 돌리고, 개선 우선순위(ROI, Return on Investment, 투자 대비 효과)를 뽑았으면 그것을 실제 변경으로 옮겨야 한다. 리포트를 백 번 들여다봐도 반영하지 않으면 소용이 없다. 개선안을 병합 요청(PR, Pull Request)으로 만들어 실제로 머지하는 데까지 가야 완성이다.

자산이 쌓이면 청구서가 늘어난다

지침 파일, 문서화된 지식(이른바 세컨드 브레인), 명세, 각종 훅과 스킬이 하나씩 쌓이면 팀의 자산은 늘어난다. 그런데 그만큼 매 세션에 실려 들어가는 컨텍스트도 커진다. 컨텍스트가 커지면 토큰이 늘고, 토큰이 늘면 청구서가 늘어난다. 지침 파일에 수백~수천 줄을 박아 두면, 팀원 한 명이 세션을 열 때마다 그 분량이 매번 컨텍스트에 들어간다. 거기에 세컨드 브레인과 큰 명세 파일까지 한 세션에 얹히면 수십만 토큰은 금세 나온다.

토큰이라는 단위, 그리고 누구의 청구서인가

토큰은 모델이 텍스트를 처리하는 최소 단위다. 영어 단어 하나가 토큰 하나인 것은 아니다. BPE(Byte Pair Encoding, 바이트 쌍 부호화)라는 방식으로 문자열을 덩어리로 묶어 둔 사전에 맞춰 텍스트가 토큰 열로 잘린다. 대략 영어는 한 토큰이 약 네 글자, 즉 0.75단어 정도이고, 한국어는 한 토큰이 1.5~2글자 수준이라 같은 내용이라도 영어보다 대략 두 배가량 토큰을 더 쓴다. 코드는 영어와 비슷한 수준이다. 비용을 극단적으로 최적화하려면 지시를 영어로 쓰는 편이 유리하다는 계산이 여기서 나온다.

또 하나 짚을 것은 '누구의 청구서를 줄이는가'다. 개인이 자기 카드로 결제하면 토큰이 곧 내 돈이라 자연히 보수적으로 쓴다. 반면 팀이나 회사 청구서로 나가면 비용이 잘 체감되지 않아 마음껏 쓰게 된다. 그러다 위에서 토큰 최적화 가이드라인이 내려오는 흐름이 반복된다. 개인 최적화와 조직 최적화는 유인 구조가 다른, 서로 다른 문제다.

가장 큰 레버 — 프롬프트 캐싱

비용을 실제로 크게 깎는 도구를 하나만 꼽으면 프롬프트 캐싱이다. 같은 앞부분(프리픽스)을 반복해서 보내면, 서버가 그 프리픽스를 처리한 결과를 잠시 저장해 둔다. 다음 호출에서 같은 프리픽스가 필요할 때 이를 전체 입력 토큰이 아니라 캐시 읽기로 받아 훨씬 싸게 처리한다.

비유로 이해하기 — 프롬프트 캐싱

매번 같은 서류 뭉치를 처음부터 다시 검토하는 대신, 앞부분의 '검토 결과'를 잠깐 책상에 얹어 두는 것과 같다. 다음 요청 때 그 부분은 다시 읽지 않고 얹어 둔 결과를 재사용한다. 단, 책상은 잠깐만 쓸 수 있어(기본 5분) 오래 두면 치워진다.

가격 구조는 세 가지만 알면 된다. 캐시 읽기는 기본 입력가의 약 10%로, 대략 1/10 값이다. 캐시 쓰기는 기본보다 비싸서, 5분짜리 유효기간(TTL, Time To Live, 유효 시간)이면 약 1.25배, 1시간짜리면 약 2배다. 기본 TTL은 5분이며, 캐시가 읽힐 때마다 그 시점부터 다시 5분이 연장된다. 그래서 작업을 쭉 이어 가면 캐시가 계속 살아 있지만, 잠깐 자리를 비워 5분이 지나면 캐시가 사라진다. 명세 기반의 긴 작업이 의외로 토큰 효율이 좋은 이유다.

캐시 친화적 프롬프트 구조 고정된 프리픽스(시스템 프롬프트·CLAUDE.md·세컨드 브레인)를 캐시 경계 위에 두어 캐시하고, 매번 바뀌는 값은 경계 아래에 둔다. 캐시 친화적 프롬프트 구조 고정된 앞부분은 캐시하고, 매번 바뀌는 값은 경계 아래로 내린다 시스템 프롬프트 CLAUDE.md (에이전트 지침) 세컨드 브레인 (문서·지식) ▼ 캐시 경계 (cache breakpoint) 현재 시간 등 매번 바뀌는 값 유저 메시지 (이번 요청) 캐시 적중 읽기 = 기본가의 1/10 매번 새로 계산 기본 TTL 5분 · 읽을 때마다 갱신 · 프리픽스 중간이 바뀌면 아래가 전부 깨진다
캐시 친화적 프롬프트 구조. 시스템 프롬프트·지침·문서처럼 고정된 앞부분을 캐시 경계 위에 두어 캐시(읽기 1/10 가격)하고, 현재 시간·유저 메시지처럼 매번 바뀌는 값은 경계 아래로 내린다.

실수 하나가 캐시를 통째로 날린다. 만약 프리픽스 앞쪽에 '현재 시간'처럼 매번 바뀌는 값을 두면, 그 지점 이후는 전부 캐시 미스가 되어 매 요청마다 다시 계산된다. 한 줄 때문에 지침과 문서 수만 토큰이 매번 재계산되는 셈이다. 반대로 고정값을 앞으로, 매번 바뀌는 값을 뒤로 배치하면 큰 덩어리를 싼값에 캐시할 수 있다.

캐시를 날리는 대표적 실수

세션 도중에 지침 파일(CLAUDE.md)을 고치면 프리픽스가 바뀌어 캐시가 날아간다. 세션 중간에 모델을 바꾸는 것도 마찬가지다. 모델 식별자도 시스템 프롬프트에 들어가므로, 오퍼스로 쓰다가 소넷으로 갈아타면 앞서 쌓아 둔 캐시가 전부 무효가 된다. 수정과 모델 교체는 세션이 끝난 뒤에 하는 것이 원칙이다.

세션을 잠시 껐다가 한참 뒤에 다시 여는 경우도 비슷하다. 이미 5분 TTL이 지나 캐시가 사라졌기 때문에, 재개 시 그 큰 컨텍스트를 다시 캐시에 써 넣어야 한다. 코딩 에이전트가 이어서 시작할 때 "토큰이 너무 큰데 처음부터 다시 할지, 압축(compact)할지" 물어보는 이유가 여기에 있다.

최적화 기법과 안티패턴

몇 가지 기법은 알아 둘 만하다. 무거운 탐색은 서브 에이전트에 맡긴다. 탐색은 출력 토큰이 크게 늘어 메인 세션의 컨텍스트를 오염시키기 쉬운데, 별도 에이전트로 떼어 내면 메인 컨텍스트를 지킬 수 있다. 이때 서브 에이전트는 저렴한 모델로 돌리는 편이 좋다. 큰 파일은 한 번 읽고 캐시하며, 고정된 프리픽스는 앞쪽에 둔다. 이런 부분은 최근의 코딩 에이전트가 상당 부분 알아서 처리하지만, 원리를 아는 것과 모르는 것은 작업 감각이 다르다. 긴 세션은 압축보다 새 세션을 여는 편이 대개 낫다.

반대로 피해야 할 패턴도 분명하다. 지도나 지침 없이 큰 코드베이스를 통째로 읽어 들이면 세션이 금세 가득 찬다. 이미 캐시된 것과 같은 컨텍스트를 반복해서 주입하면 캐시가 무의미해진다. 설계든 단순 타이핑이든 늘 가장 비싼 모델만 쓰는 것도 낭비다. 끝난 작업의 흔적을 컨텍스트에 계속 남겨 두는 것도 마찬가지다. 다만 절약이 지나쳐 컨텍스트를 과하게 줄이면 오히려 결과 품질이 떨어져 재작업 비용이 늘 수 있으니, 양날의 검이라는 점은 감안해야 한다.

사후 대시보드와 사전 코스트 게이트

비용 관리 장치는 성격이 둘로 나뉜다. 대시보드는 이미 쓴 세션의 비용을 보여 주는 사후 분석이다. 세션 로그를 파싱해 토큰과 캐시 효율, 비용을 집계하고 점수화한다. 캐시 적중률, 출력 밀도(읽기만 많고 산출이 적지 않은지), 같은 파일을 여러 번 읽는 중복 정도, 출력 1천 토큰당 도구 호출 수 같은 지표가 쓰인다. 여기서 캐시 활용도가 특히 큰 비중을 차지한다.

코스트 게이트는 반대로 사전 예방이자 실시간 통제다. 훅(hook)으로 누적 토큰을 추적하다가 임계치를 넘으면 개입한다. 한 세션이 일정 토큰을 넘으면 "이번 세션 비용이 초과됐습니다, 계속하시겠습니까"라고 경고하거나, 200K 토큰을 넘으면 자동 압축을 하도록 지침에 명시할 수 있다. 하나의 PR을 만드는 데 든 누적 세션 비용이 임계를 넘으면 그 PR에 라벨을 붙여 나중에 따로 분석·최적화할 수도 있다. 사후 대시보드와 사전 게이트가 함께 있으면 좋다.

핵심

청구서를 줄이는 가장 빠른 길은 "아끼자"는 구호가 아니다. 캐시 최적화와 비용 통제를 팀 공유 자산(훅·대시보드·플러그인)으로 박아 자동으로 강제하는 것이다. 그러면 한 사람이 아니라 팀 전체, 나아가 조직 전체의 효율이 올라간다.

정리하면, 코드베이스를 먼저 건강하게 만들고 그 위에 에이전트를 위한 지도를 얹어 탐색 비용을 낮춘다. 그다음 캐시를 중심으로 토큰 흐름을 최적화하고, 그 규칙을 개인의 습관이 아니라 팀의 장치로 고정한다. 도구가 알아서 해 주는 부분이 점점 늘고 있지만, 그 원리를 아는 팀과 모르는 팀의 생산성 차이는 시간이 갈수록 벌어진다.