본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 24. 20:47

결과 보고서가 아닌 작업 내용을 검증하라: 코딩 에이전트의 성공 주장은 단지 주장일 뿐이다

요약

코딩 에이전트의 성공 보고서가 실제 작업 결과와 다를 수 있음을 경고하며, 에이전트의 자기 보고 대신 결정론적 검증기를 통한 직접적인 작업 검증의 중요성을 강조합니다.

핵심 포인트

  • 에이전트의 성공 보고서는 실제 사실(ground truth)이 아닌 생성된 출력물일 뿐임
  • 캐시된 결과, 잘못된 타겟, 불완전한 변경 사항 등 보고서의 허구 사례 제시
  • 결과물을 생성하는 것보다 검증하는 것이 비용 효율적이라는 비대칭성 활용 필요
  • 에이전트의 작업 결과물(artifact)과 보고서를 분리하여 검증해야 함

서브 에이전트(sub-agent)의 성공 보고서는 생성된 출력물일 뿐, 실제 사실(ground truth)이 아닙니다. 직접 작업을 검증하고, 잘못된 전제를 거부하는 에이전트에게 보상을 주십시오.

이번 봄의 한 세션에서, 나는 워크스페이스 전반에 걸친 이름 변경(rename) 작업을 몇 명의 서브 에이전트에게 나누어 할당했습니다. 에이전트들을 하나씩 차례로 투입했고, 다음 에이전트에게 보내기 전에 각 커밋(commit)을 직접 검증했습니다. 그 하나의 습관 덕분에 단 한 번의 오후 동안 세 건의 자신만만한 오보를 잡아낼 수 있었습니다.

첫 번째는 컴파일(compile)이 되지 않았음에도 통과(pass)되었다고 보고된 경우였습니다. 한 작업 단위가 성공(green)으로 돌아왔는데, 보고서에 인용된 빌드(build) 체크가 0.34초 만에 완료되었습니다. 0.3초라는 시간은 대규모 워크스페이스의 컴파일 시간이 아닙니다. 그것은 이전 컴파일의 캐시(cached)된 잔상일 뿐입니다. 직접 실행한 실제 빌드는 2.4초가 걸렸고 진정으로 통과되었습니다. 하지만 보고서는 코드가 아닌 캐시를 읽고 있었기 때문에 그 사실을 알 방법이 없었습니다.

두 번째는 존재할 수 없는 테스트 결과였습니다. 한 작업 단위가 빌드 타겟(build target)에서 121개의 테스트가 통과했다고 보고했습니다. 하지만 보고서에 기술된 대로 실행했을 때, 해당 타겟은 did not match any packages라는 오류를 내며 종료되었습니다. 타겟을 해결(resolve)하지 못하는 명령어가 121개의 성공적인 테스트를 셀 수는 없습니다. 숫자는 실제였지만, 그에 부착된 명령어는 허구였습니다. 올바른 방식, 즉 올바른 매니페스트(manifest)를 대상으로 실행했을 때 테스트는 통과되었습니다. 작업 자체는 건전했습니다. 하지만 어떻게 확인되었는지에 대한 설명은 허구였습니다.

세 번째는 완료되었다고 보고된, 절반만 적용된 변경 사항이었습니다. 이름 변경 작업이 컴파일러가 볼 수 있는 모든 표면을 깨끗하게 훑고 거기서 멈췄습니다. 컴파일러가 볼 수 없는 식별자(identifiers)와 주석(comments)은 그대로 남겨둔 채, 작업이 완료되었다고 보고한 것입니다. 이 잔여물은 별도의 체크 과정에서 코드에 여전히 옛 용어가 남아 있다는 점이 발견되면서 드러났습니다.

당시 내가 작성한 노트를 그대로 옮기면 다음과 같습니다:

보고서를 신뢰하는 대신 모든 서브 에이전트의 커밋을 직접 재검증하고 있다. 이번 세션에서만 오래된 캐시로 인한 "통과(pass)", 잘못 표기된 빌드 타겟, 그리고 절반만 적용된 트리(tree)를 잡아냈으며, 모두 손상 없이 복구했다.

여기에 중요한 점, 그리고 회의적인 시각이 놓치고 있는 부분이 있습니다. 세 가지 사례 모두에서 '작업(work)' 자체는 괜찮았습니다. 컴파일(compile)은 통과했고, 테스트(tests)도 통과했으며, 이름 변경(rename) 작업은 단 한 번의 깔끔한 복구 커밋(recovery commit)으로 완료할 수 있었습니다. 신뢰할 수 없었던 산출물(artifact)은 코드가 아니었습니다. 그것은 바로 보고서였습니다.

