
컨텍스트 윈도우란 - AI 기억의 한계가 서비스를 망치는 방식, 20년차 개발자의 설계 실수 고백
컨텍스트 윈도우는 AI가 단일 요청에서 처리할 수 있는 최대 토큰 수다. 이 한도를 넘으면 AI는 앞의 내용을 기억하지 못한 채 답변을 생성한다. 대화가 길어지거나 문서가 클 때 AI가 갑자기 엉뚱한 답변을 내놓거나 앞에서 한 말을 기억 못하는 이유가 여기에 있다. 이것을 이해하지 못하고 AI 서비스를 만들면, 사용자는 AI가 멍청하다고 느끼고 개발자는 왜 그런지 한참을 헤매게 된다.
컨텍스트 윈도우, 금붕어 기억력이 아닌 칠판 크기의 문제
AI 기억력을 금붕어에 비유하는 사람들이 있는데 틀린 비유다. 더 정확한 건 칠판이다. 칠판 크기가 컨텍스트 윈도우다. 칠판에 들어가는 내용이 많아질수록 오래된 내용은 지워야 새 내용을 쓸 수 있다. 칠판이 꽉 차도 지우지 않으면? 더 이상 쓸 수 없거나 오류가 난다. 칠판 안에 있는 내용은 완벽하게 기억한다. 칠판 밖으로 나간 내용은 존재 자체를 모른다.
현장에서 이걸 처음 실감한 건 고객 상담 챗봇을 만들었을 때다. 대화가 30분을 넘어가니까 앞에서 이미 확인한 주문 번호를 다시 물어보는 현상이 나타났다. 사용자 불만이 터졌다. 원인을 찾는 데 꽤 걸렸다. 결국 대화 히스토리가 컨텍스트 한도를 초과해서 앞부분이 잘려나간 것이었다. AI는 주문 번호를 들은 적이 없다고 인식하고 있었다.
이 문제의 장점은 명확한 한계가 있다는 것이다. 한계가 명확하면 설계할 수 있다. 단점은 사용자 입장에서 이 한계가 전혀 보이지 않는다는 점이다. 갑자기 맥락을 잃는 AI는 사용자 신뢰를 한번에 무너뜨린다.
모델별 컨텍스트 윈도우 크기, 창문 크기가 다 다르다
모델마다 창문 크기가 다르다. 창문이 클수록 더 긴 문서를, 더 긴 대화를, 더 많은 예시를 한 번에 처리할 수 있다. 하지만 창문이 크면 비용도 크다. 무조건 큰 게 좋은 게 아니라 용도에 맞는 크기를 선택해야 한다.
2025년 기준으로 Claude는 최대 20만 토큰, Gemini 1.5 Pro는 최대 100만 토큰, GPT-4o는 12만 8000토큰 수준이다. 이 숫자들은 계속 커지고 있다. 하지만 크다고 무조건 다 채워 쓰면 비용이 폭발한다. 실제로 필요한 만큼만 쓰는 설계가 중요하다.
# 컨텍스트 윈도우 관리 유틸리티
import tiktoken
from typing import List, Dict
class ContextWindowManager:
def __init__(self, model: str = "gpt-4o", max_tokens: int = 128000, reserve_output: int = 2000):
self.model = model
self.max_tokens = max_tokens
self.reserve_output = reserve_output
self.available_tokens = max_tokens - reserve_output
try:
self.enc = tiktoken.encoding_for_model(model)
except:
self.enc = tiktoken.get_encoding("cl100k_base")
def count_tokens(self, text: str) -> int:
return len(self.enc.encode(text))
def fit_messages(self, messages: List[Dict], system_prompt: str = "") -> List[Dict]:
system_tokens = self.count_tokens(system_prompt)
remaining = self.available_tokens - system_tokens
fitted = []
# 최신 메시지부터 역순으로 추가
for msg in reversed(messages):
msg_tokens = self.count_tokens(msg.get("content", ""))
if remaining - msg_tokens < 0:
break
fitted.insert(0, msg)
remaining -= msg_tokens
dropped = len(messages) - len(fitted)
if dropped > 0:
print(f"경고: 컨텍스트 초과로 {dropped}개 메시지 제거됨")
return fitted
# 사용 예시
manager = ContextWindowManager(model="gpt-4o", max_tokens=128000)
messages = [
{"role": "user", "content": "안녕하세요"},
{"role": "assistant", "content": "안녕하세요! 무엇을 도와드릴까요?"},
{"role": "user", "content": "주문 번호 12345 확인해주세요"},
{"role": "assistant", "content": "주문 12345를 확인했습니다."},
]
system = "당신은 친절한 고객 서비스 상담원입니다."
fitted = manager.fit_messages(messages, system)
print(f"원본 메시지: {len(messages)}개, 최적화 후: {len(fitted)}개")
Lost in the Middle 현상, 창문 가운데는 AI가 잘 못 본다
컨텍스트 윈도우의 또 다른 함정이 있다. 창문이 크다고 해서 창문 안의 모든 내용을 동등하게 처리하지 않는다는 것이다. 연구에 따르면 LLM은 컨텍스트의 맨 앞과 맨 뒤 내용은 잘 기억하지만 가운데 내용은 상대적으로 덜 활용하는 경향이 있다. "Lost in the Middle" 현상이라고 부른다.
이걸 실무에서 처음 겪었을 때는 황당했다. 분명히 컨텍스트 안에 답이 있는데 AI가 틀린 답을 냈다. 확인해보니 정답이 되는 정보가 긴 컨텍스트의 한가운데 파묻혀 있었다. 앞뒤로 이동시켰더니 정답률이 올라갔다. 컨텍스트의 배치도 설계 요소라는 걸 그때 배웠다.
중요한 정보는 시스템 프롬프트 쪽(앞)이나 사용자 메시지 바로 앞(뒤)에 배치하는 게 좋다. 덜 중요한 배경 정보는 가운데에 넣는다.
긴 문서 처리 전략, 청킹과 RAG
컨텍스트 윈도우 한계를 극복하는 가장 현실적인 방법은 청킹과 RAG다. 청킹은 긴 문서를 작은 조각으로 나누는 것이다. RAG는 Retrieval-Augmented Generation으로, 질문과 관련 있는 조각만 검색해서 컨텍스트에 넣는 방식이다. 100페이지 문서 전체를 넣는 게 아니라 질문에 답할 수 있는 2~3개 조각만 찾아서 넣는다.
이 방식으로 컨텍스트 크기를 현실적으로 유지하면서도 큰 문서를 다룰 수 있다. 비용도 줄고, 답변 품질도 오히려 올라가는 경우가 많다. 관련 없는 내용이 줄어드니까 AI가 핵심에 집중할 수 있어서다.
# 간단한 청킹 유틸리티
import tiktoken
def chunk_text(text: str, chunk_size: int = 500, overlap: int = 50, model: str = "gpt-4o") -> list:
try:
enc = tiktoken.encoding_for_model(model)
except:
enc = tiktoken.get_encoding("cl100k_base")
tokens = enc.encode(text)
chunks = []
start = 0
while start < len(tokens):
end = min(start + chunk_size, len(tokens))
chunk_tokens = tokens[start:end]
chunk_text = enc.decode(chunk_tokens)
chunks.append({
"text": chunk_text,
"token_count": len(chunk_tokens),
"start_token": start,
"end_token": end
})
start += chunk_size - overlap
return chunks
# 사용 예시
long_text = "긴 문서 내용이 여기에 들어갑니다. " * 200
chunks = chunk_text(long_text, chunk_size=500, overlap=50)
print(f"전체 청크 수: {len(chunks)}")
for i, chunk in enumerate(chunks[:3]):
print(f"청크 {i+1}: {chunk['token_count']}토큰")
컨텍스트 윈도우를 이해하기 전과 후의 차이
컨텍스트 윈도우 개념 없이 AI 서비스를 만들면 이런 오류를 만나게 된다. "왜 앞에서 한 말을 기억 못하지?", "왜 긴 문서에서 엉뚱한 부분 얘기하지?", "왜 대화가 길어질수록 답이 이상해지지?". 이 모든 게 컨텍스트 윈도우로 설명된다.
이해하고 나서는 설계 자체가 달라진다. 대화 히스토리 관리 전략을 처음부터 세우고, 중요한 정보는 컨텍스트의 앞뒤에 배치하고, 긴 문서는 반드시 청킹 전략을 쓴다. 컨텍스트 한도를 모니터링하는 코드를 처음부터 넣는다. 이런 습관들이 쌓여서 안정적인 AI 서비스가 만들어진다. 컨텍스트 윈도우는 제약이지만, 이 제약을 이해하는 사람이 제약 없이 짜는 사람보다 훨씬 좋은 서비스를 만든다.
출처 및 참고 자료
- Lost in the Middle 연구 논문: https://arxiv.org/abs/2307.03172
- Anthropic 컨텍스트 윈도우 문서: https://docs.anthropic.com/ko/docs/about-claude/models
- OpenAI 컨텍스트 길이 가이드: https://platform.openai.com/docs/guides/context-length
- LangChain 청킹 전략: https://python.langchain.com/docs/how_to/character_text_splitter
- RAG 패턴 가이드: https://www.anthropic.com/research/retrieval-augmented-generation