4가지 명령어로 AI 에이전트의 사각지대 점검하기
요약
코딩 에이전트가 코드베이스의 의존성을 정확히 파악하는지 테스트하고 개선하는 4단계 절차를 소개합니다. 'sense' 도구를 활용해 로컬 인덱스를 구축하고 MCP를 통해 에이전트에게 구조적 정보를 제공함으로써 에이전트의 사각지대를 해소하는 방법을 다룹니다.
핵심 포인트
- 에이전트의 답변을 맹신하지 말고 직접 실행 결과와 비교할 것
- 단순 grep 방식의 한계와 구조적 데이터의 필요성 이해
- sense 도구를 이용한 로컬 호출 및 의존성 그래프 구축
- MCP를 통해 에이전트에게 구조적 도구를 연결하는 방법
제 말을 그대로 믿지 마세요. 당신이 아주 잘 알고 있는 저장소(repo)에서 직접 실행해 보고 차이점(diff)을 직접 확인해 보세요. 네 가지 명령어로 약 5분이면, 당신의 코딩 에이전트가 당신의 코드베이스에서 무엇을 볼 수 있고 무엇을 볼 수 없는지 정확히 알게 될 것입니다.
이 선 아래로는 이론은 없습니다. 오직 단계별 절차뿐입니다.
먼저 모델을 선택하세요
가장 잘 아는 앱을 여세요. 신중하게 오후 시간을 할애하여 리팩터링(refactor)해야 할 모델, 즉 앱의 절반이 의존하고 있는 핵심 허브 모델 하나를 선택하세요. Inbox, Order, Account, Booking, MergeRequest 같은 것 말이죠. 금요일에 아무도 건드리고 싶어 하지 않는 것, 왜냐하면 무엇에 의존하고 있는지 아무도 확신할 수 없기 때문입니다.
그것이 당신의 테스트 대상입니다. 네 가지 단계 내내 그 모델을 염두에 두세요.
1단계, 에이전트에게 아무런 준비 없이 질문하기
당신이 평소 사용하는 에이전트(Claude Code, Cursor, Copilot 등 무엇이든)에서, 현재 가지고 있는 도구 외에는 아무것도 사용하지 말고 구조적인 질문을 던지세요:
before I change how the Inbox model is torn down,
find every place in the codebase that depends on it.
Inbox를 당신이 선택한 모델로 바꾸세요. 그다음 에이전트가 무엇을 말하는지가 아니라, 어떻게 대답하는지를 관찰하세요. 에이전트는 토큰을 grep하고, 해당 토큰이 포함된 파일을 열고, 주변 파일 몇 개를 샘플링하며, 머릿속에서 관계를 재구성할 것입니다. 다음과 같은 체인을 보게 될 것입니다:
grep -rin "inbox" app/ lib/ # 수백 개의 결과가 나오지만 대부분 무관함
grep -rinE "belongs_to :inbox|has_many :inboxes" # 명명된 연관 관계(associations), 빠르게 찾아냄
grep -rin "inbox_id" # 이제부터 추측이 시작됨
에이전트가 주는 답변을 저장하세요. 나열된 의존 항목(dependents)의 개수를 세어보세요. 답변은 완전하고, 자신감 있으며, 잘 구조화된 것처럼 보일 것입니다. 바로 그 느낌이 우리가 테스트하려는 대상입니다.
2단계, 맵(map) 설치하기
curl -fsSL https://luuuc.github.io/sense/install.sh | sh
단 하나의 바이너리입니다. 이것은 코드베이스의 호출 및 의존성 그래프(call-and-dependency graph)의 로컬 인덱스를 구축하고, 에디터가 모델에 접속할 때 이미 사용하는 것과 동일한 통로인 MCP를 통해 에이전트에게 제공합니다. 데이터는 기기를 떠나지 않습니다. 코드를 단 한 줄도 수정하지 않습니다.
3단계, 저장소 스캔하기
sense scan
앱의 루트(root)에서 실행합니다. 이는 일회성 빌드(build)입니다. 완료되면 코드베이스의 형태, 파일, 심볼(symbols), 이들 사이의 엣지(edges), 즉 방금 전 에이전트가 grep을 통해 재구성하려 했던 그래프를 출력합니다. 규모가 큰 앱의 경우, 이는 인간이 머릿속에 담을 수 없는 수치이며, 이것이 바로 콜드 런(cold run)이 놓친 근본적인 이유입니다.
4단계, 에이전트를 연결하고 다시 질문하기
sense setup
이 명령은 구조적 도구들을 에이전트에 연결하여, 에이전트가 스스로 이를 사용하도록 만듭니다. (이 마지막 부분이 중요합니다. 지도를 한 번도 호출하지 않는 에이전트는 지도가 아예 없었던 것과 다름없는 점수를 받습니다.)
이제 1단계에서 했던 것과 동일한 질문을 다시 던지세요. 이번에 에이전트는 수백 번의 grep 대신 단 한 번의 구조적 호출(structural call)을 수행합니다. 다음과 같은 결과가 나타납니다:
> sense_blast Inbox
Inbox (app/models/inbox.rb)
110 symbols in blast radius
...
에이전트는 단 한 번에 해결된 종속 집합(resolved dependent set)을 받아오며, 파일을 찾아 헤매는 대신 각 파일을 읽고 고정(pinning)하는 데 예산(budget)을 사용합니다.
이제 두 답변을 비교(diff)하기
1단계의 콜드 감사(cold audit) 결과와 매핑된 결과를 나란히 놓아보세요. 그 둘 사이의 간극이 바로 정답입니다.
그 간극은 명백한 연관 관계가 아닐 것입니다. 에이전트는 콜드 상태에서도 명명된(named) 연관 관계들은 grep으로 찾아냈기 때문입니다. 대신, 컨서언트(concern), 서비스(service), 3단계 호출 깊이에서 ID로 모델을 로드하는 워커(worker), 또는 설정 문자열 레지스트리(config-string registry)를 통해 모델에 측면으로 접근하는 종속 항목들이 나타날 것입니다. 즉, 검색할 수 있는 공유 토큰이 없는 항목들입니다. 이 실험을 수행한 벤치마크에서, 잘 구축된 하나의 Rails 앱을 대상으로 테스트했을 때 프런티어 에이전트(frontier agent)는 콜드 상태에서는 11개 중 2개만을 찾아냈으나, 매핑(map)을 사용했을 때는 11개 모두를 찾아냈습니다. 여러분의 수치는 여러분만의 결과로 나타날 것이며, 그 형태는 익숙할 것입니다.
여러분의 비교 결과에서 주목해야 할 두 가지 사항은 다음과 같습니다:
→ 콜드 에이전트는 거의 확실히 아무것도 '발명'하지 않았습니다. 나열된 모든 것은 실제 존재하는 것이었습니다. 에이전트의 실패는 발명이 아니라 누락(omission)입니다. 출력 결과 어디에도 에이전트가 조기에 중단되었다는 경고는 나타나지 않습니다.
→ 만약 당신의 저장소(repo)가 작고 한곳에 모여 있다면(colocated), 차이(diff)는 아주 작거나 없을 수도 있습니다. 그것은 실험의 실패가 아닙니다. 그것은 실제적이고 신뢰할 수 있는 답변입니다. 즉, 당신의 에이전트가 이미 전체 구조를 파악하고 있으므로 더 이상 의구심을 가질 필요가 없다는 뜻입니다. 격차는 규모가 큰 애플리케이션에서 발생하며, 바로 그 지점이 당신이 결코 간과해서는 안 되는 곳입니다.
당신이 방금 증명한 것
지도가 모델을 더 똑똑하게 만든 것이 아닙니다. 지도는 단일 파일 어디에도 존재하지 않았던 것, 즉 파일들 사이의 경계(edges)를 모델이 읽을 수 있도록 제공했을 뿐입니다. 그리고 이 방식은 모델이 업그레이드되어도 계속 유지될 것입니다. 왜냐하면 이 지도는 (어떤 모델도 암기하지 못한) 이 커밋 시점의 당신의 코드를 기반으로 구축되었고, 코드가 변경됨에 따라 다시 인덱싱(re-indexing)되며, 당신이 지정하는 어떤 에이전트에게든 서비스를 제공하기 때문입니다. 이것은 오늘날의 모델에 거는 도박이 아닙니다. 어떤 모델을 사용하든 에이전트에게 결여되어 있었던 구조를 제공하는 것입니다.
당신이 방금 실행한 차이(diff)는 에이전트가 그동안 조용히 추측해 왔던 코드베이스의 일부입니다. 이제 당신은 그 수치를 확인했습니다.
이 작업의 근간이 되는 벤치마크, 방법론, 그리고 13개의 실제 저장소에 대한 원시 데이터(raw data).
공개 사항: 저는 지도(Sense)를 만듭니다. 모든 것이 공개되어 있으니 저를 믿는 대신 직접 확인해 보십시오. 하지만 여기서 유일하게 중요한 확인은 당신이 방금 당신의 코드에 직접 실행해 본 결과입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기