4 minute read

스펙 시트에 박힌 ‘100만 토큰 지원’ 같은 마케팅 문구를 곧이곧대로 믿지 말라는 건 귀에 딱지가 앉도록 들었다. 하지만 솔직히 개발자 입장에서 1M 컨텍스트라는 숫자를 보면 심장이 두근거리는 게 인지상정 아닌가(물론 내 맥미니는 벌써 비명을 질렀다). 며칠 치 회의록, 코드 리뷰, 터미널 배포 로그를 압축이나 요약 같은 잔기술 없이 통째로 들이부어도 남는 광활한 용량이니까. 그런데 r/openclaw의 한 용자가 이 100만 토큰 한계선까지 에이전트를 극한으로 밀어붙였다가 처참하게 침몰한 기록을 공개했다. 결론부터 말하자면 에이전트는 23시간 만에 정신줄을 놓아버렸고, 마지막 단말마는 ‘design’ 단어의 무한 반복이었다…

무슨 일이 벌어졌나

글쓴이 u/OleCuvee는 OpenClaw를 얹은 디스코드 봇 에이전트를 실전에 굴리고 있었다. 두뇌는 Ollama Cloud의 GLM 5.3 Flash, 컨텍스트 창은 무려 1,048,576 토큰이다. 여러 채널에서 6명 남짓한 팀원들과 실시간 대화도 나누고, 도구도 척척 부르고, 코드 수정에 영수증 정리까지 도맡아 하는 빡센 실전 워크로드였다.

처음 23시간 동안은 기적처럼 잘 돌아갔다. 트랜스크립트 이벤트 800개를 넘기면서도 복잡한 개발 체인을 물고 늘어졌고, 과거 결정 사항도 칼같이 기억했다(여기까진 ‘와, 드디어 AGI가 왔구나’ 싶었겠지).

첫 번째 이상 징후는 컨텍스트가 683k 토큰에 도달했을 때 터졌다. 어떤 팀원이 다른 셋업 작업 끝났다고 보고했는데, 에이전트가 뜬금없이 19시간 전에 끝난 옛날 작업 지시문을 툭 뱉어낸 거다. 솔직히 이때만 해도 그러려니 넘겼단다. 원래 LLM 오래 굴리다 보면 옛날 기억이 가끔 새어 나오는 건 흔한 버그니까(국룰이다).

그런데 딱 2분 뒤, 지옥문이 열렸다.

에이전트가 그 옛날 작업을 두고 혼자 긴 내부 계획 독백을 중얼거리더니, 화면에 수백 개의 “design” 단어를 기관총처럼 쏟아내기 시작했다. 이어서 초록색 체크표시, “tool tool tool”, “toolResult”, 가짜 트랜스크립트 조각, 정체불명의 숫자 나열, 심지어 내부 오케스트레이션 패킷 껍데기까지 미친 듯이 토해냈다(공포 영화가 따로 없다). /new, /reset, /stop 같은 비상 탈출 명령어는 먹통이었고, 결국 세션 프로세스를 강제로 킬(kill)해야만 했다. 마지막 정상 턴이 683k, 최종 뇌사 상태에 빠진 턴이 688k. 공식 스펙 1M의 딱 65% 지점에서 장렬히 전사했다.

정상 응답이라는 더 큰 문제

이 사건에서 소름 돋는 건 에이전트 붕괴 그 자체가 아니다. 런타임 하네스(시스템 모니터링) 관점에서는 이 모든 참사가 완벽한 성공으로 기록되었다는 점이다.

컨텍스트 오버플로 에러도 안 떴고, API 프로바이더 타임아웃도 없었다. “design design design…“이라는 끔찍한 헛소리가 시스템상으로는 ‘200 OK, 유효한 응답’으로 처리된 거다. 즉, 서버 헬스체크 대시보드만 보고 있으면 에이전트가 미쳐 날뛰는 동안에도 초록불이 반짝이고 있었다는 뜻이다.

글쓴이가 식은땀을 흘리며 텔레메트리 로그를 깠을 때 마주한 진실은 더 충격적이었다.

GPT-5.5 경로 (OpenAI)   : cache-read 14.9M / 미캐시 1.33M → 프롬프트의 91.8% 캐시 적중
GLM 5.3 Flash (Ollama)  : cacheRead 0, cacheWrite 0      → 캐시 재사용 관측 없음

붕괴 직전 25분 동안 68만 토큰짜리 거대한 프롬프트가 10번이나 연속으로 API에 전송됐고, 그 짧은 찰나에 입력 토큰만 610만 개가 갈려 나갔다. 원래 시스템 설계는 컨텍스트가 75%를 채우면 자동으로 압축(compaction) 알고리즘이 돌게 되어 있었는데, 하필 그 안전망이 켜지기 딱 10만 토큰 전에 모델이 먼저 뻗어버렸다.

