피드백 지연 시간은 에이전트의 IQ이다
요약
에이전트의 성능은 피드백 루프의 지연 시간에 따라 결정됩니다. 테스트 실행 속도가 빠를수록 에이전트는 신중한 협업자로 작동하지만, 지연 시간이 길어지면 검증 없이 코드를 작성하는 추측가로 변질됩니다.
핵심 포인트
- 피드백 지연 시간은 에이전트의 작업 충실도와 직결됨
- 빠른 테스트는 에이전트의 TDD 실천을 유도함
- 느린 피드백은 에이전트를 검증 없이 추측하게 만듦
- 지연 시간 감소는 에이전트의 'IQ'를 높이는 핵심 요소
동일한 에이전트와 동일한 프롬프트를 사용했음에도 불구하고, 제가 작업하는 두 개의 코드베이스에서는 현저히 다른 결과물이 나왔습니다. 한 곳은 테스트 스위트 (test suite)가 8초 만에 실행됩니다. 다른 한 곳은 12분이 걸립니다. 8초가 걸리는 프로젝트에서는 에이전트가 신중하고 반복적인 협업자 역할을 수행합니다. 반면 12분이 걸리는 프로젝트에서는 에이전트가 확신에 찬 추측가 (guesser)가 되어버립니다.
처음에는 직관적인 느낌으로 이를 알아차렸습니다. 느린 코드베이스의 에이전트는 한 번에 5개의 파일을 작성한 뒤, 아무것도 엔드 투 엔드 (end to end)로 실행해보지 않은 채 작업이 완료되었다고 선언하곤 했습니다. 빠른 코드베이스의 에이전트는 함수 하나를 작성하고, 테스트를 실행하고, 실패에 반응하며, 이를 수정하고, 다시 테스트를 실행했습니다. 동일한 모델이었고
에이전트의 추측(Speculation)은 그럴듯해 보입니다. 컴파일이 되는 코드를 생성하고, 사용자의 저장소(repository)에서 본 패턴을 따르며, 명칭을 합리적으로 붙입니다. 문제는 '그럴듯함'이 '정확함'과 같지는 않다는 점입니다. 추측하는 에이전트는 추측치를 배포하는 것이고, 반복(iterate)하는 에이전트는 테스트된 정답을 배포하는 것입니다. 차이점(diff)만 봐서는 이 둘을 구분하기 어려울 수 있습니다.
이것은 제가 내면화하는 데 너무 오래 걸렸던 통찰입니다. 느린 피드백은 에이전트를 더 느리게 만드는 것이 아닙니다. 에이전트를 덜 정직하게 만듭니다.
서로 다른 지연 시간(latency)이 실제로 어떻게 느껴지는가
제가 면밀히 관찰한 작업에서의 에이전트 행동을 바탕으로 분류한 대략적인 범주입니다.
1초 미만의 피드백 (린트(lint), 타입 체크(type check), 저장 시 실행되는 작은 단위 테스트(unit test))은 신중한 TDD(테스트 주도 개발) 실천가처럼 작동하는 에이전트를 제공합니다. 수정하고, 확인하고, 수정하고, 확인합니다. 작업의 단위는 단일 변경 사항입니다. 실수는 그것이 발생한 함수를 벗어나기 전에 포착됩니다.
몇 초에서 1분 사이 (빠른 단위 테스트 세트)는 변경 사항을 작은 커밋(commit) 단위로 묶고 그 사이에 테스트 세트를 실행하는 에이전트를 제공합니다. 실수는 파일이나 모듈 내에서 포착됩니다. 에이전트는 빈번하고 눈에 띄게 경로를 수정합니다.
5분에서 10분 사이 (전형적인 통합 테스트 세트(integration suite))는 시작할 때 테스트 세트를 실행하고, 한 덩어리의 변경을 수행한 뒤, 마지막에 한 번 더 실행하며 그 사이에는 행운을 빌며 기다리는 에이전트를 제공합니다. 실수는 경계 지점에서만 포착됩니다. 덩어리 내부의 미묘한 회귀(regression)는 에이전트가 이를 알릴 수 있는 세밀한 피드백을 받지 못했기 때문에 때때로 그냥 지나치기도 합니다.
20분 이상 (느린 CI 루프, 또는 다른 것이 충분히 빠르지 않아 에이전트가 로컬에서만 실행하는 테스트 세트)은 추측하는 에이전트를 만들어냅니다. 에이전트는 전체 세션 동안 테스트 세트를 한두 번 정도만 실행하며, 그 외에는 검증 없이 코드로부터 추론합니다. 실수는 리뷰(review), QA, 또는 프로덕션(production) 단계에서 포착됩니다.
그 임계점(breakpoints)은 정확하지 않습니다. 하지만 그 형태는 실재합니다. 루프(loop)에서 제거하는 지연 시간(latency)의 차수(order of magnitude)만큼, 에이전트에게 돌려주는 충실도(fidelity)의 차수도 커집니다.
이것이 빠른 테스트(fast tests)의 당위성을 어떻게 바꾸는가
빠른 테스트의 당위성은 과거에 다음과 같았습니다. 테스트가 빠르면 개발자들이 더 많이 실행할 것이고, 빠른 피드백은 버그를 더 일찍 잡아낼 것입니다. 느린 테스트는 건너뛰게 되며, 건너뛰는 테스트는 죽은 코드(dead code)가 됩니다. 이 모든 것은 여전히 사실입니다.
하지만 이제 이 방정식에 새로운 용어가 등장했습니다. 당신의 에이전트(agent)가 이제 테스트 스위트(test suite)의 소비자(consumer) 중 하나가 된 것입니다. 에이전트에게 최적화된 테스트 스위트는 개발자에게 최적화된 테스트 스위트와 동일해 보이지만, 그 정도가 훨씬 더 심화됩니다. 기준점은 더 이상 "개발자가 실행할 만큼 충분히 빠른가"가 아닙니다. 기준점은 "에이전트가 의미 있는 변화(meaningful change)가 있을 때마다 실행할 수 있을 만큼 충분히 빠른가"입니다.
그 기준점은 훨씬 낮습니다. 개발자는 2분짜리 스위트를 견딜 수 있을지도 모릅니다. 하지만 에이전트는 2초짜리 스위트를 한 시간 동안 100번이라도 기꺼이 실행할 것입니다. 그 단계에 도달하기 위한 투자들(포트와 어댑터(port-and-adapter) 접점, 데이터베이스가 필요 없는 모든 것에 대한 인메모리 페이크(in-memory fakes), 단위 테스트(unit)와 통합 테스트(integration) 계층 간의 명확한 구분)는 제가 CI 시간을 단축하는 것에 관한 글에서 주장했던 투자들과 동일합니다. 논거는 같지만, 소비자가 다를 뿐이며, 그 보상은 복리로 쌓입니다.
보상을 가져다주는 투자들
실제로 유의미한 변화를 만들어내는 항목들의 짧은 목록입니다.
프로덕션 코드에서의 의존성 역전(Dependency inversion). 모든 외부 경계(데이터베이스, 메일러, HTTP 클라이언트, 큐)는 애플리케이션이 소유한 인터페이스(interface) 뒤에 위치합니다. 테스트 시에는 해당 인터페이스에 인메모리 구현체(in-memory implementation)가 할당됩니다. 테스트 프로세스는 Docker를 부팅하지 않으며, 스키마를 마이그레이션(migrate)하지도, 소켓(socket)을 열지도 않습니다. 테스트 비용은 밀리초(milliseconds) 단위로 떨어집니다.
신뢰를 보장하는 테스트 피라미드 (test pyramid). 저렴하고 수많은 층인 단위 테스트 (Unit tests)는 모든 변경 사항마다 실행됩니다. 인프라가 진정으로 필요한 소수의 통합 테스트 (Integration tests)는 별도로, 더 적은 빈도로 실행됩니다. 이 둘을 혼합하는 것이 바로 10초면 끝날 일을 10분이 걸리게 만드는 테스트 스위트 (test suite)를 만드는 원인입니다.
사소한 실수를 잡아내는 프리커밋 훅 (Pre-commit hooks). 린트 (Lint) 및 타입 (type) 에러는 전체 테스트 실행 후가 아니라 밀리초 (milliseconds) 단위 내에 실패해야 합니다. 에이전트 (agent)가 세미콜론 (semicolon) 하나를 잊었다는 것을 배우기 위해 CI 사이클을 소모해서는 안 됩니다. 그것이 바로 로컬 훅 (local hook)이 존재하는 이유입니다.
테스트 범위 (test scopes)의 깔끔한 분리. 에이전트가 자신이 수정하고 있는 모듈에 대한 테스트만 실행할 수 있을 때, 루프 (loop)의 모든 사이클이 빨라집니다. 에이전트는 자신이 방어할 수 있는 가장 좁은 범위를 선택할 것이며, 결과적으로 더 확신을 가지고 작업을 배포할 것입니다.
테스트 간 공유 상태 (shared state) 없음. 병렬성 (Parallelism)은 당신이 아직 취하지 않은 가장 저렴한 속도 향상 방법입니다. 당신의 모든 코어 (cores)에서 실행될 수 있는 테스트 스위트는 에이전트가 당신의 인내심을 태우지 않고도 반복 (iterate)할 수 있는 스위트입니다.
첫 번째 에이전트 기능을 배포하려는 사람에게 해주고 싶은 말
프롬프트 (prompts)를 튜닝하기 전에, 테스트 스위트의 시간을 측정하세요. 더 많은 규칙을 작성하기 전에, 마지막 변경 사항이 작동했는지 확인하는 데 몇 초가 걸리는지 세어보세요. 대부분의 코드베이스에서 더 나은 에이전트로 가는 가장 빠른 길은 더 큰 모델 (model)이나 더 풍부한 하네스 (harness)가 아닙니다. 그것은 에이전트가 충분히 감당할 수 있을 만큼 짧은 피드백 루프 (feedback loop)입니다.
모델은 당신이 제공하는 것을 바탕으로 최선을 다하고 있습니다. 당신이 모델에게 제공하는 것은, 대부분, 모델이 얼마나 빨리 학습할 수 있게 허용하느냐 하는 것입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기