보고서는 출력물보다 약한 증거이다

저는 이전에 Compiling the Process에서, 높은 처리량(high-throughput)을 가지면서 일관성(low-consistency)이 낮은 생성기를 신뢰할 수 있게 만드는 저렴한 방법은 그 앞에 결정론적 검증기(deterministic verifier)를 배치하여 비대칭성(asymmetry)을 활용하는 것이라고 주장한 바 있습니다. 즉, 올바른 결과물을 생성하는 것보다 출력물을 확인하는 것이 훨씬 더 저렴하다는 점을 이용하는 것입니다. 컴파일러(compiler)가 그 패턴의 한 사례이며, 테스트 스위트(test suite)가 또 다른 사례입니다.

자기 보고(self-report)는 동일한 비대칭성의 잘못된 끝단에 위치합니다. 그것은 생성기가 자신의 출력물을 스스로 서술하는 것입니다. 즉, 작업을 생성한 것과 동일한 프로세스에 의해 생성된 손실이 있는 요약(lossy summary)이며, 그 뒤에 독립적인 신호(independent signal)가 없습니다. 이로 인해 자기 보고는 그것이 설명하는 출력물보다 엄격하게 더 약한 증거가 됩니다. 출력물은 다시 실행(re-run)할 수 있지만, 문장은 다시 실행할 수 없습니다.

이것은 특정 툴체인(toolchain)만의 특이한 현상이 아닙니다. Huang과 동료들은 Large Language Models Cannot Self-Correct Reasoning Yet (ICLR 2024)에서 "LLM은 외부 피드백(external feedback) 없이는 자신의 응답을 스스로 수정하는 데 어려움을 겪으며, 때로는 자기 수정 후에 성능이 오히려 저하되기도 한다"는 사실을 발견했습니다. 대조할 외부 요소 없이 자신의 추론(reasoning)을 스스로 채점하도록 요청받은 모델은 신뢰할 수 있게 개선되지 않으며, 때로는 더 나빠지기도 합니다. Birgitta Böckeler는 테스트에 대해 실무자 관점에서 동일한 논점을 제시합니다: "에이전트가 테스트도 직접 생성했습니다. 그렇다면 저는 테스트에 대한 피드백을 고민해야 할지도 모릅니다." 생성기가 직접 작성한 검증기는 생성기와 독립적이지 않습니다. 자기 보고는 그 극한의 사례입니다. 즉, 별도의 신호 없이 생성기가 스스로를 채점하는 것입니다.

따라서 모든 사람이 이미 코드에 대해 받아들이고 있는 규율은 한 단계 위에서도 똑같이 엄격하게 적용됩니다. 우리는 검증 없이 에이전트가 작성한 코드를 신뢰하지 않습니다. 마찬가지로, 검증 없이 에이전트가 작성한 상태 주장 (status claim) 또한 신뢰해서는 안 됩니다.

주장이 아닌 실제 신호를 검증하라

"보고서를 검증하라"는 말은 고개를 끄덕이기는 쉽지만, 잘못 수행하기도 쉽습니다. 에이전트의 요약을 더 주의 깊게 다시 읽는 것은 검증이 아닙니다. 그것은 동일한 허구를 두 번 읽는 것에 불과합니다. 검증이란 실제 신호 (genuine signal)를 직접 다시 실행하고, 시스템이 실제로 반환하는 내용을 읽는 것을 의미합니다.

오래된 캐시 (stale-cache) 통과 사례는 날카로운 교훈을 줍니다. 결정적인 단서는 보고서의 문구에 있지 않았습니다. 보고서의 문구는 자신 있게 '성공(green)'이라고 말하고 있었습니다. 결정적인 단서는 0.34초라는 실행 시간이었는데, 이는 해당 워크스페이스의 실제 빌드(build)로는 달성할 수 없는 시간이었습니다. 해결책은 실제 컴파일 (compile)을 강제하고, 그 실제 소요 시간과 종료 코드 (exit code)를 읽는 것이었습니다. 잘못 표기된 타겟 (target) 사례도 같은 맥락입니다. 결정적인 단서는 인용된 명령어가 인용된 수치를 만들어낼 수 없다는 점이었고, 따라서 그 수치는 보고서가 명시하지 않은 어딘가에서 왔음이 분명했습니다. 두 사례 모두 해결 방법은 동일하게 지루한 작업이었습니다. 그것에 관한 산문(prose)을 읽는 대신, 실제 타겟을 대상으로 실제 명령어를 실행하고 실제 출력값을 읽는 것이었습니다.