진짜 씁쓸한 블랙코미디는 따로 있다. 붕괴 직전에 작성자가 “캐싱 레이어 하나 새로 짜줄까?” 하고 물어봤더니, 에이전트 녀석이 아주 씩씩하고 자신만만하게 답했다는 거다. “걱정 마세요! 반복되는 컨텍스트는 프로바이더가 프롬프트/KV 캐싱으로 알아서 싸게 처리해 줍니다!” (물론 완벽한 헛소리였다). OpenAI나 Anthropic이면 맞는 말인데, 정작 녀석이 돌던 실제 경로에선 cacheRead=0, cacheWrite=0이 찍히고 있었다. “이거 엄청 저렴해요”라고 천연덕스럽게 뻥을 치는 동안 시스템은 매 턴 68만 토큰을 생돈으로 태우고 있었던 셈이다. 이 유저는 훗날 이 순간을 ‘체르노빌 모먼트’라고 회고했다.

컨텍스트 크기와는 별개의 병

더 골 때리는 후일담이 있다. 완전히 세션을 밀고 클린 리셋을 돌렸는데, 프롬프트가 고작 2만 토큰밖에 안 되는 새 세션에서도 똑같은 정신분열 증상이 재현됐다는 사실이다.

이번엔 형태가 달랐다. 에이전트가 속마음(내부 판단 과정)을 사용자 화면에 그대로 생중계하기 시작했다. “사용자 요청을 이렇게 재작성함 -> 답변할지 말지 고민 중 -> 이제 최종 답변을 내보내겠음”이라는 뇌내 망상을 줄줄이 읊은 뒤에야 답변 본문이 나왔다. 심지어 답변하지 않는 게 낫겠다고 판단한 턴에서는 “NO_REPLY”라는 내부 플래그를 채팅방에 당당히 쏴버렸다. 컨텍스트 길이가 길어서 터진 게 아니라, 모델의 출력 경계(Guardrail) 자체가 망가졌다는 방증이다.

그럼에도 작성자의 결론은 꽤나 성숙하다. GLM 5.3 Flash를 쓰레기라고 내다 버리지 않았다. 평소 수시간 동안은 훌륭한 추론과 툴 활용 능력을 보여줬고, 지금도 디스코드 일상 업무에 쓰고 있단다. 모델 탓만 하며 징징대는 대신, 아키텍처 레벨에서 재발 방지책을 짰다.

  1. 오염된 채널 2개 영구 폐쇄
  2. 망가진 세션 재진입 원천 차단
  3. 스크래치패드 유출 방어 레이어 삽입
  4. 무거운 로그 처리를 실시간 대화 파이프라인에서 분리
  5. 정기적인 강제 세션 리셋 도입

왜 주목할까

광활한 컨텍스트 윈도우는 분명 달콤한 유혹이다. 하지만 그 넓은 방이 실제 운영 환경에서 어떤 악조건을 만났을 때 무너지는지는 제조사 브로슈어가 절대 알려주지 않는다.

  1. ‘1M 컨텍스트’는 스펙일 뿐, 품질 보증 수표가 아니다: 프리필(prefill)이 잦은 에이전트 환경에서 실질적으로 안전한 컨텍스트는 스펙의 60~70% 수준일 수 있다.
  2. 압축 시점의 재설계: 단순히 ‘남은 용량 비율(%)’만 보고 기다리다간 안전망 닿기 전에 죽는다. 누적된 미캐시 입력량이나 트랜스크립트 바이트 크기 기준으로 조기 압축을 때려야 한다.
  3. 캐시 텔레메트리 감시: 내 눈으로 캐시 적중률(cacheRead)이 안 보이면 캐싱은 없는 거나 다름없다.
  4. 출력 감시 안전망 필수: 200 OK로 떨어지는 유창한 쓰레기 응답을 걸러낼 토큰 반복 감지나 가드레일이 반드시 필요하다.

정리

장기 실행 에이전트를 운영하는 개발자라면 당장 내 서비스의 cacheRead 메트릭부터 뜯어보게 만드는 뼈 때리는 글이다. 100만 토큰의 허상을 직접 온몸으로 부딪쳐 깨지고, 그 처절한 실패 로그를 가감 없이 공유해 준 개발자에게 경의를 표하고 싶다.

그 불운했던 에이전트의 이름은 Franny였다. 붕괴 직전 스스로 고백했다고 한다. 내 기억도 결과도 온통 지어낸 허상투성이라 무엇을 믿어야 할지 모르겠다고. 컨텍스트 창이 몇 백만 토큰이냐를 자랑하는 시대지만, 정작 중요한 건 그 창문이 언제 흐려지는지 먼저 알아채는 엔지니어의 통찰력이다.

원본 스레드: I ran Francis as a 1M context Discord agent for 23 hours (r/openclaw)