본문 바로가기
카테고리 없음

컨텍스트 윈도우란 - AI 기억의 한계가 서비스를 망치는 방식 설계 실수 고백

by BOOST YOUR INFORMATION 2026. 5. 13.

컨텍스트 윈도우 AI 기억의 한계가 서비스를 망치는 방식 개발자의 설계 실수 고백 참조 이미지
AI 기억의 한계가 서비스를 망치는 방식

 

컨텍스트 윈도우란 - 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

소개 및 문의 · 개인정보처리방침 · 면책조항

© 2026 ⚡ 정보 부스터 🚀