정직하게 짚고 넘어가야 할 점은, 검증기 (verifier) 또한 속을 수 있다는 것입니다. 오래된 캐시 사례에서 저의 도구조차 잠시 저를 오도했습니다. 에디터의 진단 (diagnostics) 기능이 편집 중간의 스냅샷으로부터 유령 오류 (phantom errors)를 띄우고 있었는데, 이는 잘못된 통과를 만들어낸 캐시만큼이나 오래된 상태였습니다. 검증기는 그 검증기가 읽는 신호의 신선도 (freshness)만큼만 신뢰할 수 있습니다. 이에 대한 방어책은 생성기가 우연히 만들어낼 수 없는 것에 기반을 두는 것입니다. 즉, 실제 빌드 시간, 실제 종료 코드, 또는 실제로 실행된 명령어로부터 얻은 실제 테스트 횟수와 같은 것들입니다.

역설적인 미덕: 거절에 보상하라

거짓된 성공을 불신하는 것과 동일한 회의론은 반대 방향으로도 작용해야 합니다. 그렇지 않으면 "에이전트는 항상 틀렸다"라고 가정하는 부정적인 태도로 변질될 수 있습니다. 이것은 신뢰의 문제가 아니라 증거의 문제입니다. 그리고 에이전트가 생성할 수 있는 가장 깔끔한 증거는 때때로 당신이 가장 원하지 않는 보고서일 수 있습니다: "당신의 전제가 틀렸으며, 저는 진행하지 않겠습니다."

이후의 빌드 세션에서, 위임된 6개의 작업 중 2개가 코드가 아닌 거절(refusal)로 돌아왔습니다. 각각의 이유는 라이브 코드베이스(live codebase)가 작업에 명시된 전제와 모순되었기 때문입니다. 한 작업은 수치를 8로 고정해 두었습니다. 에이전트는 현재 코드를 기준으로 이를 계산하여 24임을 확인했고, 틀렸다고 판단되는 수치에 맞춰 구현하는 대신 작업을 중단했습니다. 또 다른 작업은 기존의 강제 검사(enforcement check)가 느슨하다고 가정했습니다. 에이전트는 이를 추적하여 해당 검사가 출시된 날부터 정밀하게 작동해 왔음을 발견했고, 절반만 구축된 변경 사항을 깨끗한 트리(clean tree) 상태로 되돌린 뒤 작업을 설계(design) 단계로 돌려보냈습니다. 두 경우 모두 추측하지 않았습니다. 둘 다 모순을 드러내고 질문했습니다.

이는 무엇을 만들지 결정하는 것과 그것을 만드는 것 사이의 경계를 재설정합니다. 빌드 단계는 단순히 코드가 작성되는 곳이 아닙니다. 계획이 라이브 코드와 처음 만나는 곳이며, 따라서 전제 거짓화(premise-falsification) 체크포인트가 됩니다. 빌드 단계의 가장 가치 있는 출력물은 때때로 커밋(commit)이 아니라 거짓으로 판명된 전제입니다. 일반적인 트리거는 운영자의 회의적인 질문입니다. 한 사례에서 어떤 이름이 계속 신경 쓰여 제가 압박을 가하자, "두 부분 모두 당신 말이 맞습니다 — 확인됨"이라는 답변과 함께 증거가 돌아왔고, 임기응변식으로 처리하는 대신 변경 사항을 설계 단계로 되돌리기로 결정했습니다.

따라서 오케스트레이터(orchestrator)의 역할은 대칭적입니다. 재실행하여 확인하기 전까지는 자신만만한 성공을 불신하고, 정직한 거절을 무시하는 대신 보호하십시오. 이 둘은 동일한 검증자가 동일한 작업, 즉 주장(claim)과 그것이 설명해야 하는 실제 사실(ground truth)을 분리하는 작업을 수행하는 것입니다.

규칙, 그리고 이 규칙이 전파되는 이유

운영 규칙은 간단합니다. 모든 서브 에이전트(sub-agent)의 커밋(commit) 이후에 독립적으로 검증하십시오. 에이전트가 요약한 내용이 아니라, 실제 신호(genuine signal)를 다시 실행하십시오. 검증의 규모는 수행된 작업에 비해 저렴하게 유지되도록 설정하십시오. 이 비대칭성(asymmetry)이 핵심이며, 검증 비용이 작업을 다시 수행하는 비용만큼 커지는 순간 이 체계는 붕괴합니다. DONEPASS를 사실이 아닌, 확인을 기다리는 주장(claims)으로 취급하십시오. 그리고 에이전트가 커밋 대신 허위 전제(falsified premise)를 가지고 돌아온다면, 그것을 시스템이 제대로 작동하고 있는 것으로 간주하십시오.

