코딩 에이전트에게는 단순한 샌드박스가 아닌 증명 환경(Proof Environment)이 필요합니다
요약
코딩 에이전트의 안전한 실행을 위한 샌드박스를 넘어, 작업의 정확성을 검증할 수 있는 '증명 환경(Proof Environment)'의 필요성을 강조합니다. 격리(Isolation)만으로는 에이전트의 결과물이 올바른지 확인할 수 없으므로, 재현 가능한 상태와 증거를 제공하는 런타임이 필수적입니다.
핵심 포인트
- 샌드박스의 격리는 보안을 보장하지만 작업의 정확성을 보장하지 않음
- 증명 환경은 알려진 상태에서 시작하여 동작에 대한 증거를 반환해야 함
- 재현 가능한 상태를 위해 커밋, 의존성, 툴체인 등의 기록이 중요함
- 단순 종료 코드가 아닌 변화에 대한 실질적인 증거가 필요함
샌드박스(Sandbox)는 틀린 답을 포함할 수 있습니다.
당연한 소리처럼 들리겠지만, 많은 에이전트 인프라(Agent infrastructure)는 여전히 격리(Containment)를 최종 목적지로 취급합니다. 에이전트를 일회용 컨테이너(Disposable container)에 넣습니다. 자격 증명(Credentials)을 제한합니다. 작업이 끝나면 환경을 해제합니다. 이제 실행은 "안전"합니다.
더 안전해졌죠, 맞습니다. 하지만 정확해졌을까요? 아니요.
격리(Isolation)는 에이전트가 당신의 노트북을 덮어쓰지 않았거나, 한 작업의 파일 시스템(Filesystem)을 다른 작업으로 유출하지 않았다는 사실은 알려줄 수 있습니다. 하지만 체크아웃(Checkout)이 재현 가능했는지, 테스트(Tests)가 의도한 동작을 측정했는지, 페이지가 올바르게 렌더링(Rendered)되었는지, 또는 최종 디프(Diff)가 요청된 범위 내에 머물렀는지는 알려줄 수 없습니다.
프로덕션(Production) 작업을 위해서는 코딩 에이전트에게 증명 환경(Proof environment)이 필요합니다. 즉, 알려진 상태(Known state)에서 시작하여, 당신이 중요하게 생각하는 동작을 확인하고, 다른 사람이 검사할 수 있는 증거(Evidence)를 반환하는 격리된 런타임(Runtime)입니다.
이 마지막 부분이 없다면, 당신은 그저 격리된 성공 주장만을 갖게 될 뿐입니다.
샌드박스가 실제로 해결하는 것
에이전트의 실행은 무질서하기 때문에 샌드박스는 유용합니다.
현실적인 작업은 종속성(Dependencies)을 설치하고, 서비스를 실행하며, 데이터베이스(Database)를 변경하고, 브라우저(Browser)를 열고, 파일을 생성하고, 포트(Ports)를 점유하며, 백그라운드 프로세스(Background processes)를 남길 수 있습니다. 해당 상태를 공유하는 두 에이전트는 재현하기 어려운 방식으로 서로를 방해할 수 있습니다. 실패한 실험이 다음 시도를 오염시킬 수도 있습니다.
작업별 또는 사용자별 환경은 이러한 무질서를 줄여줍니다. Agent-Sandbox와 같은 프로젝트는 명시적인 라이프사이클 관리(Lifecycle management)와 함께 격리된 코드, 셸(Shell), 브라우저, 컴퓨터 세션을 노출합니다. 포크 가능한(Forkable) 코딩 환경에 대한 논의는 동일한 아이디어를 더 확장합니다. 즉, 파괴적인 테스트(Destructive tests)나 경쟁하는 구현을 시도하기 전에 전체 상태를 복제하는 것입니다.
이는 모든 에이전트에게 동일한 장기 사용 개발 머신을 제공하는 것보다 실질적인 개선입니다.
하지만 격리는 좁은 질문에만 답합니다:
이 작업은 어디에서 실행되었으며, 무엇에 영향을 미칠 수 있었는가?
정확성(Correctness)은 다른 질문입니다:
어떤 동작이 변했으며, 그 변화가 옳다는 주장을 뒷받침하는 증거는 무엇인가?
컨테이너 경계(Container boundary)는 이를 대신 답변해 줄 수 없습니다. 종료 코드(Exit code) 역시 마찬가지입니다.
재현 가능한 상태(reproducible state)로 시작하기
에이전트가 무언가를 증명하기 전에, 환경(environment)은 고유한 정체성(identity)을 가져야 합니다.
샌드박스(sandbox)에 무엇이 들어 있었는지 아무도 모른다면, "샌드박스에서 통과했습니다"라는 말은 설득력이 떨어집니다. 실행 과정을 재현할 수 있도록 충분한 상태(state)를 기록하십시오:
- 리포지토리 커밋(repository commit) 및 더티 트리(dirty-tree) 상태
- 의존성 락파일(dependency lockfile) 및 베이스 이미지(base image)
- 설치된 툴체인(toolchain) 버전
- 픽스처(fixtures), 시드 데이터(seed data), 그리고 서비스 버전
- 비밀 정보(secrets)가 삭제된 관련 환경 입력값
- 뷰포트(viewport), 디바이스 프로필(device profile), 그리고 브라우저 상태
- 정확한 작업 프롬프트(task prompt) 또는 수락 기준(acceptance criteria)
브라우저 및 애플리케이션 상태는 특별한 주의가 필요합니다. git worktree는 소스 파일은 재현할 수 있지만, 로그인된 세션, 데이터가 채워진 데이터베이스, 인메모리 큐(in-memory queue), 또는 절반쯤 완료된 다단계 흐름(multi-step flow)은 캡처하지 못합니다. 이것이 환경 수준의 포크(environment-level forks)가 흥미로운 이유입니다. 두 가지 접근 방식이 단순히 동일한 커밋이 아니라, 동일한 애플리케이션 상태에서 시작할 수 있기 때문입니다.
시작 지점이 다르다면, 에이전트 실행 간의 비교는 대부분 보여주기식(theater)에 불과합니다. 패치(patch) 때문인지, 픽스처(fixture) 때문인지, 아니면 어제 남겨진 프로세스 때문인지 알 수 없게 됩니다.
환경의 정체성은 출력물과 함께 전달되어야 합니다. 검토자(reviewer)가 CI 로그로부터 이를 역공학(reverse-engineer)해야 하는 상황이 발생해서는 안 됩니다.
성공한 명령어가 행동 오라클(behavioral oracle)은 아닙니다
에이전트는 눈에 보이는 체크(visible checks)를 만족시키는 데 매우 능숙합니다. 하지만 그 눈에 보이는 체크가 불완전할 때 문제가 발생합니다.
작업 내용이 "결제 실패 시 폼(form)을 열어둔 상태로 유지하고 인라인 에러(inline error)를 표시하라"라고 가정해 봅시다. 에이전트는 컴포넌트를 변경하고, 모크(mock)를 업데이트하며, 테스트를 다시 작성한 뒤 다음과 같이 보고합니다:
typecheck: passed
unit tests: passed
build: passed
하지만 페이지는 여전히 실패 시 리다이렉트(redirect)될 수 있습니다. 테스트는 이제 새롭고 잘못된 동작을 단언(assert)하고 있을지도 모릅니다. 모크는 실패 분기(failure branch)를 전혀 실행하지 않았을 수도 있습니다. 에이전트는 거짓말을 한 것이 아닙니다. 단지 취약한 계약(weak contract)에 맞춰 최적화했을 뿐입니다.
증명 환경(proof environment)에는 행동 오라클(behavioral oracle), 즉 무엇이 일어나야 하는지에 대한 작업별 정의(task-specific definition)가 필요합니다.
API 변경의 경우, 이는 골든 입력 및 출력(golden inputs and outputs)과 부수 효과(side effects)에 대한 검증이 될 수 있습니다. 마이그레이션(migration)의 경우, 변경 전후의 스키마(schema), 대표 데이터, 그리고 롤백 실행(rollback run)이 될 수 있습니다. 프론트엔드(frontend) 작업의 경우, 명시적인 상호작용 단계, 가시적인 텍스트, 접근성 상태(accessibility state), 반응형 동작(responsive behavior), 콘솔 에러(console errors), 그리고 관련 네트워크 요청(network requests)이 포함될 수 있습니다.
오라클(oracle)이 화려할 필요는 없습니다. 다만 에이전트가 방금 작성한 구현(implementation)으로부터 독립적이어야 합니다.
이것이 불편한 부분입니다. 에이전트가 작업을 구현하는 동안 성공의 기준을 재정의하도록 허용해서는 안 됩니다. 만약 에이전트가 수락 테스트(acceptance test)를 변경한다면, 그 변경 사항은 별도의 정밀 검토(scrutiny)를 거쳐야 합니다. 그렇지 않으면 "모든 테스트 통과"라는 말이 "에이전트가 골대를 깔끔하게 옮겼다"는 의미가 될 수 있습니다.
골든 테스트(Golden tests)도 자체적인 위험을 가지고 있습니다. 골든 테스트는 이미 잘못되어 있던 동작을 그대로 보존할 수 있습니다. 골든 테스트를 작업이 무엇을 달성해야 하는지에 대한 결정의 대체재가 아니라, 이미 알려진 동작에 대한 잠금(lock) 장치로 취급하십시오.
스크린샷은 증거일 뿐, 증명은 아닙니다
프론트엔드 작업은 그 간극을 빠르게 드러냅니다.
빌드(build)는 통과할 수 있지만 모바일에서 페이지가 잘려 보일 수 있습니다. 컴포넌트 테스트(component test)는 통과할 수 있지만 대화 상자(dialog)가 열린 후 포커스(focus)가 사라질 수 있습니다. 스크린샷은 멀쩡해 보일 수 있지만 콘솔에는 에러가 가득하거나 API 요청이 잘못된 페이로드(payload)를 반환할 수 있습니다.
이제 브라우저 도구(browser tooling)를 통해 훨씬 더 풍부한 아티팩트(artifacts)를 수집하는 것이 실용적으로 가능해졌습니다. 예를 들어, Agent-browser는 접근성 스냅샷(accessibility snapshots), 스크린샷(screenshots), 스냅샷 및 픽셀 차이(snapshot and pixel diffs), 트레이스(traces), 콘솔 메시지(console messages), 페이지 에러(page errors), 네트워크 검사(network inspection), 디바이스 에뮬레이션(device emulation), 그리고 저장된 세션 상태(saved session state)를 기록합니다.
이러한 기본 요소(primitives)들이 유용한 이유는 환경이 에이전트의 확신에 찬 한 단락 대신 구조화된 증거(structured evidence)를 반환할 수 있게 해주기 때문입니다.
그럼에도 불구하고, 아티팩트를 수집하는 것이 그것을 판단하는 것과 같지는 않습니다.
스크린샷은 어떤 픽셀이 나타났다는 것을 증명합니다. 그것이 예상된 디자인과 일치한다는 것을 증명하지는 않습니다. 트레이스(trace)는 이벤트가 발생했다는 것을 증명합니다. 올바른 사용자 여정(user journey)이 완료되었다는 것을 증명하지는 않습니다. 깨끗한 콘솔은 조용한 백엔드 데이터 에러(backend data error)에 대해 거의 아무것도 말해주지 않습니다.
증거는 예상되는 결과(expected outcome)와 결합될 때 의미를 갖습니다:
Given (전제 조건): 만료된 카드를 가진 로그인된 사용자
When (실행 조건): 사용자가 결제 양식을 제출할 때
Then (결과 조건):
...
이제 스크린샷, 접근성 스냅샷(accessibility snapshot), 네트워크 로그(network log), 그리고 백엔드 기록(backend record)은 각각 특정한 질문에 답합니다. 증명(proof)이란 산출물(artifact)의 더미 그 자체가 아니라, 계약(contract)과 산출물 사이의 관계입니다.
승리 메시지가 아닌 증거 번들(evidence bundle)을 반환하세요
에이전트의 마지막 메시지는 요약입니다. 그것이 발생한 일에 대한 유일한 기록이 되어서는 안 됩니다.
유용한 증거 번들에는 다음이 포함됩니다:
- 환경 식별 정보(environment identity) 및 시작 리비전(starting revision)
- 정확한 명령(commands), 종료 코드(exit codes), 그리고 실패한 체크 항목
- 최종 소스 디프(source diff)
- 명명된 수락 기준(acceptance criteria)과 연결된 테스트 결과
- 관련 UI 상태에 대한 스크린샷 또는 시각적 디프(visual diffs)
- 브라우저 트레이스(browser trace), 콘솔 출력(console output), 그리고 페이지 에러
- 동작이 경계를 넘나들 때의 네트워크 또는 백엔드 로그
- 변경된 모든 테스트, 모크(mocks), 픽스처(fixtures), 또는 베이스라인(baselines)
- 환경에 대한 정리(cleanup) 또는 보존(retention) 결정
실패 사례를 번들에 포함시키세요. 재시도 시 통과한 불안정한(flaky) 엔드 투 엔드(end-to-end) 체크도 결과의 일부입니다. 서비스 시작에 실패하여 건너뛴 모바일 뷰포트(mobile viewport)도 마찬가지입니다. 불편한 증거를 삭제하는 것은 번들을 다시 마케팅 용도로 전락시킵니다.
또한 번들은 동일한 에이전트에게 해석을 요청하지 않고도 검토 가능해야 합니다. 디프(diff), 로그, 트레이스, 이미지를 산출물(artifacts)로 저장하세요. 체크 항목을 수락 기준(acceptance criteria)에 연결하세요. 환경 리비전(environment revision)을 확인할 수 있게 만드세요.
이것이 인간의 검토를 없애는 것은 아닙니다. 다만 인간의 검토가 신뢰(trust)에 덜 의존하게 만듭니다.
4계층 계약 (The four-layer contract)
전체 설정은 네 가지 계층으로 축약될 수 있습니다.
1. 재현 가능한 상태 (Reproducible state)
소스, 의존성(dependencies), 데이터, 서비스, 브라우저 세션, 그리고 작업 계약(task contract)을 식별합니다. 재실행(rerun)은 그 결과가 의미를 가질 수 있을 만큼 원래 상태에 충분히 가까운 지점에서 시작되어야 합니다.
2. 격리 (Isolation)
작업에 고유한 프로세스(processes), 파일 시스템(filesystem), 포트(ports), 브라우저 상태(browser state)를 부여하십시오. 자격 증명(credentials)과 외부 액세스(external access)의 범위를 별도로 제한하십시오. 샌드박스(sandbox)를 사용한다고 해서 외부로 발생하는 부작용(side effects)이 자동으로 안전해지는 것은 아닙니다.
3. 행동 오라클 (Behavioral oracle)
구현(implementation) 외부에서 기대되는 결과(expected outcomes)를 정의하십시오. 골든 입력 및 출력(golden inputs and outputs), 명시적인 UI 어설션(UI assertions), 불변량(invariants), 또는 작업과 일치하는 도메인 체크(domain checks)를 사용하십시오.
4. 검토 가능한 증거 (Reviewable evidence)
주장(claim)을 평가하는 데 필요한 명령(commands), 디프(diff), 체크(checks), 실패(failures), 스크린샷(screenshots), 트레이스(traces), 로그(logs)를 반환하십시오. 다른 사람이 의견을 달리할 수 있도록 충분한 컨텍스트(context)를 보존하십시오.
어느 한 계층이라도 건너뛰면 결과는 약해집니다.
재현 가능하지만 격리되지 않은 실행(unisolated runs)은 서로를 오염시킵니다. 오라클(oracle) 없는 격리된 실행은 안전하게 수행되지만 증명하는 바는 거의 없습니다. 아티팩트(artifacts) 없는 체크는 검토자가 요약본을 믿도록 강요합니다. 기대되는 결과가 없는 아티팩트는 아무도 해석할 수 없는 스크린샷 폴더가 되어버립니다.
에이전트 하네스(agent harness)를 위한 체크리스트
에이전트가 작성한 변경 사항을 수락하기 전에 다음을 질문하십시오:
- 환경의 시작 상태를 식별하고 재현할 수 있는가?
- 작업이 격리된 파일 시스템, 프로세스, 서비스 및 브라우저 컨텍스트에서 실행되었는가?
- 자격 증명과 외부 부작용(external side effects)의 범위가 명시적으로 제한되었는가?
- 체크(checks)가 일반적인 리포지토리 상태(repository health)가 아닌 요청된 동작을 측정했는가?
- 에이전트가 성공을 정의하는 테스트(test), 모크(mock), 픽스처(fixture), 스냅샷(snapshot) 또는 베이스라인(baseline)을 변경했는가?
- 증거에 실패한 체크와 건너뛴 커버리지(skipped coverage)가 포함되어 있는가?
- 검토자가 에이전트의 설명(narration) 없이도 디프(diff)와 런타임 아티팩트(runtime artifacts)를 조사할 수 있는가?
- 환경에 명시적인 정리(cleanup) 또는 보존(retention) 결과가 있는가?
시작하기 위해 거대한 플랫폼이 필요하지는 않습니다. 실행 시 환경 매니페스트(environment manifest)를 추가하십시오. 수락 기준(acceptance criteria)은 생성된 패치(patch) 외부에 두십시오. UI 변경 사항의 경우 브라우저 트레이스(browser traces)를 저장하십시오. 변경된 테스트를 일급 검토 항목(first-class review items)으로 취급하십시오. 증거 번들(evidence bundle)을 풀 리퀘스트(pull request)에 첨부하십시오.
그러고 나서 더 나은 질문을 던지십시오.
에이전트가 안전하게 실행되었는지를 묻지 마십시오.
에이전트가 무엇을 증명했는지 다른 사람이 검증할 수 있는지를 물으십시오.
참고 자료 (Source notes)
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기