더 이상 코딩 에이전트에 프롬프트를 한 번씩 입력하는 방식으로 작업하지 마세요. 대신 에이전트에 프롬프트를 계속 공급하는 루프를 설계해야 합니다. AI 코딩 에이전트로 실질적인 생산성을 얻는 팀은 에이전트를 대화 상대가 아니라, 검증 가능한 루프 안에서 실행되는 작업자로 다룹니다.
요약 (TL;DR)
코딩 에이전트 루프는 다음 흐름을 반복하는 제어 구조입니다.
- 에이전트가 변경 사항을 생성한다.
- 코드를 실행한다.
- 테스트, 스키마, 계약 같은 검증 게이트를 통과하는지 확인한다.
- 실패 결과를 다시 에이전트에 전달한다.
- 통과하거나 반복 한계에 도달할 때까지 반복한다.
핵심은 에이전트가 아니라 검증 게이트입니다. 모호한 피드백은 루프를 표류하게 만들고, 결정론적인 피드백은 루프를 수렴시킵니다. API 및 백엔드 작업에서는 자동화된 테스트 스위트와 계약 검사가 그 게이트 역할을 합니다. 그래서 API 테스트는 에이전트 워크플로의 마지막 단계가 아니라 중심이어야 합니다.
프롬프트 입력에서 루프 설계로
대부분의 개발자는 채팅 상자로 AI 코딩을 시작합니다.
이 함수 고쳐줘.
이 에러 해결해줘.
이 엔드포인트 만들어줘.
간단한 함수나 설명에는 충분합니다. 하지만 실제 개발 작업은 보통 한 번에 끝나지 않습니다. 테스트가 실패하고, 스키마가 맞지 않고, 인증 처리가 빠지고, 에지 케이스가 깨집니다.
수동 프롬프트 방식에서는 개발자가 직접 루프가 됩니다.
- 에이전트 출력 읽기
- 코드 실행
- 에러 찾기
- 에러를 다시 붙여넣기
- 다음 프롬프트 작성
문제는 에이전트는 몇 초 만에 코드를 만들지만, 사람은 컨텍스트 전환과 검토에 몇 분을 씁니다. 빠른 시스템 안에서 사람이 병목이 됩니다.
루프 설계는 이 구조를 뒤집습니다.
에이전트가 코드 작성
→ 스크립트가 실행
→ 테스트 결과 캡처
→ 실패 결과를 다음 프롬프트로 전달
→ 다시 실행
사람은 내부 반복에 끼어들지 않습니다. 작업을 정의하고, 결과를 승인하고, 실패가 반복될 때 중단시키는 역할만 합니다. Anthropic의 효과적인 에이전트 구축 글도 같은 방향을 강조합니다. 성과는 더 똑똑한 단일 프롬프트가 아니라, 모델 주변에 연결한 환경과 피드백 구조에서 나옵니다.
질문을 바꿔야 합니다.
에이전트에게 뭐라고 말할까?
가 아니라,
어떤 루프가 에이전트에게 올바른 피드백을 계속 제공할까?
입니다.
코딩 에이전트 루프의 구성 요소
실제로 필요한 구성은 단순합니다.
-
작업 사양
- 완료 조건을 명확히 적습니다.
- 예: “POST /orders는 생성된 주문을 201로 반환하고, 응답 본문은 스키마를 만족해야 하며, 필수 필드가 누락되면 422를 반환해야 한다.”
-
에이전트
- 모델과 도구입니다.
- 파일 읽기, 파일 쓰기, 셸 명령 실행 등이 포함됩니다.
-
실행 단계
- 에이전트가 만든 변경 사항을 실제로 실행합니다.
- 테스트, 빌드, 타입 체크, API 요청 등이 여기에 해당합니다.
-
검증 게이트
- 통과/실패를 결정론적으로 판단합니다.
- 실패 시 구체적인 이유를 제공합니다.
-
종료 조건
- 게이트 통과
- 최대 반복 횟수 도달
- 비용 또는 시간 한계 초과
가장 작은 형태의 루프는 다음과 같습니다.
task = load_spec("orders-endpoint.md")
last_result = None
for attempt in range(MAX_ITERATIONS):
agent.run(task, feedback=last_result) # generate
result = run_verification() # run + check
if result.passed:
break # success
last_result = result.failures # feed failure back
else:
escalate_to_human(last_result)
이게 전체 패턴입니다.
에이전트가 생성하고, 게이트가 판단하고, 실패가 다음 프롬프트가 됩니다. 모든 테스트가 성공하거나 반복 횟수를 소진할 때까지 계속됩니다. 에이전트 하네스 아키텍처를 보면 이 구조를 더 큰 워크플로 안에서 어떻게 배치하는지 이해할 수 있습니다.
원샷 프롬프트가 실패하는 이유
단일 프롬프트는 두 가지를 가정합니다.
- 모델이 처음부터 올바른 코드를 작성한다.
- 잘못된 부분은 사람이 잡아낸다.
실제 개발에서는 둘 다 자주 깨집니다.
모델은 그럴듯한 코드를 잘 생성합니다. 하지만 그 코드가 실제로 올바른지 판단하는 데는 약합니다. 예를 들어 다음과 같은 엔드포인트를 만들 수 있습니다.
- 컴파일은 됨
- 기본 요청은 성공함
- 하지만 필수 필드 누락 시 500을 반환함
- 응답 타입이 OpenAPI 스키마와 다름
- 인증 없는 요청을 허용함
채팅 화면에서는 “완료했습니다”라고 말할 수 있지만, 실제 서비스에서는 버그입니다.
루프는 모델의 자기 평가를 믿지 않습니다.
에이전트: 완료했습니다.
게이트: 테스트 실패. customer_id 누락 시 422가 아니라 500이 반환됨.
이제 에이전트의 자신감은 중요하지 않습니다. 중요한 것은 테스트 결과, 스키마 불일치, 계약 위반 같은 신호입니다.
또 하나의 장점은 병렬화입니다. 수동 프롬프트 방식에서는 개발자가 지켜볼 수 있는 만큼만 처리량이 나옵니다. 루프 방식에서는 여러 에이전트가 각자의 게이트를 기준으로 동시에 작업할 수 있습니다. 동적, 병렬 에이전트 워크플로의 핵심도 여기에 있습니다. 더 빨리 타이핑해서 확장하는 것이 아니라, 검증 가능한 루프를 추가해서 확장합니다.
검증 게이트가 루프의 핵심입니다
대부분의 실패한 에이전트 워크플로는 모델이 약해서 실패하지 않습니다. 피드백 신호가 약해서 실패합니다.
좋지 않은 피드백은 이런 형태입니다.
뭔가 이상해. 다시 확인해줘.
좋은 피드백은 이런 형태입니다.
test_create_order_without_customer_id failed
Expected:
HTTP 422
Actual:
HTTP 500
Error:
KeyError: customer_id
app/orders.py:42
두 번째 피드백은 다음 반복을 바로 이끕니다. 에이전트는 추측하지 않고 정확한 실패 지점을 수정할 수 있습니다.
좋은 검증 게이트의 조건은 다음과 같습니다.
-
이진적이어야 합니다
- 통과 또는 실패가 명확해야 합니다.
-
재현 가능해야 합니다
- 같은 입력에 대해 같은 결과가 나와야 합니다.
-
실패 이유가 구체적이어야 합니다
- 테스트 이름, 예상값, 실제값, diff, 라인 번호, 에러 코드가 포함되어야 합니다.
-
에이전트가 마음대로 수정할 수 없어야 합니다
- 에이전트가 테스트를 바꿔서 통과하게 만들 수 있다면 게이트가 아닙니다.
-
빠르게 실행되어야 합니다
- 내부 루프에 20분짜리 테스트 스위트를 넣으면 반복 속도가 무너집니다.
대부분의 성숙한 코드베이스에는 이미 게이트가 있습니다.
- 단위 테스트
- 타입 검사
- 린터
- 컴파일러
- JSON 스키마 검증
- 계약 테스트
- API 테스트
이들은 모두 “무엇이 틀렸는지”를 기계적으로 알려주는 오라클입니다. 에이전트 루프에 새 도구를 만들기보다, 이미 신뢰하는 게이트에 루프를 연결하세요. 테스트 기반이 약하다면 자동화된 테스트의 실제 모습을 먼저 정리하는 것이 좋습니다.
API 및 백엔드 작업에서는 테스트 스위트가 곧 루프입니다
API 엔드포인트를 에이전트가 작성한다고 가정해보겠습니다. 올바르게 동작하는지 판단하는 기준은 모델의 설명이 아닙니다.
기준은 실제 동작입니다.
- 올바른 HTTP 상태 코드
- 스키마와 일치하는 응답 본문
- 인증 및 권한 처리
- 잘못된 입력 거부
- OpenAPI 계약 준수
- 에러 응답 형식 일관성
이 모든 것은 자동화된 테스트로 확인할 수 있습니다. 즉, API 테스트 스위트는 에이전트 루프가 필요로 하는 검증 게이트와 같은 구조를 이미 가지고 있습니다.
엔드포인트 작업용 루프는 이렇게 구성할 수 있습니다.
- 에이전트가 작업 사양과 OpenAPI 정의를 읽는다.
- 에이전트가 엔드포인트를 작성하거나 수정한다.
- 하네스가 실행 중인 서비스에 API 테스트를 실행한다.
- 실패 결과를 구조화해서 수집한다.
- 실패 결과를 에이전트의 다음 입력으로 전달한다.
- 테스트가 성공할 때까지 반복한다.
- 최종 결과를 사람이 검토한다.
예를 들면 실패 피드백은 다음처럼 전달되어야 합니다.
Failure 1:
Endpoint: POST /orders
Case: missing customer_id
Expected status: 422
Actual status: 500
Failure 2:
Endpoint: GET /orders/{id}
Field: total
Expected type: number
Actual type: string
Failure 3:
Spec endpoint /orders/{id} is not implemented.
이런 피드백은 모호한 의견이 아니라 기계가 생성한 정확한 신호입니다. 그래서 루프가 표류하지 않고 수렴합니다.
여기서 스키마 우선 및 계약 테스트가 중요해집니다. OpenAPI 사양은 에이전트와 검증 게이트가 함께 읽는 진실의 원천이 됩니다. 코드와 사양이 어긋나면 문서화 문제가 아니라 즉시 실패하는 게이트가 됩니다.
Apidog는 이 지점에서 유용합니다. Apidog는 API 디자인, 스키마, 모의 서버, 자동화된 테스트를 한곳에서 다루는 올인원 API 플랫폼입니다. 따라서 사양과 게이트를 같은 작업 공간에서 유지할 수 있습니다.
실제 루프에서는 다음처럼 활용할 수 있습니다.
- OpenAPI 기반으로 API 계약 관리
- 테스트 시나리오를 검증 게이트로 사용
- 응답 스키마 검증 결과를 에이전트 피드백으로 전달
- 모의 서버로 아직 구현되지 않은 의존성 대체
- 에이전트가 안정적인 테스트 대상에 대해 반복 실행
팀이 에이전트에게 엔드포인트 호출과 검사를 맡기고 싶다면 Apidog AI 에이전트 디버거 같은 접근도 사용할 수 있습니다. 수동 테스트 러너를 직접 만드는 대신 시각적으로 게이트를 구성하고 싶다면 Apidog를 다운로드해 테스트 흐름을 먼저 정리하세요.
최소한의 자체 수정 API 루프 만들기
복잡한 프레임워크부터 시작할 필요는 없습니다. 필요한 것은 세 가지입니다.
- 명확한 사양
- 실패 시 0이 아닌 종료 코드를 반환하는 테스트 명령
- 에이전트와 테스트를 연결하는 글루 코드
1단계: 사양을 게이트 기준으로 작성하기
작업 사양은 “구현해줘”가 아니라 검증 가능한 조건이어야 합니다.
## Task: POST /orders 구현
요구사항:
- 유효한 요청이면 201을 반환한다.
- 응답 본문은 OrderResponse 스키마를 만족한다.
- customer_id가 없으면 422를 반환한다.
- items가 빈 배열이면 422를 반환한다.
- 인증 토큰이 없으면 401을 반환한다.
- OpenAPI 문서의 /orders 계약과 일치해야 한다.
에이전트는 이 사양과 OpenAPI 파일을 함께 읽어야 합니다.
2단계: 게이트 명령 정하기
테스트 명령은 통과 시 0, 실패 시 0이 아닌 값을 반환해야 합니다.
예:
# pytest
pytest tests/api/test_orders.py
또는 API 테스트 시나리오를 실행할 수 있습니다.
# the gate, as one command
apidog run ./tests/orders-suite --reporter json > result.json
루프는 어떤 도구를 쓰는지보다 다음 두 가지에 관심이 있습니다.
- 종료 코드
- 실패 출력
3단계: 루프 연결하기
가장 단순한 루프는 다음과 같습니다.
import subprocess
MAX_ITERATIONS = 8
feedback = None
for attempt in range(MAX_ITERATIONS):
run_agent(
task="implement orders API per spec",
feedback=feedback
)
gate = subprocess.run(
[
"apidog",
"run",
"./tests/orders-suite",
"--reporter",
"json",
],
capture_output=True,
text=True,
)
if gate.returncode == 0:
print(f"green on attempt {attempt + 1}")
break
feedback = parse_failures(gate.stdout)
else:
print("8 attempts, still red; escalating to a human")
여기서 중요한 함수는 parse_failures()입니다. 에이전트에게 전체 로그를 던지는 것보다, 실패 원인을 정리해서 전달하는 편이 좋습니다.
def parse_failures(raw_json: str) -> str:
failures = extract_failed_cases(raw_json)
return "\n\n".join(
f"""
Failed case: {case.name}
Endpoint: {case.endpoint}
Expected: {case.expected}
Actual: {case.actual}
Message: {case.message}
"""
for case in failures
)
4단계: 게이트 보호하기
에이전트가 테스트와 사양을 수정할 수 있으면 루프가 왜곡됩니다.
피해야 할 구조:
에이전트가 코드 수정
→ 테스트 실패
→ 에이전트가 테스트를 느슨하게 수정
→ 테스트 통과
테스트 파일과 OpenAPI 사양은 에이전트가 편집할 수 없는 영역으로 두세요. 에이전트는 사양을 만족해야지, 사양을 바꾸면 안 됩니다.
5단계: 반복과 비용 제한하기
항상 제한을 두세요.
MAX_ITERATIONS = 8
MAX_SECONDS = 600
MAX_COST_USD = 5
수렴하지 않는 루프는 빠르게 비용을 태웁니다. 반복 로그를 남기고, 어떤 실패가 계속 반복되는지 추적하세요. 토큰 사용량이 문제라면 에이전트 토큰 비용 절감 전략도 함께 적용할 수 있습니다.
좋은 루프를 설계할 때 피해야 할 실수
1. 에이전트가 스스로 평가하게 만들기
나쁜 게이트:
완료했어?
좋은 게이트:
pytest 통과 여부
OpenAPI 스키마 검증 결과
계약 테스트 결과
게이트는 에이전트 외부에 있어야 합니다.
2. 테스트 커버리지가 너무 얕은 경우
테스트가 세 개뿐이면 에이전트는 세 개만 만족시킵니다. 루프의 품질은 게이트 커버리지에 의해 제한됩니다.
얕은 테스트는 얕은 결과를 만듭니다.
3. 종료 조건이 없는 경우
무한 반복은 워크플로가 아닙니다. 폭주입니다.
항상 다음 조건을 설정하세요.
- 최대 반복 횟수
- 최대 실행 시간
- 최대 비용
- 실패 시 인간에게 에스컬레이션하는 조건
4. 내부 루프에 너무 느린 게이트를 사용하는 경우
15분짜리 통합 테스트는 병합 전 검증에는 좋지만, 에이전트 내부 루프에는 느립니다.
권장 구조:
- 내부 루프: 빠른 API 테스트, 타입 체크, 핵심 계약 테스트
- 외부 루프: 전체 통합 테스트, E2E, 장시간 검증
5. 사양을 변경 가능하게 두는 경우
OpenAPI 사양은 계약입니다. 에이전트가 버그 있는 구현에 맞춰 사양을 수정하면 계약 테스트는 잘못된 이유로 성공합니다.
사양은 보호해야 합니다.
6. 작업 단위를 너무 크게 잡는 경우
나쁜 작업:
전체 주문 서비스를 만들어줘.
좋은 작업:
POST /orders 엔드포인트를 사양에 맞게 구현해줘.
엔드포인트 단위, 기능 단위, 실패 케이스 단위로 쪼개세요. 작은 루프는 수렴합니다. 큰 루프는 자주 표류합니다.
이 원칙은 Claude Code, Cursor, Codex, 직접 만든 에이전트 모두에 적용됩니다. 도구 연결 패턴과 실패 모드는 에이전트 워크플로 도구 연결에서 다룬 내용과도 같습니다.
앞으로의 방향
“프롬프트 입력을 멈추고 루프를 시작하라”는 말은 단순한 팁이 아닙니다. AI 코딩에서 중요한 기술이 바뀌고 있다는 신호입니다.
앞으로 더 중요한 역량은 프롬프트 문장 작성이 아니라 다음을 설계하는 능력입니다.
- 명확한 작업 사양
- 결정론적 검증 게이트
- 빠른 테스트 루프
- 보호된 계약 문서
- 반복 종료 조건
- 에이전트가 접근할 수 있는 파일과 없는 파일의 경계
이것은 프롬프트 엔지니어링보다 시스템 설계에 가깝습니다. 이미 테스트, 계약, CI를 중심으로 생각하는 개발자에게 유리한 방식입니다.
자동화된 테스트의 가치도 달라집니다. 과거에는 테스트가 회귀를 막는 보험에 가까웠습니다. 에이전트 워크플로에서는 테스트가 생성기를 올바른 결과로 이끄는 조향 장치가 됩니다.
강력한 자동화된 테스트 커버리지와 깔끔한 계약을 가진 팀은 에이전트를 바로 연결할 수 있습니다. 그렇지 않은 팀은 빠르게 생성되지만 검증되지 않은 코드를 더 많이 얻게 됩니다.
핵심 요점
코딩 에이전트를 더 잘 쓰는 방법은 더 긴 프롬프트를 쓰는 것이 아닙니다. 에이전트에 올바른 피드백을 계속 제공하는 루프를 만드는 것입니다.
에이전트는 빠른 생성기입니다. 하지만 자신이 만든 코드가 올바른지 판단하는 신뢰할 수 있는 감각은 없습니다. 그 감각은 테스트, 스키마, 계약 같은 결정론적 게이트가 제공합니다.
API를 구축한다면 이미 게이트를 가지고 있습니다.
- 테스트 스위트
- OpenAPI 스키마
- 계약 테스트
- 응답 검증
- 인증 및 에러 케이스 테스트
작게 시작하세요.
- 하나의 엔드포인트를 고릅니다.
- 엄격한 사양을 작성합니다.
- 빠른 API 테스트 스위트를 연결합니다.
- 에이전트가 테스트와 사양을 수정하지 못하게 합니다.
- 반복 횟수를 제한합니다.
- 실패 결과를 다음 프롬프트로 전달합니다.
- 테스트가 성공할 때까지 루프를 실행합니다.
게이트가 시각적이고, 스키마를 인식하며, 팀 전체에서 공유 가능해야 한다면 Apidog를 사용할 수 있습니다. Apidog는 디자인, 모의 서버, 자동화된 테스트를 하나의 작업 공간에서 제공하므로 테스트가 에이전트를 이끄는 루프를 더 쉽게 만들 수 있습니다. 다운로드해서 API 테스트를 에이전트 워크플로의 중심에 두세요.

Top comments (0)