리더보드 1위 에이전트를 골랐다. 그리고 실제 레포에 붙였더니 조용히 망했다. dev.to에 올라온 한 테크 리드의 고백이다. 드라마틱한 폭발은 없었다. 함수 하나를 리네임했는데 열어보지도 않은 파일 세 개가 깨졌다. 테스트는 통과했다. 레포는 망가져 있었다. 이 이야기가 불편하게 익숙하다면, 이 글이 당신 팀을 위한 것이다.
벤치마크가 우리 팀에게 거짓말하는 이유
벤치마크 점수가 가짜라서가 아니다. 그냥 다른 코드를 측정한 숫자다. 구조적으로 네 가지 간극이 있다.
첫째, 모델은 벤치마크 정답을 이미 학습했을 가능성이 높다. 공개 벤치마크의 문제들은 오래됐고, 모델은 그 정답을 학습 데이터로 흡수했을 수 있다. 문제 해결 능력이 아니라 암기를 측정하는 셈이다.
둘째, 벤치마크의 실행 환경은 현실과 다르다. 깨끗한 레포, 명확한 이슈 하나, 테스트 커맨드 하나. 실제 팀원이 에이전트에게 주는 건 반쯤 열린 에디터, 지저분한 브랜치, 슬랙 스레드, 그리고 리뷰어 코멘트다.
셋째, 우리 코드베이스는 우리만의 관습이 있다. 내부 라이브러리, 래퍼, 테스트 스타일, 금지된 임포트. 어떤 벤치마크도 그걸 모른다. 에이전트는 교과서적으로 완벽한 코드를 쓰고, 리뷰어는 첫눈에 거절한다.
넷째, 통과 기준 자체가 다르다. 벤치마크는 깨진 테스트가 다시 통과하면 합격이다. 우리 팀은 그게 기본이고, 관련 없는 테스트를 건드리지 않았는지, 파일 전체를 리포맷하지 않았는지, 불필요한 임포트를 추가하지 않았는지, 리뷰할 수 있을 만큼 작은지를 모두 본다.
리더보드는 후보를 좁히는 스니프 테스트로만 쓸 것. 실제 의사결정 도구로는 쓰지 말 것.
평가 데이터는 이미 우리 깃 히스토리에 있다
가장 좋은 평가 데이터셋은 외부에서 구할 필요가 없다. 최근 머지된 PR 50개가 벤치마크가 흉내 낼 수 없는 모든 것을 담고 있다. 실제 의도, 리뷰어 코멘트, 통과한 테스트 스위트, 검증된 최종 diff.
방법은 단순하다. 버전 범프나 자동 생성 파일을 제외한 실제 작업 PR 50개를 뽑고, 각 PR의 시작 커밋과 이슈 텍스트를 기록한다. 레포를 그 시작 시점으로 롤백하고 에이전트에게 이슈를 넘겨 샌드박스에서 돌린다. 나온 결과를 실제 머지된 diff와 비교한다.
단, 텍스트 유사도로 점수 매기는 실수는 하지 말 것. 리뷰어가 실제로 통과시켰을 코드인지를 기준으로 봐야 한다. 그리고 매주 최신 PR 하나를 추가하고 가장 오래된 것을 제거해서 평가셋이 현재 팀의 작업 패턴을 계속 반영하게 유지한다.
실전에서 살아남은 5가지 평가 기준
충분한 리플레이를 돌리고 나면 측정할 것들이 명확해진다. 각각은 벤치마크가 절대 포착하지 못하는 것을 잡아낸다.
1. 이 diff가 우리 리뷰를 통과하는가 텍스트 일치가 아니라 동작 기준이다. 아무도 요청하지 않은 파일을 리포맷했는지, 머지된 버전이 통과한 테스트를 깨트렸는지, 같은 결과에 두 배 분량의 diff를 썼는지를 감점 요인으로 본다.
2. 도구를 올바른 순서로 사용했는가 코딩 에이전트는 텍스트 생성기가 아니라 루프다. 파일을 읽고, 수정하고, 테스트를 돌리고, 반응하고, 커밋한다. 파일을 열기 전에 수정했는지, 수정이 의도한 위치에 정확히 반영됐는지, 테스트를 실제로 돌렸는지 아니면 블라인드 커밋했는지, 변경한 것만 커밋했는지를 본다. 열어보지도 않은 파일을 수정하는 건 자신감 있는 추측일 뿐이다.
3. 변경이 닿는 모든 파일을 업데이트했는가 이것이 앞서 언급한 팀을 태운 항목이다. 에이전트가 헬퍼 함수를 리네임하고 다른 파일의 호출 지점을 그대로 남겨두면, 해당 파일의 테스트는 통과하고 레포는 망가진다. 변경된 파일에서 임포트를 따라 외부로 나가며 다운스트림 파일이 여전히 맞게 연결되는지 확인한다.
4. 플랜이 실제 작업까지 살아남았는가 최신 에이전트들은 코드에 손대기 전에 플랜을 작성한다. 그 플랜을 채점할 가치가 있다. 플랜이 실제 요청과 일치했는가, 최종 diff가 여전히 플랜과 일치하는가. 에이전트는 중간에 표류하며 테스트가 통과하는 동안 조용히 원래 요청을 배반한다. 이 항목이 어떤 에이전트를 리뷰어들이 신뢰하는지를 예측하는 가장 강력한 지표였다고 해당 사례는 밝히고 있다.
5. 나쁜 아이디어를 포기할 줄 아는가 이것이 가장 중요한 항목이 됐다. 테스트가 실패하면 훈련된 에이전트는 되돌리고 다른 접근을 시도한다. 훈련되지 않은 에이전트는 실패 위에 코드를 계속 쌓아올린다. 실패한 테스트 실행당 몇 번의 수정을 하는지, 실제로 되돌리는 행동을 하는지를 트레이스에서 확인한다. 되돌리기 없이 실패당 여러 수정을 반복하는 에이전트는 반드시 리그레션을 배포한다.
처음 세 항목은 정확성을 잡는다. 네 번째는 의도를 잡는다. 다섯 번째는 감독 없이 믿을 수 있는지를 잡는다.
환경을 설계하지 않으면 평가는 무의미하다
에이전트를 고르는 것과 운영하는 것은 다른 문제다. Claude Code 환경 구축 시리즈를 정리한 다른 글은 14개 컴포넌트로 이루어진 에이전트 운영 환경을 소개한다. 메모리, 스킬, 가드레일, 자율 실행, 가시성, 자가 치유. 각각을 따로 보면 독립적인 주제처럼 보이지만, 이 구성 요소들은 실제로 단일 루프를 돌린다.
메모리가 어제까지의 컨텍스트를 넘기고, 그걸 바탕으로 스킬이 선택되고, 자율 실행이 돌아가고, 모니터링이 결과를 관찰한다. 감독 없이 돌기 때문에 가드레일이 필요하고, 무언가 깨지면 자가 치유가 롤백하고, 그 수리 로그가 다시 메모리로 흘러 다음 결정의 기반이 된다.
이 구조에서 네 가지 원칙이 반복해서 등장한다.
자기 보고를 믿지 말고 측정값으로 교차 검증하라. 에이전트가 "완료했습니다"라고 말해도 파일이 실제로 변경됐는지, 커밋이 실제로 이루어졌는지를 독립적으로 확인하는 스크립트가 있어야 한다. AI에게 더 많이 맡길수록, 사람과 스크립트가 검증을 더 강하게 쥐어야 한다.
이상이 있을 때만 말하게 하라. 매일 아침 "정상입니다"를 알려주는 시스템은 3일 안에 아무도 안 읽는다. 침묵을 기본값으로, 이상 징후만 눈에 띄게. 알림 수와 신뢰도는 반비례한다.
자동화가 많아질수록 가드레일을 정밀하게 올려라. 에이전트가 자율적으로 많이 돌수록 조용한 사고가 빠르게 퍼진다. pre-push 시크릿 스캔, 위험한 셸 패턴 탐지는 코딩 에이전트가 생성하는 diff에 동일하게 적용된다. 실제로 API 키 유출과 위험한 eval 패턴이 잡혔다고 해당 글은 밝히고 있다.
환경은 설계하는 것이 아니라 키우는 것이다. 처음부터 완벽한 시스템을 설계하려 하지 말고 쓰면서 추가하고 주기적으로 정리한다. 30개의 launchd 자동화와 85개의 스킬도 하나씩 추가하며 쌓인 결과다.
에이전트 선택 이후에 오는 문제
에이전트를 고르고 환경을 설계해도 아직 한 가지 문제가 남는다. 에이전트가 두 시간 동안 독립적으로 작업한 뒤 모든 이슈가 리뷰 컬럼으로 이동해 있을 때, 코드를 보는 것만으로는 충분하지 않다. '어떻게 여기까지 왔는가'라는 질문이 생긴다. 중간에 방향 수정이 있었는가, 예상하지 못한 티켓이 새로 만들어졌는가, 초기 비전이 수정됐는가 아니면 포기됐는가.
Epiq을 소개한 다른 글은 이를 비전 드리프트라 부른다. 아키텍처 드리프트 너머에 있는 문제—구현이 코드 패턴뿐 아니라 원래 제품 의도에서 멀어지는 현상이다. 깃이 소스 코드의 진화를 추적 가능하게 만든 것처럼, 다음 세대 프로젝트 관리 도구는 의도의 진화를 추적 가능하게 만들어야 한다는 주장이다.
에이전트 하나가 두 시간 작업해도 이 질문이 생겼다면, 에이전트 스무 개가 사흘을 작업하면 어떻게 될지는 자명하다.
팀 리드 관점의 결론
벤치마크 1위 에이전트를 골랐던 그 팀 리드의 결론은 단순하다. 벤더는 모델과 프롬프트를 소유한다. 평가와 결정은 팀 리드가 소유한다. 그리고 팀 리드의 평가만이 우리 코드가 실제로 어떻게 생겼는지를 안다.
AI-First 팀 리빌딩에서 에이전트 선택은 리더보드를 캡처하는 것으로 끝나지 않는다. 우리 깃 히스토리로 평가셋을 만들고, 다섯 가지 기준으로 점수를 매기고, 선택한 에이전트를 감독 없이 돌릴 수 있는 환경을 설계하고, 그 환경이 의도에서 멀어지지 않도록 추적 가능한 구조를 갖추는 것까지가 하나의 사이클이다.
리더보드 1위가 우리 레포에서 조용히 실패할 때, 그 실패를 빠르게 잡는 구조가 없는 팀은 몇 주를 낭비한다. 그 구조를 미리 설계하는 것이 지금 팀 리드의 일이다.