안녕하세요, 자바파커입니다.
문서 100페이지를 통째로 넣었습니다. 그런데 모델이 가운데 내용을 못 찾습니다.
앞부분을 물으면 잘 답합니다. 뒷부분도 잘 답합니다. 그런데 중간쯤에 있던 문장을 물으면 "문서에 없다"고 합니다. 분명히 넣었는데도요.
결론부터 말씀드리면 — 컨텍스트에 넣는 것과 모델이 실제로 쓰는 것은 다릅니다. 정확도는 정보가 어디에 있느냐에 따라 달라지고, 그 모양이 U자입니다. 앞과 뒤는 잘 보고 가운데가 약합니다.
LLM 토큰 편에서 "200K 컨텍스트는 글자가 아니라 토큰 200,000개"라고 말씀드렸는데, 오늘은 그 200,000개를 모델이 다 똑같이 보지는 않는다는 이야기입니다.
컨텍스트 윈도우는 작업대다
컨텍스트 윈도우는 모델이 한 번에 올려놓고 볼 수 있는 토큰의 총량입니다. 시스템 프롬프트, 대화 기록, 붙여넣은 문서, 그리고 모델이 생성할 답변까지 전부 여기 들어갑니다.
두 가지가 자주 오해됩니다.
① 기억이 아니라 작업대입니다. 모델은 이전 대화를 "기억"하지 않습니다. 매 요청마다 지금까지의 대화 전체를 다시 통째로 읽습니다. 대화가 길어질수록 매번 읽는 양이 늘어나는 구조입니다.
② 입력만 세는 게 아닙니다. 출력도 같은 창을 씁니다. 입력으로 창을 거의 채우면 답변할 자리가 남지 않습니다.
U자 곡선 — Lost in the Middle
여기서부터가 본론입니다.
스탠퍼드 연구진의 Lost in the Middle 실험은 단순합니다. 문서 여러 개를 컨텍스트에 넣고 질문하는데, 정답이 든 문서의 위치만 바꿔 가며 정확도를 잽니다.
결과가 U자였습니다.
정확도
▲
│ ● ●
│ ● ●
│ ● ●
│ ● ● ● ● ● ●
└──────────────────────────────────────────▶
맨 앞 가운데 맨 뒤 정답 위치정답이 맨 앞이나 맨 뒤에 있을 때 가장 정확하고, 가운데에 있을 때 가장 부정확합니다. 논문에서는 위치만 바꿨는데 정확도가 30% 넘게 떨어지는 구간이 나왔습니다.
내용도, 질문도, 문서 개수도 그대로입니다. 위치만 바뀌었습니다.
광고된 길이 ≠ 실제로 쓸 수 있는 길이
"1M 토큰 지원"이라고 하면 100만 토큰을 다 쓸 수 있을 것 같지만, 실제로는 다릅니다.
RULER 벤치마크는 단순 검색이 아니라 여러 정보를 찾아 엮어야 하는 과제로 롱컨텍스트 모델을 평가했습니다. 17개 모델을 테스트했는데, 전부 입력이 길어질수록 회수율이 떨어졌습니다. 여기서 나온 개념이 유효 컨텍스트 길이(effective context length) 입니다 — 광고된 길이보다 짧습니다.
이후 LongBench v2, HELMET 같은 후속 벤치마크에서도 같은 경향이 이어집니다. 최신 모델들이 많이 개선된 건 맞지만, "넣으면 다 본다"는 아직 아닙니다.
특히 갈리는 지점이 있습니다.
| 과제 유형 | 긴 컨텍스트에서 |
|---|---|
| 한 문장 찾기 (needle in a haystack) | 비교적 잘 버팀 |
| 여러 곳을 찾아 엮기 (multi-hop) | 확연히 떨어짐 |
| 전체를 훑고 추론하기 | 가장 많이 떨어짐 |
"바늘 찾기 테스트는 100% 통과했다"는 홍보 문구를 조심해야 하는 이유입니다. 실무는 대개 바늘 하나 찾기가 아니라 여러 개를 엮는 일입니다.
왜 이런 일이 생기나
정확한 원인은 아직 연구 중이고 여러 설명이 겹쳐 있습니다. 다만 관측은 일관됩니다.
① 학습 데이터의 위치 편향. 사람이 쓴 글은 중요한 내용이 앞(요약·서론)이나 뒤(결론)에 오는 경향이 있습니다. 모델은 그 분포를 학습했습니다.
② 어텐션이 얇게 퍼집니다. 토큰이 많아질수록 각 토큰에 배분되는 주의가 옅어집니다. 문장 100개 중 하나를 고르는 것과 10,000개 중 하나를 고르는 것은 다릅니다.
③ 위치 인코딩의 외삽 한계. 학습할 때 본 길이보다 훨씬 긴 입력에서는 위치 정보가 약해집니다. 롱컨텍스트 모델들이 이 부분을 계속 개선하고 있습니다.
셋 다 "모델이 게으르다"가 아니라 구조적 성질입니다. 프롬프트로 "빠짐없이 읽어라"라고 써도 크게 달라지지 않습니다.
그래서 무엇을 바꿔야 하나
① 중요한 것을 끝에 두세요. 가장 싸고 효과가 확실한 조치입니다. 질문·지시문은 문서 뒤에 붙이는 게 앞에 두는 것보다 대체로 낫습니다. 시스템 프롬프트처럼 고정된 내용은 앞에 두고요.
② 다 넣지 말고 골라 넣으세요. 100페이지를 넣고 "찾아봐"라고 하는 것보다, 관련된 5페이지만 넣는 쪽이 정확합니다. 이게 컨텍스트가 커졌는데도 RAG를 계속 쓰는 이유입니다. 넣을 수 있느냐와 잘 쓰느냐는 다른 문제입니다.
③ 길면 쪼개세요. 여러 곳을 엮어야 하는 과제라면 한 번에 던지지 말고, 부분별로 요약한 뒤 그 요약들을 다시 넘기는 편이 안정적입니다.
④ 비용과 지연도 같이 보세요. 컨텍스트가 길면 매 요청마다 그만큼 다시 읽습니다. 요금이 오르고 첫 응답까지 걸리는 시간도 늘어납니다. 고정된 앞부분은 프롬프트 캐싱으로 덜어낼 수 있습니다.
확인하는 법
의심되면 직접 재 보시면 됩니다. 방법은 단순합니다.
- 확인용 문장 하나를 정합니다 (예:
사내 VPN 비밀번호는 alpaca-7 이다) - 긴 문서의 맨 앞 / 가운데 / 맨 뒤에 각각 넣어 세 벌을 만듭니다
- 같은 질문을 던지고 답이 갈리는지 봅니다
가운데 버전만 틀린다면 그게 이 문제입니다. 문서 길이를 2배, 4배로 늘려 가며 어디서부터 무너지는지도 확인해 두면, 그 길이가 여러분 서비스의 실질적인 상한입니다.
자주 묻는 질문 (FAQ)
Q. 컨텍스트가 1M까지 커졌으면 RAG는 이제 필요 없지 않나요? A. 아닙니다. 세 가지가 남습니다. 정확도 — 다 넣으면 가운데를 놓칩니다. 비용 — 매 요청마다 전부 다시 읽습니다. 지연 — 길수록 첫 응답이 늦습니다. RAG는 "넣을 수 없어서" 쓰는 게 아니라 "골라 넣는 게 더 나아서" 씁니다.
Q. 프롬프트에 "전체를 빠짐없이 읽어라"라고 쓰면 되나요? A. 효과가 크지 않습니다. 위 세 가지는 지시로 바뀌는 성질이 아닙니다. 지시문을 다듬는 것보다 위치를 바꾸고 양을 줄이는 쪽이 훨씬 확실합니다.
Q. 대화가 길어지면 왜 느려지고 비싸지나요? A. 모델이 기억하지 못하기 때문입니다. 매 요청마다 대화 전체를 다시 읽습니다. 대화가 길수록 매번 읽는 양이 늘고, 그만큼 요금과 지연이 함께 늘어납니다. 주기적으로 요약해서 갈아 끼우는 게 정석입니다.
정리
- 컨텍스트 윈도우는 기억이 아니라 작업대다. 출력도 같은 창을 쓴다.
- 정확도는 위치에 따라 U자를 그린다. 앞과 뒤는 잘 보고 가운데가 약하다.
- 광고된 길이 ≠ 유효 길이. 여러 정보를 엮는 과제일수록 더 떨어진다.
- 중요한 건 끝에, 그리고 다 넣지 말고 골라 넣는다.
- 컨텍스트가 커져도 RAG를 쓰는 이유가 여기 있다.
토큰이 어떻게 세어지는지는 LLM 토큰 편에, 골라 넣는 방법은 RAG 편에 정리해 뒀습니다.