-
에이전트 루프의 파수꾼, 검증(Verification) — 행동의 결과를 평가하고 멈추는 법IT 2026. 6. 7. 22:00
AI 에이전트가 자율 루프(Loop)를 성공적으로 마치고 멈추려면 반드시 거쳐야 할 단계가 있다. 바로 검증(Verification)이다. 행동 단계에서 로컬 시스템에 가한 변화가 당초 사용자가 요구했던 목표와 성공 조건을 충족했는지 면밀하게 따져보는 과정이다. 검증이 없는 에이전트는 목적지도 확인하지 않고 무작정 달리기만 하는 제어 불능의 열차와 같다.
이 글에서는 에이전트 루프의 마침표이자 신뢰성을 보장하는 마지막 보루인 검증 단계가 어떤 구체적 조치를 수행하며, 무한 루프를 방지하는 정지 조건 설계가 왜 중요한지 살펴본다.
① 검증(Verification) 단계에서 수행하는 일
검증 단계는 이전의 행동(Action) 결과로 나타난 시스템의 최신 물리 상태가 최종 성공 기준을 만족하는지 수학적, 논리적, 혹은 실증적 도구들을 활용해 비교 및 채점하는 작업을 전담한다.
검증 단계의 상세 과업들은 다음과 같다.
- 성공 메트릭 평가 (Success Metric Evaluation): 테스트 통과율, 소스 코드 빌드(Build, 소스 코드를 실행 가능하거나 기계가 이해할 수 있는 바이너리 형태로 변환하는 구문 분석 및 패키징 과정) 결과, 또는 특정한 파일의 생성 여부 등 사전에 명시된 목표 달성 지표를 정량적으로 계산한다.
- 정적 및 동적 무결성 분석: 컴파일러나 타입 검사기, 린터(Linter, 코드 포맷 및 구문 오류 분석 도구) 등을 가동하여 구문 오류(Syntax Error)나 스타일 위반이 없는지 확인한다.
- 탈출 및 정지 시점 판단: 목표 달성이 입증되면 루프를 안전하게 정상 종료한다. 반면 실패했거나 진행이 고착(Stuck)된 상태가 감지되면 루프 횟수 한계(MAX_ATTEMPTS)를 체크해 조기 정지 여부를 판정한다.
- 피드백용 에러 수집: 검증 과정에서 실패가 일어난 경우, 실패의 근본 원인을 담은 traceback(에러 역추적 로그)이나 린트 경고 정보를 모아 다음 관찰(Observation) 단계로 피드백을 전달하기 위해 보존한다.
다이어그램 설명. 행동 단계에서 수집된 로컬 상태 변화를 받아와서 테스트, 빌드, 린터 등을 실행해 성공 여부를 판정한다. 검증에 성공하면 즉시 루프를 안전하게 종료하고 최종 성과를 반환한다. 반면 실패했을 때는 시도 횟수가 제한(MAX_ATTEMPTS)을 넘었는지 확인한 뒤, 넘었다면 사람에게 개입을 요청하고 이내라면 실패 분석 로그를 묶어 다시 관찰 단계로 보낸다.
② 왜 검증을 해야 하는가?
에이전트가 임의로 행동을 마친 뒤 스스로 "문제를 모두 완벽하게 해결했다"고 장담하는 것은 지극히 위험하다. LLM은 환각 상태에 자주 빠지기 때문에, 자신이 고친 코드가 컴파일을 통과하는지 직접 눈으로 검증하는 장치가 필수적이다.
검증 단계가 필요한 이유는 다음과 같다.
- 자가 수정(Self-Correction) 피드백 완성: 행동에 의한 상태 변화가 잘못되었다는 것을 기계적인 컴파일 오류나 테스트 실패를 통해 확실하게 자각하고, 오류를 수정하도록 고쳐 쓰는 동적 학습 루프를 닫아 완성한다.
- 무한 루프 방지 및 안전 예산(Budget) 통제: 목표 달성이 요원할 때 계속해서 동일한 API 비용을 낭비하며 루프를 돌지 않도록 강제로 브레이크를 밟아 정지시키는 안전핀 역할을 제공한다.
- 수행 신뢰도 검증: 사람의 개입 없이도 빌드 0건 에러, 테스트 100% 통과와 같은 엄격하고 통계적인 사실 증거를 확보해 결과의 신뢰도를 확보한다.
③ 앞단계 및 뒷단계와의 연결고리
검증은 행동(Action)이 남긴 물리적 잔재를 수거하여 평가한 뒤, 실패 시 이를 가공해 다음 루프의 관찰(Observation)로 넘기는 브레이크 역할을 수행한다.
이전 단계 (행동) 현재 단계 (검증) 다음 단계 (관찰) "특정 파이썬 유틸리티 파일의 세율 함수 변경 행동을 완료한다." 수정된 코드베이스에서 pytest단위 테스트 도구를 실행한다.실패한 테스트의 에러 줄 번호와 실패 사유 로그를 수집하여 맥락에 보존한다. - 이전 단계(행동)와 연결: 행동 엔진에 의해 코드 수정이나 CLI 명령어 구동이 종료된 시점에, 변경된 저장소의 상태를 이어받아 테스트 커맨드나 린트 스크립트를 즉시 작동시킨다.
- 다음 단계(관찰)와 연결: 만약 검증 시 테스트가 깨졌다면, 그 에러 트레이스(Traceback, 에러 역추적 로그) 정보를 포맷팅하여 관찰 단계로 넘겨준다. 관찰 단계는 이를 번역해 다음 계획을 세울 수 있도록 LLM의 맥락 창을 재구성한다.
④ 실질적으로 어떻게 동작하는가? (사례 중심)
성공 기준이 뚜렷한 정량적 시나리오와, 그렇지 않은 모호한 시나리오에서 검증이 어떻게 영리하게 동작하는지 실제 동작 매커니즘을 알아본다.
1. 컴파일 에러 및 단위 테스트 자동 파싱
행동이 끝나면 검증 엔진은 백그라운드에서 사전에 빌드된 테스트 실행기를 구동한다. 아래는 에이전트가
pytest도구를 호출하고 그 출력을 파싱해 자가 치유를 트리거하는 과정이다.# 테스트 실행 후 에러 메시지를 정밀하게 구조화하는 검증 로직 예시 def verify_test_results(workspace_path): # 테스트 명령어 구동 (Exit Code와 출력 보존) exit_code, stdout, stderr = run_command_in_sandbox("pytest", cwd=workspace_path) if exit_code == 0: return {"status": "success", "message": "모든 단위 테스트 통과"} # 실패한 테스트의 원인 분석 error_summary = [] # 에러 트레이스에서 파일명과 라인 번호를 정규식으로 매칭 pattern = r"FILE: (.*?\.py), LINE: (\d+), ERROR: (.*)" for line in (stdout + stderr).split("\n"): match = re.search(pattern, line) if match: error_summary.append({ "file": match.group(1), "line": int(match.group(2)), "reason": match.group(3) }) return { "status": "failure", "failures": error_summary, "raw_log": stdout[:1000] # 맥락 창 낭비를 방지하기 위한 슬라이싱 요약 }코드 설명. 검증 단계는 테스트 실행 도구를 활용해 빌드 상태를 체크한다. 실패 시에는 긴 로그를 날것 그대로 맥락 창에 밀어 넣지 않고, 실패를 촉발한 핵심 파일명, 줄 번호, 오류 요약만을 발췌하는 요약(Summarize) 가공을 거친다. 이는 ③에서 다룬 맥락의 낭비를 원천적으로 절감하는 효율적인 공학 기법이다.
2. 모호한 정성적 목표에 대한 정책 기반 검증 (Policy-based Verification)
"코드가 읽기 쉽게 리팩터링되었는가?" 또는 "결정 문서 양식에 잘 맞춰 작성되었는가?" 같은 모호한 정성적 목표는 단순한 유닛 테스트 컴파일 결과만으로는 완전한 검증이 곤란하다.
이때는 엄격한 정책 가이드라인을 토대로 한 정적 트리 검사나 LLM 판정(LLM-as-a-judge, 판사로서의 LLM — 생성된 결과를 다른 고성능 AI 모델을 통해 평가 및 채점하는 기법) 모델을 별도로 적용해 정밀하게 채점한다.
// 정성적 규칙 준수 여부를 체크하는 체크리스트 프로토콜 (JSON) { "verification_mode": "policy_check", "policy_document": "docs/adr/0017-line-anchor-doctrine.md", "target_draft": "2026-05-24-04-agent-loop-action.md", "checks": [ { "rule_id": "rule_1", "description": "모든 코드 심볼에 file:line 링크가 형식에 맞게 달렸는가?", "passed": true }, { "rule_id": "rule_2", "description": "설계 결정 기록 식별자가 모두 숨김 처리 되었는가?", "passed": false, "reason": "14번 라인에서 식별자가 그대로 노출됨" }, { "rule_id": "rule_3", "description": "금칙어가 사용되지 않고 자체로 변환되었는가?", "passed": true } ] }코드 설명. 기계적인 테스트를 돌릴 수 없는 정성적/문서적 성격의 결과물에 대해서는, 검사 규칙 체크리스트와 자체 정책 스키마를 대조해 검증을 치른다. 위 사례에서는 규칙 2번을 통과하지 못해 실패 판정이 나며, 실패 사유를 구체적으로 피드백해 에이전트가 다음 관찰 단계에서 특정 노출 부분을 확실하게 타격해 수정하도록 돕는다.
정리하며
검증(Verification)은 에이전트에게 맹목적인 과속을 막아주고 절제된 문제 해결을 가능케 하는 브레이크다. 가속페달(행동)도 중요하지만, 성공 기준을 준엄하게 확인하고 무한 반복을 미연에 방지하는 똑똑한 브레이크가 채워질 때 비로소 우리는 에이전트의 수행 능력을 전적으로 신뢰할 수 있다.
이 글은 생성형 AI의 도움을 받아 작성되었습니다. 원본 자료를 기반으로 AI가 초안을 생성하고, 작성자가 검토·편집하였습니다.
'IT' 카테고리의 다른 글
Claude Code에서 나만의 AI 전문가 만들기 — 서브에이전트 제작 가이드 (0) 2026.06.10 품질과 지식의 정합성 보장, OpenCode의 자율 검증(Verify) 메커니즘 (0) 2026.06.09 안전하고 확실한 구현, 실행(Execute) — permission 가드레일과 터미널 실행 제어 (0) 2026.06.08 OpenCode 로컬 AI 에이전트의 첫걸음, 계획(Plan) — 가설 수립과 마일스톤 설계 (0) 2026.06.08 오픈소스 에이전트 OpenCode는 세상을 어떻게 관찰하는가? — 로컬 에이전트의 관찰 엔진 분석 (0) 2026.06.08 에이전트 루프의 실행력, 행동(Action) — 생각에서 변화로 나아가는 도구 호출 (0) 2026.06.07 에이전트 루프의 나침반, 계획(Planning) — 복잡함을 나눌 때 시작되는 문제 해결 (0) 2026.06.06 에이전트 루프의 첫 단추, 관찰(Observation) — 세상의 상태를 맥락으로 번역하기 (0) 2026.06.06 에이전트의 다섯 가지 본질 — 루프·도구·맥락·정지·신뢰 (0) 2026.06.06 내 코드 위키를 남의 코딩 에이전트가 쓰게 하려면 — SKILL.md 한 장으론 부족하다 (0) 2026.06.05