Claude Code 장애 리뷰: Anthropic의 세 가지 프로덕션 버그가 에이전트 엔지니어에게 주는 교훈
요약
Anthropic이 공개한 Claude Code의 세 가지 프로덕션 장애 사례를 통해 LLM 에이전트 시스템 구축 시 주의해야 할 교훈을 다룹니다. 추론 수준 변경, 캐시 최적화, 시스템 프롬프트 수정이 실제 서비스에서 어떤 예기치 못한 부작용을 일으켰는지 상세히 분석합니다.
핵심 포인트
- 추론 수준(reasoning effort) 조정은 지연 시간 개선과 지능 저하 사이의 트레이드오프를 유발함
- 캐시 최적화 로직 오류는 에이전트의 기억 상실과 반복적인 도구 호출 문제를 야기함
- 시스템 프롬프트의 미세한 수정이 코딩 품질과 같은 핵심 성능의 퇴보를 불러올 수 있음
- 에이전트 시스템은 파라미터, 캐시, 프롬프트 등 복합적인 요소의 상호작용을 고려해야 함
서론 (Intro)
지난달, Anthropic은 보기 드문 형태의 장애 리뷰 (incident review)를 공개했습니다.
보기 드문 점은 그들에게 버그가 있었다는 사실이 아닙니다. 대규모 모델 제품을 만든다면 버그는 당연히 수반되는 요소입니다.
정말 보기 드문 점은 그들이 세 가지 프로덕션 장애 (production incidents)를 상세히 기록했다는 것입니다. 각 장애가 어떻게 발생했는지, 왜 테스트에서 놓쳤는지, 왜 내부적으로 재현하기 어려웠는지, 그리고 이후에 무엇을 변경했는지를 말이죠.
이 리뷰를 읽고 나서, 저는 이 내용을 면밀히 연구할 가치가 있다고 생각했습니다. 만약 여러분이 LLM 에이전트 (LLM Agents), 특히 멀티턴 작업 (multi-turn tasks), 도구 호출 (tool calls), 컨텍스트 압축 (context compression), 그리고 추론 추적 관리 (reasoning trace management)를 포함하는 시스템을 구축하고 있다면, 이러한 실패 사례들은 예외적인 상황이 아닙니다. 그것들은 길 위에서 여러분을 기다리고 있습니다.
세 가지 버그, 세 가지 실패 모드 (Three Bugs, Three Failure Modes)
요약 버전은 다음과 같습니다.
첫 번째 버그: 3월 4일, high 추론 모드에서 Opus 4.6의 간헐적인 UI 프리징 (UI freezes) 문제를 해결하기 위해, 팀은 기본 추론 노력 (reasoning effort) 수준을 high에서 medium으로 변경했습니다.
내부 테스트 결과는 괜찮아 보였습니다. 지능은 아주 약간 하락했지만, 지연 시간 (latency)은 크게 개선되었습니다.
하지만 출시 후, 사용자들은 강력하게 반발했습니다. Claude가 더 멍청해졌다고 느낀 것입니다.
한 달 뒤인 4월 7일, 해당 변경 사항은 롤백 (rolled back)되었습니다.
두 번째 버그: 3월 26일, Anthropic은 캐시 최적화 (cache optimization) 기능을 배포했습니다. 아이디어는 간단했습니다. 세션이 한 시간 이상 유휴 상태(idle)가 되면, 재개 시 발생하는 비용을 줄이기 위해 오래된 사고 이력 (thinking history)을 삭제하는 것이었습니다.
합리적으로 들리지 않나요?
하지만 프로덕션 구현 단계에서 버그가 발생했습니다. 원래는 오래된 사고 내용을 한 번만 삭제해야 했습니다. 대신, 이후의 모든 턴 (turn)마다 계속해서 삭제를 반복했습니다.
그 결과 Claude는 작업을 계속 수행하면서도, 자신이 왜 그 작업을 하고 있는지에 대한 기억을 반복적으로 잃어버리게 되었습니다. 사용자들은 망각, 반복, 이상한 도구 호출 (tool calls), 그리고 점점 더 기이해지는 동작을 목격했습니다.
설상가상으로, 사고 블록 (thinking blocks)이 계속 사라지면서 각 요청은 캐시 미스 (cache miss)가 되었고, 사용량 제한 (usage limits)을 더 빠르게 소모했습니다.
근본 원인 (root cause)은 2주가 지난 4월 10일이 되어서야 파악되었습니다.
세 번째 버그: 4월 16일, Opus 4.7의 장황한 출력 (verbose output)을 줄이기 위해, 팀은 시스템 프롬프트 (system prompt)에 한 줄을 추가했습니다:
도구 호출 (tool calls) 사이에는 25단어를 넘지 않게 사용하고, 최종 응답에는 100단어를 넘지 않게 하세요.
해당 프롬프트(prompt) 한 줄은 몇 주간의 내부 테스트 동안 눈에 띄는 퇴보 (regression)를 보이지 않았습니다.
하지만 출시 후, 코딩 품질이 3% 하락했습니다.
4월 20일, 해당 설정은 롤백 (rollback)되었습니다.
이 세 가지 버그는 서로 달라 보이지만, 동일한 문제를 가리키고 있습니다. 에이전트 (Agent) 시스템에서는 파라미터 (parameters), 캐시 (caches), 프롬프트 줄 (prompt lines)과 같이 국소적으로 보이는 것들이 여전히 핵심 실행 로직에 영향을 미칠 수 있다는 점입니다.
그것들을 건드리는 것은, 모델의 뇌를 건드리는 것과 같습니다.
추론 이력 (Reasoning History)은 로그가 아니라 작업 기억 (Working Memory)이다
두 번째 버그는 제가 계속해서 되새기게 되는 문제입니다.
"토큰을 절약하기 위해 오래된 생각을 지워라"는 것은 매우 정상적인 엔지니어링 최적화 (engineering optimization)입니다. 사고 블록 (thinking blocks)은 길고 비용이 많이 듭니다. 세션이 한 시간 동안 유휴 상태 (idle)였다면, 오래된 추론 체인 (reasoning chain)은 덜 중요해 보일 수 있습니다.
하지만 그것이 바로 함정입니다.
에이전트에게 추론 흔적 (reasoning trace)은 단순한 로그가 아닙니다. 그것은 단순히 무엇이 일어났는지를 기록하는 것이 아닙니다. 더 중요한 역할은 에이전트가 왜 이전의 결정을 내렸는지를 보존하는 것입니다.
그 '이유'가 바로 멀티 턴 (multi-turn) 작업이 계속 진행될 수 있게 해주는 동력입니다.
그것이 사라지면, 에이전트는 즉시 충돌 (crash)하지 않습니다. 여전히 대화하고, 도구를 호출하며, 결과를 반환할 수 있습니다. 하지만 이미 잊기 시작한 상태입니다.
어떤 경로가 제외되었는지, 왜 현재 경로가 선택되었는지, 그리고 사용자가 실제로 해결하려고 했던 문제가 무엇인지 잊어버립니다.
그 결과는 아주 고약한 형태의 성능 저하 (degradation)로 나타납니다. 성능은 점점 나빠지고, 작업은 표류 (drift)하게 됩니다.
이러한 종류의 버그는 고통스럽습니다. 왜냐하면 충돌이 아니기 때문입니다. 깔끔한 스택 트레이스 (stack trace)를 제공하지도 않습니다. 대신 프로덕션 환경에서 에이전트가 이상하게 나빠졌다는 느낌으로 서서히 나타납니다.
따라서 컨텍스트 관리 (context management)는 단순히 토큰 수를 무식하게 깎아내는 방식이 되어서는 안 됩니다.
최소한, 우리는 세 가지 카테고리를 분리해야 합니다:
- 압축하지 말 것 (Do not casually compress): 결정 근거 (decision rationale), 작업 의도 (task intent), 엄격한 제약 조건 (hard constraints), 추론 경로 (reasoning path).
- 압축 가능 (Can compress): 중간 관찰 결과 (intermediate observations), 도구 출력값 (tool outputs), 프로세스 자료 (process material).
- 삭제 가능 (Can drop): 포맷팅 도우미 (formatting helpers), 중복된 설명 (redundant explanations), 임시 디스플레이 콘텐츠 (temporary display content).
추론 이력 (Reasoning history)은 캐시 쓰레기 (cache garbage)가 아닙니다. 많은 경우, 그것은 에이전트 (Agent)의 작업 기억 (working memory)입니다.
당신은 토큰을 아끼고 있다고 생각할지도 모릅니다. 하지만 실제로는 에이전트가 작업에 집중할 수 있게 해주는 시스템의 일부를 제거하고 있는 것일 수도 있습니다.
모든 프롬프트 라인은 코드다 (Every Prompt Line Is Code)
세 번째 버그도 그만큼 중요합니다.
"말을 줄여라 (say less)"라는 한 줄을 추가하는 것이 어떻게 코딩 품질을 저하시킬 수 있을까요?
모델의 동작 (model behavior)에서, 출력의 감소와 사고의 감소는 항상 별개의 것이 아니기 때문입니다.
만약 당신이 최종 답변을 100단어 이내로 제한하고, 도구 호출 (tool calls) 사이의 텍스트를 25단어 이내로 제한한다면, 모델은 표현을 압축할 뿐만 아니라 결정 과정 (decision process) 자체를 압축해 버릴 수도 있습니다.
이것은 전통적인 의미의 버그가 아닙니다. 모델은 당신이 준 목표를 위해 진심으로 최적화(optimizing)하고 있는 것입니다.
그렇기에 Anthropic의 후속 규율 (follow-up discipline)이 중요합니다. 모든 시스템 프롬프트 (system prompt) 변경 사항은 모델별로 절제 실험 (ablated)을 거쳐야 합니다. 한 줄씩 테스트할 수 있다면, 한 줄씩 테스트하십시오. 지능에 영향을 미칠 수 있는 변경 사항은 점진적 배포 (gradual rollout)와 침전 기간 (soak period)이 필요합니다.
다소 무겁게 들릴 수도 있습니다.
하지만 프롬프트가 프로덕션 코드 (production code)라는 점을 받아들인다면, 이러한 규율은 과도한 것이 아닙니다.
깨끗한 테스트 환경은 프로덕션과 다르다 (Clean Test Environments Are Unlike Production)
사람들이 직면하기 싫어하는 흔한 에이전트 엔지니어링 (Agent engineering) 문제가 있습니다:
테스트 환경이 너무 깨끗하다는 것입니다.
너무 깨끗해서 프로덕션 (production)처럼 보이지 않을 정도입니다.
많은 에이전트 실패 사례는 단순히 "입력 A가 잘못된 출력 B를 생성한다"처럼 단순하지 않습니다. 그것들은 상태의 시퀀스 (sequence of state)에 의존합니다:
한 시간 이상 세션 유휴 상태 (session idle)
재개 (resume)
멀티 턴 도구 사용 (multi-turn tool use) 계속
...
그러한 종류의 상태 시퀀스는 단위 테스트 (unit tests)로 커버하기 어렵고, 엔드 투 엔드 테스트 (e2e tests)에서도 놓치기 쉽습니다.
우리는 기능을 테스트하지만, 프로덕션은 상태 머신 (state machine)을 실행합니다.
그것이 바로 Anthropic이 나중에 테스트 빌드 대신, 공개 릴리스와 정확히 동일한 Claude Code 빌드를 더 많은 내부 직원들이 사용하게 했던 이유이기도 합니다.
실제 사용(Real usage)은 여전히 가장 훌륭한 통합 테스트 (integration test)입니다.
기본값은 곧 제품이다 (Defaults Are the Product)
이제 첫 번째 버그로 돌아가 보겠습니다.
high를 medium으로 변경한 것은 엔지니어링 관점에서는 타당했습니다. 프리징 (freezes)이 줄어들고, 지연 시간 (latency)이 낮아지며, 지능 저하는 아주 미미했기 때문입니다.
문제는
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기