레슨 1: 컨텍스트 윈도우가 에이전트가 가진 메모리의 전부다
학습 목표:
- '에이전트가 이전 대화를 기억한다'가 착각인 이유 설명하기
- 단일 요청의 컨텍스트 윈도우에 무엇이 포함되고 무엇이 포함되지 않는지 짚기
- 컨텍스트 로트가 무엇인지, 그리고 윈도우가 크다고 해서 자동으로 다루기 좋은 것은 아닌 이유 설명하기
- API 호출이 스테이트리스인지 판단하고, 그것이 메모리에 어떤 의미인지 설명하기
전제: 이 시리즈의 처음 네 개 코스, 그중에서도 '에이전트 도구 호출: 에이전트가 실제로 일하게 만들기'의 도구 호출 왕복 프로토콜 포함 | 다음: 레슨 2 >>
기억하는 것처럼 보이는 대화
고객 지원 에이전트와 대화하고 있다고 해봅시다:
두 번째 턴에서 에이전트는 당신의 이름이 Sarah라는 것을 분명히 '기억하고' 있고, ORD-2026-8842에 대해 물었다는 것도 기억합니다. 마치 그 세부 정보들을 어딘가에 정리해 두었다가 다음번에 다시 꺼내 올 수 있는 것처럼 보입니다.
진실은 훨씬 더 단순합니다. 요청할 때마다 당신의 코드는 대화 시작부터 지금까지의 모든 메시지를 다시 묶어 그대로 모델에 보냅니다.1 모델은 '당신의 이름이 Sarah라는 것을 기억하고 있다'를 보는 것이 아니라, '사용자가 말했다: 내 이름은 Sarah'를 매번 처음부터 다시 읽는 것입니다. 이전 턴의 모든 문장, 모든 도구 호출은 당신 자신의 코드에 의해 이번 턴의 요청 안에 배치되어야 합니다. 모델은 스스로 아무것도 저장하지 않습니다.
API 호출은 스테이트리스다
더 직설적으로 말하면: 한 호출과 다음 호출 사이에 서버에서 조용히 보관되는 것은 아무것도 없습니다. 이 요청이 처리되고 나면 그 토큰들은 모델의 시야에서 사라집니다. 다음 요청이 아무것도 실어 오지 않으면 모델은 백지 상태를 봅니다 — 당신의 이름조차 모릅니다.
그것이 메모리처럼 느껴지는 이유는 호스트 애플리케이션이 당신을 대신해 궂은일을 해주기 때문입니다: 히스토리 메시지 배열 전체를 다시 보냅니다. 이것은 모델의 능력이 아닙니다. 계속 커지는 당신 코드 안의 배열일 뿐입니다. 이 성질에는 이름이 있습니다 — **스테이트리스(stateless)**입니다. 공식 문서의 표현을 빌리면: "The Messages API is stateless, which means that you always send the full conversational history to the API."1 (Messages API는 스테이트리스이며, 이는 항상 전체 대화 히스토리를 API로 보내야 한다는 뜻입니다) 서버는 요청 사이에 세션별 비공개 상태를 보관하지 않습니다. 모든 '메모리'는 클라이언트 자신이 실어 나르고 다시 보내야 합니다.
컨텍스트 윈도우에 실제로 담기는 것
모델이 볼 수 있는 모든 것은 컨텍스트 윈도우라는 컨테이너 안에 존재합니다. 문서는 요청 안의 모든 것이 포함된다고 명시합니다: "Everything in the request counts toward the context window: the system prompt, every message in messages (including tool results, images, and documents), and your tool definitions. The output Claude generates for the turn, including its extended thinking, counts too."2 (요청 안의 모든 것이 컨텍스트 윈도우에 포함됩니다: 시스템 프롬프트, messages 안의 모든 메시지(도구 결과, 이미지, 문서 포함), 그리고 도구 정의입니다. Claude가 그 턴에서 생성하는 출력도, 확장 사고를 포함해 함께 포함됩니다)
이 요청에서는 system, tools, 그리고 messages 배열 안의 세 메시지 모두가 컨텍스트 윈도우에 포함됩니다. 모델의 응답이 생성되면 그 출력 토큰들도 같은 이번 턴의 윈도우 사용량에 포함됩니다. 응답에는 usage 필드가 담겨 있어 그 턴이 실제로 소비한 입력 토큰과 출력 토큰의 수를 알려줍니다: "Every response reports what the request consumed in its usage field."2 (모든 응답은 요청이 소비한 것을 usage 필드로 보고합니다)
이 요청에 묶여 들어가지 않은 것 — 이를테면 아직 어떤 도구도 조회하지 않은, 데이터베이스에 놓여 있는 주문 레코드 — 은 컨텍스트 윈도우의 일부가 아닙니다. 모델은 그것을 볼 수 없고, 그것이 존재한다는 것을 난데없이 알 수도 없습니다. 그래서 '메모리'는 어떤 메커니즘에 의해 이 요청 안으로 능동적으로 실려 들어와야 합니다. 자동으로 닿을 수 있는 것이 아닙니다.
윈도우는 썩는다 — 크다고 더 나은 것은 아니다
윈도우가 담을 수 있는 양에는 상한이 있습니다 — 용량은 모델마다 다르고, 공식 수치는 최대 100만 토큰까지 갑니다: "The context window (up to 1M tokens, depending on the model) holds the conversation history plus the new output Claude generates."2 (컨텍스트 윈도우는(모델에 따라 최대 1M 토큰) 대화 히스토리와 Claude가 생성하는 새 출력을 담습니다) 하지만 그렇다고 가능한 한 가득 채워 넣어야 한다는 뜻은 아닙니다. 문서는 특정 현상, **컨텍스트 로트(context rot)**를 명명합니다: "As token count grows, accuracy and recall degrade, a phenomenon known as context rot. This makes curating what's in context just as important as how much space is available."2 (토큰 수가 늘어날수록 정확도와 회상이 저하되며, 이는 컨텍스트 로트로 알려진 현상입니다. 이 때문에 컨텍스트에 무엇을 담을지 선별하는 일은 얼마나 많은 공간이 남아 있는지만큼이나 중요해집니다) 다시 말해, 윈도우가 담는 내용이 많아지고 어수선해질수록 모델은 그 안에서 올바른 답을 끄집어내는 데 더 서툴러집니다 — 이는 컨텍스트에 무엇을 넣는지가 얼마나 공간이 남았는지만큼 중요하다는 것을 의미합니다.2
이는 메모리 설계에 직접 영향을 줍니다: 히스토리 전체를 컨텍스트에 쏟아붓는 것은 공짜가 아니고(윈도우 용량을 채웁니다), 대가가 없는 것도 아닙니다(오래된 정보 더미에 파묻힌, 지금 실제로 관련 있는 한 문장을 찾느라 모델이 더 애를 써야 합니다). 레슨 2에서는 그 누적을 실무에서 어떻게 다룰지 — 히스토리를 잘라내는 법, 요약하는 법을, 무한정 커지도록 두지 않고 다루는 방법을 다룹니다.
'메모리'라는 단어는 사실 은유다
서두의 그 지원 대화로 돌아가 봅시다. '에이전트가 당신의 이름이 Sarah라는 것을 기억한다'라고 말할 때, 정확한 표현은 이렇습니다: 당신의 코드가 완전한 히스토리 —'내 이름은 Sarah'를 담은 그 히스토리를— 그대로 모델에 한 번 더 재전송했고, 모델이 이 요청 안에서 그것을 다시 읽었다는 것입니다. 저장도 없고, 회상도 없고, 오직 재전송만 있습니다.
이것은 말꼬리를 잡는 것이 아닙니다. '메모리는 재전송이 만들어 낸 착각이다'라는 것을 이해하는 일은, 진짜로 '기억하는' 에이전트를 어떻게 설계할지에 직접 영향을 줍니다:
- 히스토리 배열이 무한정 커지면 윈도우는 조만간 가득 차고, 그 위에 컨텍스트 로트까지 겪습니다 — 레슨 2가 푸는 문제입니다.
- 어떤 정보가 여러 세션에 걸쳐(이 하나의 대화 안뿐 아니라) 지속되어야 한다면, messages 배열에 밀어 넣는 것에 기댈 수 없습니다. 그것은 어딘가 외부에 기록되어야 합니다 — 레슨 3이 다루는 외부 메모리입니다.
- 에이전트가 작업 도중에 '내가 어디까지 진행했는지'를 알아야 한다면, 그 진행 상황 역시 컨텍스트 윈도우 안에서 보이는 구조화된 상태여야 하며, 모델이 추측하는 것이 아닙니다 — 레슨 4의 주제입니다.
이 세 갈래는 모두 같은 사실의 서로 다른 따름정리입니다: 모델은 윈도우 안에 있는 것만 압니다. 윈도우 안에 없는 것은 모델에 관한 한 존재하지 않습니다.
정리
- '에이전트가 이전 대화를 기억한다'는 착각이다: 진실은 호스트 애플리케이션이 매 요청마다 전체 히스토리를 다시 묶어 넣고, 모델 자체는 아무것도 저장하지 않는다는 것이다1
- API 호출은 스테이트리스다. 서버는 요청 사이에 세션별 비공개 상태를 보관하지 않으므로, 모든 '메모리'는 클라이언트가 능동적으로 실어 날라야 한다1
- 컨텍스트 윈도우는 이 요청이 실제로 실어 나르는 모든 것을 담는다: 시스템 프롬프트,
messages 안의 모든 메시지(도구 결과, 이미지, 문서 포함), 도구 정의, 그리고 그 턴에 대한 모델 자신의 출력2
- 윈도우에는 크기 상한이 있고, 크다고 자동으로 쓰기 좋은 것은 아니다 — 컨텍스트 로트는 토큰을 많이 쌓을수록 정확도와 회상이 저하됨을 뜻한다2
- '모델은 윈도우 안에 있는 것만 안다'를 파악하는 것은 다음 세 레슨이 푸는 문제로 곧장 이어진다: 히스토리를 어떻게 관리할지, 메모리를 어떻게 외부화할지, 상태를 어떻게 구조화할지
레슨 2: 대화 히스토리 관리: 추가, 잘라내기, 요약 >>