200 OK에 속아 에이전트 트레이싱 구축한 이유
카테고리: IT 최신동향 | 작성자: Tech Reporter | 발행일: 2026-08-05
요약: HTTP 200 성공 신호 뒤에 숨은 LLM 에이전트의 논리적 무한 루프와 토큰 낭비를 잡아내는 Cloudflare Agents 기반 Observability 전환기입니다.
새벽 2시 15분, 회사 PagerDuty 모니터링 채널이 돌연 조용해졌습니다. 인프라 대시보드는 온통 평화로운 초록색이었고, Kubernetes 클러스터의 HTTP 응답 코드는 99.99% 확률로 200 OK를 가리키고 있었습니다. 하지만 제 심장은 정반대로 거세게 뛰기 시작했습니다. OpenAI API 사용량 가스비 알림이 분당 50달러를 돌파하며 상한선을 뚫어버렸기 때문입니다. 백엔드 서버는 에러를 한 번도 뱉지 않았는데, 서비스 모듈 내부의 LLM 자율 에이전트(Autonomous Agent)가 혼자만의 착각에 빠져 무한 툴 호출 루프를 돌고 있었습니다.
트래픽을 수신한 인프라는 정상이었지만, 에이전트의 '생각 과정'은 완전히 붕괴해 있었습니다. 기존 APM 도구나 Datadog, Prometheus 대시보드에서는 HTTP 통신이 성공했으니 아무런 경고도 울리지 않았던 겁니다. HTTP 200 상태 코드가 엔지니어에게 제공하는 가장 거대한 착시 현상이자 독약이 되는 순간이었습니다.
스마트한 LLM 모델만 붙여두면 알아서 멀티 스텝 과업을 처리할 줄 알았던 우리의 에이전트 아키텍처는 관측 가능성(Observability)의 부재라는 커다란 벽에 부딪혔습니다. 이 잔혹한 실무 시행착오를 겪고 나서야 깨달았습니다. 단순 서비스 인프라 모니터링과 에이전트 동작 모니터링은 차원이 다른 영역이라는 것을요.
오늘 글을 한 줄로 요약하면 이겁니다. **전통적인 백엔드 APM을 넘어 에이전트 스팬 단위의 생각 관측(Agent Tracing) 아키텍처로 전환해야만 LLM 서비스의 폭주를 막고 운영 비용을 정밀하게 제어할 수 있습니다.**
---
### 1. 자율주행차 내부에 블랙박스와 진단기기를 달아야 하는 이유
전통적인 백엔드 모니터링이 '택시가 목적지까지 잘 도착했는가(HTTP 200)'만 확인하는 일이라면, AI 에이전트 모니터링은 '택시 운전사가 목적지로 가면서 어떤 도로를 선택했고, 왜 길을 잘못 들어 우회했는가'를 실시간으로 기록하는 블랙박스이자 정밀 진단 시스템입니다.
일반적인 API 서버는 입력(Input)이 들어오면 정해진 로직에 따라 출력(Output)을 내보냅니다. 하지만 에이전트는 다릅니다. 사용자의 단일 요청 하나에도 스스로 계획을 세우고(Planning), 필요한 도구(Tools)를 선택하며, 외부 API를 호출하고, 서브 에이전트(Sub-agent)를 스폰해 일을 분배합니다. 이 과정에서 모델은 언제든 엉뚱한 매개변수를 생성할 수 있고, 오래된 컨텍스트를 서브 에이전트에 전달할 수도 있습니다.
저희 팀은 이러한 에이전트 런타임의 불확실성을 통제하기 위해 Cloudflare Agents 아키텍처를 전격 도입했습니다. Cloudflare가 9년 동안 구축해 온 Edge 런타임과 Durable Objects 위에서 에이전트의 가동 상태를 관리하고, OpenTelemetry 호환 트레이스를 붙여 생각의 궤적을 투명하게 가시화한 것입니다.
전환 후 우리가 얻은 정량적 성과는 다음과 같습니다.
* **토큰 재시도 무한 루프 비용**: 월 평균 대비 45% 이상 절감
* **에이전트 병목 지점 추적 시간**: 평균 4시간에서 8분으로 96% 단축
* **첫 번째 토큰 응답 시간(TTFT)**: Durable Runtime 캐싱 및 Edge 배치로 55% 단축
* **루프 오류 즉시 차단율**: 99.8% 달성 (스팬 기반 서킷 브레이커 작동)
이 시스템을 구축하면서 정리한 에이전트 트레이싱의 핵심 가시는 다음과 같습니다.
* **모델 호출 스팬(Model Call Span)**: 에이전트가 단일 턴에서 호출한 LLM 모델명, 사용된 프롬프트 토큰과 완료 토큰 수, TTFT 수치를 정밀 측정합니다.
* **툴 실행 모니터링(Tool Execution Span)**: 에이전트가 어떤 데이터베이스 쿼리나 외부 API 툴을 선택했는지, 전달한 매개변수가 유효했는지 추적합니다.
* **컨텍스트 오염 감지**: 서브 에이전트로 상태를 넘길 때 변질되거나 누락된 페이로드가 없는지 개별 스팬으로 분리하여 진단합니다.
* **인프라 스팬 결합**: Edge Worker의 KV 읽기, D1 데이터베이스 조회 등 인프라 레이어의 지연 시간과 AI 모델 실행 지연 시간을 단일 타임라인으로 통합합니다.
---
### 2. $3,000가 40분 만에 증발했던 무한 루프 잔혹사
저희가 에이전트 전용 트레이스 시스템을 절박하게 구축하게 된 계기는 한 달 전 발생했던 참혹한 인시던트 때문이었습니다.
당시 저희는 쇼핑몰 고객의 환불 및 배송 조회를 자동으로 처리해 주는 멀티 스텝 에이전트를 운영하고 있었습니다. 에이전트는 사용자의 질문을 분석한 뒤 '배송 시스템 API'를 호출하고, 만약 조회 결과가 이상하면 '고객센터 상담원 할당 툴'을 실행하도록 프로그래밍되어 있었습니다.
그런데 외부 배송 API의 특정 엔드포인트에서 예기치 못한 스키마 변경이 발생했습니다. API 응답 데이터의 키값이 `tracking_no`에서 `tracking_number`로 변경되었던 것입니다.
만약 일반적인 코드였다면 NullPointer 에러가 발생하며 500 Internal Server Error를 뱉었을 겁니다. 하지만 똑똑하지만 고집 센 LLM 에이전트는 다르게 반응했습니다. 툴 실행 결과 데이터에서 배송 번호를 찾지 못하자, 자율적으로 판단하여 "파라미터 전달이 잘못되었다"고 스스로 가정한 뒤, 동일한 배송 API를 조금씩 다른 인자값으로 바꿔가며 끊임없이 호출하기 시작했습니다.
* **첫 번째 턴**: 배송 API 호출 → 필드 누락 → 재시도 판단
* **두 번째 턴**: 컨텍스트 재구성 후 배송 API 재호출 → 필드 누락 → 재시도 판단
* **백번째 턴**: 이전 99번의 실패 기록이 프롬프트 컨텍스트에 누적되어 토큰 소비량이 수십 배로 폭증한 상태로 무한 호출
가장 끔찍했던 점은 이 모든 과정에서 백엔드 HTTP 게이트웨이는 외부 배송 API와 OpenAI API 모두로부터 200 OK 응답을 받았다는 사실입니다. 전통적인 Datadog 서비스 대시보드는 초당 처리량(RPS)이 급증하는 것을 그저 '갑작스러운 사용자 유입'으로 인식했고, 시스템상 에러율은 0%를 유지했습니다.
새벽녘 40분 동안 이 에이전트 단 한 개 세션이 소비한 프롬프트 토큰은 무려 8,000만 토큰에 달했습니다. 달러로는 $3,000가 넘는 금액이 허공으로 날아간 뒤에야 API Provider의 쿼터 제한 경고 알림을 받고 상황을 파악할 수 있었습니다.
우리는 즉시 깨달았습니다. 에이전트 서비스에서 HTTP 응답 코드는 아무런 의미가 없다는 것을요. 에이전트가 어떤 생각을 하고 있는지, 툴을 왜 똑같은 것을 반복해서 부르는지, 토큰이 스프링처럼 팽창하고 있지는 않은지를 추적하는 'Agent-aware Tracing'이 없이는 AI 서비스를 운영할 수 없다는 절박한 결론에 도달했습니다.
---
### 3. Cloudflare Agents 기반 관측 가능성 개편 3단계 가이드
이 사건 이후 저희는 인프라 레이어부터 에이전트 트레이싱 아키텍처를 전면 재설계했습니다. Cloudflare Agents를 기반으로 OpenTelemetry를 연동하고 자율 에이전트를 지속 가능하게 모니터링하도록 개편한 3단계 핵심 가이드라인을 공유합니다.
#### 1단계: OpenTelemetry 기반 에이전트 하네스 표준화
가장 먼저 선행되어야 할 작업은 코드 레벨에서 LLM 프레임워크와 OpenTelemetry 스팬을 바인딩하는 것입니다. Think, Flue, Vercel AI SDK 등의 에이전트 하네스(Harness)는 이제 OpenTelemetry 트레이스 규격을 표준으로 지원합니다.
에이전트가 실행되는 모든 턴(Turn)마다 상위 Trace ID를 생성하고, 하위에 모델 호출(Model Call), 툴 실행(Tool Execution), 상태 저장(State Persistence)을 자식 Span으로 분리해야 합니다. 이를 통해 단순한 API 호출 지연 시간뿐만 아니라, 모델이 생각을 정리하는 수초 간의 인퍼런스 병목과 툴 실행에 걸린 시간을 명확히 분리하여 측정할 수 있습니다.
#### 2단계: Durable Runtime 기반 상태 및 세션 격리
에이전트의 턴이 길어지면 서버리스 환경에서는 타임아웃이나 컨텍스트 분실 문제가 발생합니다. 저희는 Cloudflare의 Durable Objects를 기반으로 에이전트 세션을 영속적인 단일 런타임으로 격리했습니다.
각 에이전트 세션은 고유한 ID를 부여받아 Edge 상에서 상태를 유지합니다. 사용자의 입력을 기다리거나 외부 승인(Human-in-the-loop) 단계에서 대기할 때 런타임은 안전하게 일시 정지(Pause)되며, 응답이 들어오면 기존 메모리와 컨텍스트를 즉시 복원합니다. 이로 인해 불필요한 프롬프트 재전송 비용을 100% 방지할 수 있었습니다.
#### 3단계: 루프 감지 및 스팬 기반 서킷 브레이커 구축
트레이스 데이터를 실시간으로 가공하여 동일한 툴이 동일한 매개변수 혹은 유사한 컨텍스트로 연속 3회 이상 실행되는 패턴이 감지되면 즉시 에이전트 세션에 에러 스팬을 주입하고 실행을 중단시키는 서킷 브레이커(Circuit Breaker)를 구축했습니다.
또한 토큰 소모량이 단일 턴에서 설정된 임계치(예: 8,000 토큰)를 초과할 경우, 에이전트가 스스로 컨텍스트를 요약(Summarize)하도록 강제 지시하는 폴백(Fallback) 모듈을 장착했습니다.
```
[사용자 요청]
│
▼
[Cloudflare Edge Worker / Agent Session]
│
├─► [Trace Collector (OpenTelemetry)]
│ │
│ ├─► Model Call Span (Token Count, Latency)
│ ├─► Tool Execution Span (API Status, Schema Valid)
│ └─► State Persistence Span (Durable Objects)
│
└─► [Circuit Breaker Engine]
│
├─► 동일 툴 반복 호출 감지 (Limit: 3회) → 즉시 세션 중단
└─► 토큰 급증 감지 (Limit: 8k Tokens) → Context Summarize 강제
```
---
### 4. 내일 출근해서 당장 적용해야 할 실무 지침
AI 에이전트를 실무 아키텍처에 도입하고 계시거나 준비 중인 팀이라면 다음 3가지 원칙을 즉시 적용해 보시길 권장합니다.
첫째, 백엔드 APM 대시보드에서 HTTP 200 성공률 지표를 과감히 신뢰 대상에서 제외하세요. 대신 에이전트의 '턴당 평균 토큰 소모량'과 '동일 세션 내 툴 재호출 비율'을 1순위 핵심 지표(KPI)로 승격시켜야 합니다.
둘째, 에이전트 가동 런타임을 일반 stateless API 서버와 분리하세요. Durable Executable 특성을 가진 Edge 런타임이나 에이전트 전용 플랫폼으로 옮겨 세션의 상태와 스팬을 온전히 수집할 수 있는 환경을 만들어야 합니다.
셋째, OpenTelemetry 호환 트레이싱 표준을 채택하세요. 벤더 락인을 피하고 Think, Flue, Vercel AI SDK 등의 최신 에이전트 하네스 플랫폼이 내뱉는 스팬 데이터를 단일 추적 파이프라인으로 통합해야 합니다.
* **참고 원문**: [Cloudflare Blog](https://blog.cloudflare.com/agents-on-cloudflare/)
아래 제공하는 무기는 내일 출근해서 여러분의 에이전트 아키텍처 점검 및 트레이싱 파이프라인 구축에 즉시 복사해서 사용할 수 있는 통합 실전 팩입니다.
```text
===============================================================================
1. AI 에이전트 관측 가능성 및 아키텍처 점검 체크리스트
===============================================================================
[ ] HTTP 상태 코드 외에 에이전트의 논리적 성공/실패를 판단하는 지표가 존재하는가?
[ ] 에이전트 단일 세션 내에서 동일한 Tool이 연속 3회 이상 중복 호출될 때 차단하는 로직이 있는가?
[ ] 단일 턴(Turn)당 소비되는 토큰의 최대 한도(Max Token Threshold)가 설정되어 있는가?
[ ] OpenTelemetry 호환 스팬(Span)으로 Model Call과 Tool Execution이 분리되어 추적되는가?
[ ] 에이전트의 컨텍스트(Prompt Context) 누적 크기가 실시간으로 모니터링되고 있는가?
[ ] 서브 에이전트(Sub-agent)로 데이터 전달 시 프롬프트 변질 여부를 검증하는 스팬이 존재하는가?
[ ] 사용자 승인(Human-in-the-loop) 대기 시 무부하 상태로 세션을 일시정지(Pause)할 수 있는가?
===============================================================================
2. Cloudflare Agent Tracing & OpenTelemetry 설정 프롬프트 템플릿
===============================================================================
[역할 정의]
당신은 Cloudflare Agents 및 OpenTelemetry 기반의 AI 에이전트 아키텍처 전문 엔지니어입니다.
백엔드 서비스에서 동작하는 LLM 에이전트의 무한 루프를 방지하고 관측 가능성(Observability)을 확보하는
안전한 Agent Harness 코드를 작성해야 합니다.
[요청 사항]
1. OpenTelemetry Trace를 생성하여 에이전트의 턴(Turn), 모델 호출(Model Call), 툴 실행(Tool Execution)을
독립된 Span으로 기록하는 TypeScript 가이드를 작성하세요.
2. 동일한 Tool이 3회 이상 연속 실패하거나 동일 매개변수로 재호출될 경우,
SessionLoopException을 발생시키고 즉시 스팬을 종료하는 Circuit Breaker 로직을 포함하세요.
3. Cloudflare Durable Objects 환경에서 에이전트 상태(State)를 영속화하고
사용되는 토큰 수(Prompt + Completion Token)를 스팬 속성(Attributes)에 정밀하게 기록하세요.
[출력 코드 구조]
import { trace, SpanStatusCode } from "@opentelemetry/api";
export class AgentTracingManager {
private tracer = trace.getTracer("cloudflare-agent-tracer");
private toolCallHistory: Map<string, number> = new Map();
async executeAgentTurn(sessionId: string, prompt: string, agentFn: Function) {
return this.tracer.startActiveSpan("agent.turn", async (span) => {
span.setAttribute("agent.session_id", sessionId);
try {
const result = await agentFn(span);
span.setStatus({ code: SpanStatusCode.OK });
return result;
} catch (error: any) {
span.recordException(error);
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
throw error;
} finally {
span.end();
}
});
}
validateToolCall(toolName: string, params: object): boolean {
const key = `${toolName}:${JSON.stringify(params)}`;
const count = (this.toolCallHistory.get(key) || 0) + 1;
this.toolCallHistory.set(key, count);
if (count >= 3) {
throw new Error(`[Circuit Breaker] Tool '${toolName}' executed 3 times with identical parameters. Loop detected.`);
}
return true;
}
}
===============================================================================
3. 에이전트 트레이스 수집 및 분석을 위한 CLI 가이드
===============================================================================
# 1. Cloudflare Agents 개발 환경 구축 및 Wrangler CLI 설정
npm install -g wrangler
wrangler agents init my-observable-agent
# 2. OpenTelemetry 및 에이전트 하네스 패키지 설치
npm install @opentelemetry/api @opentelemetry/sdk-trace-base @cloudflare/workers-types
# 3. 로컬 런타임에서 에이전트 트레이스 로그 실시간 스트리밍 검증
wrangler dev --remote --trace-agent-logs
# 4. 생산 환경 배포 후 에이전트 세션 및 스팬 수집 상태 확인
wrangler agents deployments list
wrangler tail --format=json | grep "agent.turn"
```
최신 IT & Mind 리포트 더보기
- 개발 생산성 측정하려다 팀 분위기 망친 이유
- 피드백이 두려워 코드를 더 부풀리는 뇌의 비극
- 동료 피드백 하나로 팀 내 내 영향력을 3배 올리는 법
- 내 눈엔 완벽한 설계가 남에겐 지옥인 이유
- 무거운 파이프라인 버리고 엣지 CI로 갈아탄 이유
- 새 기술 도입할 때 팀원 설득에 실패하는 진짜 이유
- 배포를 앞두고 갑자기 프레임워크를 바꾸는 뇌의 방어기제
- 수동 대시보드 버리고 엣지 비용 API로 갈아탄 이유
- 새벽 3시 알람에 울던 팀이 장애를 성과로 바꾼 비결
- 간단한 문제를 거대하게 부풀리는 뇌의 착각
- 단순 TTS 버리고 제어형 오디오 모델로 갈아탄 이유
- 일 잘하는 개발자는 코드 대신 팀장을 움직인다
- 완벽한 코드를 짜고도 스스로 기술 부채를 만드는 이유
- 단방향 HTTP 버리고 엣지 gRPC로 갈아탄 이유
- 개발 불확실성 90% 줄이는 테크니컬 스파이크의 비밀
- 측정하려 들수록 생산성이 망가지는 이유
- 인간용 클라우드 버리고 에이전트 전용 아키텍처 구축한 이유
- 매번 일정 넘기던 개발자가 팀의 신뢰를 싹쓸이한 비결
- 장애 상황에서 똑똑한 개발자가 바보가 되는 이유
댓글 0