diff는 패치가 무엇을 한다고 주장하는지를 보여 줍니다. 버그가 정말 사라졌는지, if의 새 분기가 한 번이라도 실행되는지, 의존성 업데이트가 클린 설치에서 import를 깨뜨리지 않는지는 보여 주지 않습니다. 리뷰어도 이를 알기에 많은 리뷰가 "테스트가 통과하면 LGTM"으로 끝납니다.
AI가 작성한 패치에서는 이 간극이 더 벌어집니다. 모델은 그럴듯한 코드를 빠르게 만들어 내고, 그럴듯한 코드야말로 지친 리뷰어의 눈을 빠져나가기 쉽습니다. 저렴한 해결책은 누군가 승인하기 전에, 아무것도 해칠 수 없는 곳에서 변경을 실행해 보는 것입니다.
검사: base, head, 테스트
패치가 내놓을 수 있는 가장 설득력 있는 증거는 이전 코드에서는 실패하고 새 코드에서는 통과하는 재현입니다. 샌드박스를 쓰면 이것이 20줄짜리 스크립트가 됩니다. Python 3.12, Node.js 22, git, curl을 갖추고 약 1초 만에 시작되는 Firecracker microVM입니다.
import os
from eqvps import Sandbox
REPO, BASE, HEAD = os.environ["REPO_URL"], os.environ["BASE_SHA"], os.environ["HEAD_SHA"]
def repro(sb, ref):
sb.exec(f"cd /root/app && git checkout -q {ref}", timeout=55)
return sb.exec("cd /root/app && python3 /root/repro.py", timeout=55).exit_code
with Sandbox.create(tariff="standard", ttl=1800) as sb:
sb.exec(f"git clone -q {REPO} /root/app", timeout=55)
sb.exec("cd /root/app && pip install -q -r requirements.txt", timeout=55)
sb.upload("/root/repro.py", open("repro.py").read())
before, after = repro(sb, BASE), repro(sb, HEAD)
tests = sb.exec("cd /root/app && python3 -m pytest -q", background=True).wait()
print(f"repro on base: {before}, on head: {after}; tests: {tests.state}, exit {tests.exit_code}")
repro.py는 버그 리포트에 있는 코드 조각입니다. base에서는 0이 아닌 코드로, head에서는 0으로 종료된다면 패치는 주장한 문제를 실제로 고친 것입니다. 그 한 줄과 테스트 요약을 pull request에 댓글로 남기면 리뷰어는 사실에서 출발할 수 있습니다.
테스트 스위트는 백그라운드 작업으로 실행합니다. 동기 명령 하나는 55초에서 멈추기 때문입니다. 30분의 TTL이 멈춘 실행으로 과금될 수 있는 시간을 제한합니다.
코드를 실행하는 리뷰 에이전트
같은 아이디어는 AI 리뷰어에도 적용됩니다. MCP 서버로 연결된 에이전트는 샌드박스 생성, 명령 실행, 파일 업로드와 다운로드 같은 샌드박스 도구를 갖습니다. "Python 3.8 호환성을 깨뜨릴 수 있습니다"라고 쓰는 대신 브랜치를 체크아웃하고 코드를 실행해 traceback을 인용하거나, 문제없다고 보고합니다.
이런 에이전트에게는 지출 한도와 읽기 전용 토큰을 주고, 묻지 않고 호출할 수 있는 도구를 정해 두세요. MCP 가드레일에 모든 도구가 위험도별로 정리되어 있습니다.
어떤 요금제를 고를까
| 저장소 | 요금제 | 일반적인 한 번 | 대략적인 비용 |
|---|---|---|---|
| 작은 라이브러리, 순수 Python 또는 JS | small (0.5 vCPU, 1 GB) | 2분 | $0.0011 |
| 테스트 스위트가 있는 웹 앱 | standard (1 vCPU, 2 GB) | 5분 | $0.0055 |
| 네이티브 확장, 컴파일이 필요한 의존성 | plus (2 vCPU, 4 GB) | 15분 | $0.033 |
임시 샌드박스는 최소 60초, 초 단위로 과금됩니다. 리뷰어가 며칠에 걸쳐 같은 환경으로 돌아오고 싶다면 persistent로 만드세요. 디스크를 최대 30일 동안 유지하고 시작된 시간마다 과금되므로, 이틀 리뷰용으로 유지한 standard 샌드박스는 약 $3.17입니다. pull request가 병합되면 삭제하세요.
알아 둘 만한 제한
- 계정당 동시에 명령 2개. 차례로 진행되는 리뷰에는 충분합니다. pull request 수십 개를 한꺼번에 검사하면 대기열에 들어갑니다.
- 들어오는 포트 없음. 앱을 브라우저에서 열 수 없습니다. 안에서 실행하고 두 번째 명령에서
curl localhost로 테스트하세요. - 내부에 Docker 없음. 컨테이너를 띄우는 테스트는 VPS의 runner에 맞습니다.
- 외부로 나가는 인터넷은 열려 있음. 그 덕분에
pip install이 동작합니다. 패치 작성자에게 넘기고 싶지 않은 것은 샌드박스에 넣지 마세요.
시작하기
새 계정에는 샌드박스 사용 시간 $1이 제공되며, standard 요금제로 리뷰를 100번 넘게 할 수 있습니다. 요금제는 샌드박스 페이지에, 위에서 쓴 메서드는 SDK 레퍼런스에, 설정 방법은 5분 만에 시작하는 Python SDK에 있습니다.
관련 글: 파이프라인 전체에는 격리된 CI 테스트 실행, 애초에 코드를 작성하는 에이전트에는 AI 에이전트용 샌드박스.
댓글
아직 댓글이 없습니다. 첫 번째가 되세요.