이 중 그 어떤 것도 특정 스택에 국한된 것이 아닙니다. Anthropic의 _2026 Agentic Coding Trends Report_는 이러한 변화를 직설적으로 규정합니다: "소프트웨어 개발은 코드를 작성하는 것에서 코드를 작성하는 에이전트들을 오케스트레이션(orchestrating)하는 것으로 이동하고 있습니다." 확률적 생성기(probabilistic generator)에 작업을 위임하는 모든 오케스트레이터는 동일한 문제를 물려받게 됩니다. 보고서가 돌아오고, 그 보고서는 생성기의 출력물입니다. 보고서를 지식으로 변환하는 유일한 요소는 보고서를 작성한 당사자가 아닌 검증자(verifier)뿐입니다.

정직한 한계

이것은 "신뢰하되 검증하라(trust, but verify)"는 원칙으로, 이미 격언이 될 만큼 오래된 것입니다. 제가 이 원칙을 새로 주장하는 것은 아닙니다. 여기서 유일하게 새로운 점은 이 원칙이 가리키는 대상이 — 단지 코드뿐만 아니라 — 에이전트의 _상태 주장(status claims)_을 향하고 있다는 점과, 결정론적 신호(deterministic signal)를 바탕으로 한 검증이 가끔 수행하는 감사(audit)가 아니라 모든 커밋 이후에 실행할 수 있을 만큼 충분히 저렴하다는 관찰입니다.

또한 무엇이 실패했는지에 대해 정확히 말하고 싶습니다. 왜냐하면 쉽게 읽다 보면 과잉 해석할 여지가 있기 때문입니다. 위에서 언급된 모든 사례에서 작업의 실체(substance)는 건전했습니다. 모델은 나쁜 작업자도 아니었고 고의로 그런 것도 아니었습니다. 모델은 자신의 출력물에 대해 손실이 있는 요약(lossy summary)을 생성했을 뿐이며, 이는 일관성이 낮은 생성기(low-consistency generator)가 보이는 전형적인 모습입니다. 신뢰할 수 없었던 것은 그것이 설명하는 코드가 아니라, 증거로서의 보고서였습니다. 만약

이 규율은 검증(verification) 비용이 작업 비용보다 저렴할 때만 효력을 발휘합니다. 이는 Gates Earned From Failure에서 언급된 비용 테스트에도 동일하게 적용됩니다. 만약 결과의 재검증(re-validating) 비용이 결과를 생성하는 비용만큼 발생한다면, 비대칭성(asymmetry)은 사라지고 당신은 단순히 작업을 두 번 하는 셈이 됩니다. 이득이 되는 사례는 재실행(re-run)을 위한 빠르고 결정론적인(deterministic) 신호가 있는 경우입니다. 예를 들어 컴파일(compile), 테스트 횟수(test count), 게이트의 종료 코드(exit code) 등이 이에 해당합니다.

그리고 일반적인 범위에 대한 주의 사항을 덧붙이자면: 이것은 단일 모델 제품군(model family)에서 파생된 하위 에이전트(sub-agents)를 포함하며, 수백 번의 개발 세션에 걸쳐 관찰된 약 150,000라인 규모의 단일 솔로 지향 코드베이스(solo-directed codebase)에 대한 내용입니다. 증거(receipts)는 많지만, 약점은 다른 곳에 있습니다. 이는 하나의 코드베이스와 하나의 모델 제품군에 대한 것이며, 실패가 발생하는 빈도와 체크(check)가 이를 잡아내는 빈도를 측정할 수 있는 통제된 연구(controlled study)는 존재하지 않습니다.

주장은 검증이 아니다

이 모든 것을 관통하는 핵심은 이것입니다: 보고서는 하나의 주장(claim)이며, 주장은 주장을 한 본인이 아닌 검증자(verifier)로부터만 신뢰를 얻을 수 있습니다. 이것이 에이전트의 코드에 적용되는 규칙입니다. 에이전트가 자신의 코드에 대해 설명하는 내용에도 동일한 규칙이 적용됩니다. 작업을 재실행하고, 실제 신호(signal)를 읽으십시오. 그리고 확신에 찬 통과(pass)보다 정직한 거부(refusal)를 더 가치 있게 여기십시오.

저는 컨택 센터(Contact Center) 시스템과 AI 지원 엔지니어링의 교차점에 대해 글을 쓰고 있으며, 해당 분야에서 소량의 컨설팅 및 인도(delivery) 작업을 수행하고 있습니다. 저를 LinkedIn에서 찾아보세요.

References

참고 문헌

vasyltretiakov.dev에서 게시됨.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0