Claude MCP 디버깅: 프록시, 인증(Auth), 그리고 Rate Limits 처리하기
요약
MCP 에이전트가 프로덕션 환경에서 데이터를 누락시키는 주요 원인은 코드 버그보다 프록시나 로드 밸런서 같은 인프라 설정 문제입니다. 특히, 게이트웨이가 실제 오류 상태 코드를 일반적인 502/500으로 정규화하는 것이 문제를 일으킵니다. 해결책으로 `proxy_intercept_errors off` 설정을 통해 실제 업스트림 상태 코드와 헤더가 클라이언트에게 전달되도록 해야 합니다.
핵심 포인트
- 프록시/로드 밸런서 설정이 에이전트 실패의 주원인일 수 있습니다.
- 게이트웨이가 오류 코드를 정규화하면 재시도 로직(예: 401 감지)이 오작동합니다.
- `proxy_intercept_errors off` 설정을 사용하여 실제 업스트림 상태 코드와 헤더를 전달해야 합니다.
- Rate Limit (429) 처리는 충돌로 간주하지 말고, 지터가 적용된 지수 백오프 방식을 사용하세요.
3주가 지나서야 드러나는 실패
430개의 유효 리드가 CRM에 들어갔지만 기록되지 않았습니다. 에이전트는 모든 통화에서 성공했다고 보고했습니다. 프록시 뒤의 Bearer 토큰은 6일 전에 만료되었고, 프록시는 실제 오류를 삼키고 일반적인 502 응답만 반환하고 있었습니다.
이것이 바로 프로덕션 환경에서 MCP 에이전트가 보이는 패턴입니다. 그들은 충돌하지 않습니다. 조용히 데이터를 누락시키면서 성공을 보고하며, 피해는 오늘 스택 트레이스(stack trace)로 나타나는 것이 아니라 몇 주 후에 파이프라인 리포트로 나타납니다.
당신의 프록시가 에이전트에게 거짓말을 하고 있다
대부분의 MCP 연결 실패는 프로토콜 버그가 아닙니다. 그것들은 로컬 개발 환경에서는 작동했지만, 프록시나 로드 밸런서(load balancer)가 개입하는 순간 깨지는 인프라 기본 설정입니다.
흔한 실패 사례는 다음과 같습니다: 프록시나 API 게이트웨이가 모든 업스트림(upstream) 오류를 일반적인 상태 코드, 보통 502 또는 500으로 정규화합니다. 에이전트의 재시도 로직은 401을 감지하여 토큰 새로고침을 트리거하도록 작성되어 있습니다. 하지만 그것은 401을 절대 보지 못합니다. 대신 502를 보고, 서비스가 다운되었다고 가정하고 무작정 재시도를 하거나 포기하게 됩니다.
에이전트 코드를 건드리기 전에 먼저 프록시 설정을 수정하세요. 상태 코드와 헤더를 정규화하는 대신 실제 업스트림 상태 코드와 헤더를 전달해야 합니다:
location /mcp/ {
proxy_pass http://mcp_backend;
proxy_intercept_errors off;
...
proxy_intercept_errors off를 사용하면 게이트웨이가 업스트림 오류 페이지를 재작성하는 것을 막을 수 있습니다. 실제 401이 클라이언트에게 도달하면, 기존의 새로고침 로직이 실제로 작동하게 됩니다.
서버가 당신에게 말하듯이 429를 처리하라, 충돌처럼 처리하지 마라
429 에러는 서버가 속도를 늦추라고 요청하는 것이지, 무언가 고장났다고 알려주는 것이 아닙니다. 이를 시스템 충돌로 간주하면, 에이전트가 너무 공격적으로 재시도하여 차단되거나, 완료했어야 할 작업을 포기하게 됩니다.
고정된 간격 대신 지터(jitter)를 사용한 지수 백오프(exponential backoff) 방식을 사용하세요. 고정된 간격은 모든 클라이언트가 같은 순간에 제한을 받으면, 모두가 같은 순간에 재시도하여 예정대로 두 번째 429 웨이브를 유발합니다.
import random
import time
...
문서화된 속도 제한에 맞춰가 아니라 그보다 낮은 수준으로 동시성(concurrency)을 설정하세요. 하나의 에이전트가 12개의 병렬 도구 호출을 단일 MCP 서버에 날리면, 이를 세 개 또는 네 개의 동시성 제한을 가진 큐를 통해 라우팅하는 것보다 훨씬 빨리 한계치에 도달합니다. 같은 키(key)에 대한 다른 트래픽은 자체 코드가 정상적으로 작동하더라도 여유 공간(headroom)을 소모합니다.
하나의 에이전트, 하나의 작업
리드 자격 검증, 아웃리치 초안 작성, CRM 업데이트, 미팅 예약 등 여러 작업을 수행하는 단일 에이전트는 그 작업들 사이의 핸드오프(handoff) 지점에서 실패할 것입니다. 이를 정의된 계약을 가진 좁은 에이전트들로 분할하세요. 엄격한 JSON 스키마를 출력하는 리드 자격 검증 에이전트는 디버깅하기가 매우 쉽습니다. 다섯 개의 시스템에 손대는 모놀리식(monolithic) 에이전트는 모든 버그를 로그 고고학의 오후 시간으로 만들 텐데, 전체 체인을 추적하지 않으면 어떤 책임 때문에 문제가 생겼는지 격리할 수 없기 때문입니다.
에이전트와 전송 버튼 사이에 인간을 배치하세요
초안 작성은 자동화하세요. 실제 전송(이메일, CRM 업데이트 또는 캘린더 초대장 등)은 최소한 처음 몇백 건의 실행에 대해서는 인간의 승인을 거치도록 게이트를 설정해야 합니다. 에이전트가 플래그 지정하는 내용에 대한 오탐률(false positive rate)과 미탐률(false negative rate)을 추적하고, 이 데이터가 충분히 쌓였을 때만 체크포인트를 해제하세요. 데모가 좋아 보였다는 이유로 첫날부터 게이트를 제거하면, 아무도 알아차리기 전에 나쁜 프롬프트가 실제 리스트 전체를 소진시켜 버립니다.
총 지출량(total spend)이 아닌 자격 있는 리드당 토큰을 확인하세요
총 토큰 지출량(Total token spend)만으로는 어떤 조치도 취할 수 없습니다. 중요한 것은 적격 리드당 토큰 지출량입니다. 급증은 보통 두 가지 중 하나를 의미합니다. 프롬프트가 잘못된 출력에 대해 재시도하고 있거나, 컨텍스트 창(context window)이 턴(turns)을 거치면서 불필요한 기록을 축적하여 잘리지 않고 있다는 것입니다. 모델을 확인하기 전에 호출당 토큰 수(per-call token count)를 먼저 확인하세요. 특정 도구 호출(tool call)에서 SLA(Service Level Agreement) 이상의 지연 시간(Latency) 급증은 거의 항상 외부 종속성(external dependency)에 기인하며, 모델 자체의 문제가 아닙니다.
엣지 케이스(edge cases)에서의 합성 테스트 단축키는 건너뛰세요
합성 사용자 테스트(Synthetic user testing)는 빠르고 저렴한 사전 필터입니다. 이는 지원 티켓 대기열을 대체할 수 없습니다. 도움이 되도록 조정된 모델들은 동의하는 점수(agreeable scoring)로 기본 설정되므로, 다섯 가지 다른 흐름(flows)을 테스트하는 다섯 개의 합성 페르소나(synthetic personas)는 어떤 흐름이 실제로 더 나쁘든 상관없이 종종 척도의 상단 근처에 몰리게 됩니다. 이를 최종 검증 수단으로 사용하기보다는, 실제 사용자가 발견하기 전에 명백한 오류를 포착하는 데 사용하세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
