티스토리 뷰
Claude Code로 긴 작업을 하다 보면 이상한 경험을 합니다. 분명 대화 초반에 "테스트 코드는 JUnit5로 작성해줘"라고 말했는데, 한참 뒤에 보면 JUnit4 스타일로 작성하고 있습니다. "아까 말했잖아"라고 하면 "죄송합니다"하고 고치긴 하는데, 왜 까먹은 걸까요?
1편에서 LLM이 다음 토큰을 예측하는 방식으로 동작한다고 했습니다. 이번 편에서는 그 예측을 할 때 "어디를 보고 예측하는가"에 대한 이야기입니다.
1. 컨텍스트 윈도우 - 오픈북 시험의 페이지 제한
LLM은 대화를 "기억"하지 않습니다. 매번 대화 전체를 처음부터 다시 읽습니다.
이게 직관적이지 않을 수 있는데, 비유하자면 이렇습니다. 오픈북 시험인데 펼쳐놓을 수 있는 페이지 수가 정해져 있다고 생각하면 됩니다. 시스템 프롬프트, CLAUDE.md, 이전 대화 내용, 도구 실행 결과, 그리고 방금 입력한 질문까지 전부 이 페이지 안에 들어가야 합니다.
Claude의 경우 컨텍스트 윈도우가 200K 토큰 정도인데, 많아 보이지만 실제로는 금방 찹니다. 코드 파일 몇 개 읽고, 도구 실행 결과가 쌓이고, 대화가 길어지면 순식간에 한계에 도달합니다. 특히 1편에서 이야기했듯이 한글은 토큰을 더 많이 소모하니까 체감상 더 빨리 차죠.
중요한 건, 컨텍스트 윈도우가 꽉 차면 오래된 대화 내용부터 잘려나간다는 겁니다. Claude Code에서 대화가 길어지면 자동으로 이전 내용을 요약(compact)하는 이유가 이겁니다. 전체를 다 들고 있을 수 없으니까 요약해서 공간을 확보하는 거죠.
그래서 대화 초반에 한 지시가 사라지는 겁니다. JUnit5로 써달라고 한 게 compact 과정에서 빠져버린 거죠. 까먹은 게 아니라 애초에 더 이상 볼 수 없는 겁니다.
2. 어텐션 - 모든 텍스트를 동등하게 보지 않는다
컨텍스트 윈도우 안에 있다고 해서 모든 내용에 같은 주의를 기울이는 건 아닙니다. 여기서 어텐션 메커니즘이라는 개념이 나옵니다.
수학적으로 들어가면 복잡하지만, 활용 관점에서 알아야 할 건 하나입니다. LLM은 현재 생성하는 토큰과 관련성이 높은 부분에 더 집중하고, 관련이 적은 부분은 상대적으로 덜 본다는 것.
문제는 이 "관련성 판단"이 완벽하지 않다는 겁니다. 특히 길이가 길어지면 중간에 있는 정보를 놓치는 경향이 있습니다.
3. Lost in the Middle - 정보 배치가 결과를 바꾼다
동작원리에 대해 학습을 하던중에 발견한 논문인데요, 2023년 스탠포드 연구팀이 재밌는 실험을 했습니다. 같은 정보를 입력의 앞부분, 중간, 뒷부분에 각각 배치했을 때 LLM이 얼마나 잘 활용하는지 비교한 건데, 결과가 꽤 명확했습니다.
앞부분과 뒷부분에 있는 정보는 잘 활용하는 반면, 중간에 묻힌 정보는 눈에 띄게 놓치는 비율이 높았습니다. 이걸 "Lost in the Middle" 현상이라고 부릅니다.
사람도 비슷하긴 합니다. 긴 문서를 읽을 때 처음과 끝은 기억이 잘 나는데 중간은 흐릿하잖아요. LLM도 마찬가지인데 차이점이 있습니다. 사람은 중요하다고 판단하면 중간이어도 집중하지만, LLM은 위치 자체가 영향을 줍니다.
이걸 알면 실무에서 바로 적용할 수 있는 게 있습니다.
CLAUDE.md를 작성할 때
- 가장 중요한 규칙은 파일 상단에 배치
- 덜 중요한 참고사항은 중간에
- 자주 어기는 규칙이 있다면 하단에 한 번 더 반복
프롬프트를 작성할 때
- 핵심 지시사항을 맨 앞에
- 배경 설명은 중간에
- 출력 형식이나 제약조건은 맨 뒤에
이전에 쓴 .claude 폴더 가이드에서 CLAUDE.md를 200줄 이내로 유지하라고 했는데, 단순히 "길면 안 좋다"가 아니라 이런 원리가 있기 때문입니다. 길어질수록 중간에 있는 지시사항이 묻힐 확률이 올라갑니다.
4. 멀티턴 대화의 진실 - "기억"이 아니라 "다시 읽기"
많은 사람들이 AI와 대화할 때 "기억하고 있겠지"라고 생각합니다. 하지만 실제로는 매 턴마다 전체 대화 히스토리를 입력으로 다시 넣는 구조입니다.
[1턴] 시스템 프롬프트 + 사용자 질문 → 응답
[2턴] 시스템 프롬프트 + 사용자 질문 + 응답 + 사용자 질문2 → 응답2
[3턴] 시스템 프롬프트 + 사용자 질문 + 응답 + 사용자 질문2 + 응답2 + 사용자 질문3 → 응답3
...
턴이 지날수록 입력이 계속 길어지는 구조입니다. 그래서 대화가 길어지면
- 컨텍스트 윈도우가 채워져서 오래된 내용이 잘린다
- 잘리지 않더라도 중간에 있는 내용은 어텐션이 약해진다
- 결과적으로 초반 지시를 "까먹는" 것처럼 보인다
Claude Code에서 Cmd/Ctrl + Shift + K로 대화를 초기화하거나, 작업 단위로 새 대화를 시작하는 게 좋은 이유가 여기에 있습니다. 대화를 짧게 유지할수록 LLM이 모든 맥락을 제대로 참조할 수 있습니다.
5. 에이전트 설계에서 이게 왜 중요한가
1편에서 LLM이 "다음 토큰 예측기"라고 했는데, 이번 편의 내용을 합치면 이렇게 됩니다. "제한된 범위 안에서, 위치에 따라 다른 주의력으로 읽고, 다음 토큰을 예측하는 것."
이걸 이해하면 하네스 엔지니어링에서 왜 이런 패턴들이 나오는지 납득이 됩니다.
| 하네스 설계 패턴 | 대응하는 LLM 특성 |
|---|---|
| 작업을 서브 에이전트에게 분할 | 컨텍스트 윈도우 한계 → 각 에이전트가 적은 컨텍스트로 집중 |
| CLAUDE.md를 간결하게 유지 | 길수록 중간 정보 손실 증가 |
| 중요한 규칙을 시스템 프롬프트에 배치 | 시스템 프롬프트는 항상 컨텍스트 앞쪽에 위치 |
| 대화를 주기적으로 초기화 | 오래된 컨텍스트 누적 방지 |
| 도구 실행 결과를 요약해서 전달 | 불필요한 토큰 소모 방지 |
Oh-My-Claudecode(OMC)의 서브 에이전트 구조가 대표적입니다. 메인 에이전트가 모든 작업을 다 하면 컨텍스트가 금방 차지만, 파일 탐색은 explore 에이전트에게, 코드 리뷰는 reviewer 에이전트에게 맡기면 각 에이전트가 깨끗한 컨텍스트에서 작업할 수 있습니다. 이전에 쓴 OMC 글에서 "컨텍스트 절약"이라고 소개했던 기능의 원리가 바로 요 부분입니다!
정리
컨텍스트 윈도우와 어텐션을 이해하면 AI 활용의 많은 "왜?" 또는 "아니.."가 풀립니다.
- 왜 긴 대화에서 앞의 지시를 까먹을까? → 컨텍스트가 잘리거나 어텐션이 약해져서
- 왜 CLAUDE.md를 짧게 써야 할까? → 길수록 중간 정보가 묻혀서
- 왜 서브 에이전트로 나눠서 작업할까? → 각 에이전트가 적은 컨텍스트에 집중하도록
- 왜 중요한 정보를 앞뒤에 배치할까? → Lost in the Middle 현상 때문에
다음 편에서는 Tool Use와 에이전트 루프를 다뤄보려고합니다. LLM이 도구를 쓰는 게 아니라 "도구를 써달라고 텍스트를 출력하는 것"이라는, 에이전트 동작의 핵심 원리에 대한 이야기입니다.
참고 자료
'AI' 카테고리의 다른 글
| 작은 자동화가 주는 큰 편함: CLAUDE.md 자동 생성 플러그인 만들기 (0) | 2026.04.21 |
|---|---|
| [LLM 동작원리 3편] Tool Use와 에이전트 루프: AI가 도구를 쓰는 진짜 방식 (0) | 2026.04.10 |
| [LLM 동작원리 1편] LLM은 어떻게 대답하는가: 다음 토큰 예측의 이해 (1) | 2026.04.09 |
| .claude/ 폴더 구조 완벽 가이드: 프로젝트 설정부터 고급 활용까지 알아보기 (1) | 2026.04.03 |
| Anthropic Courses: Claude 101 (0) | 2026.03.26 |
- Total
- Today
- Yesterday
- Servlet
- Python
- Delete
- AI
- Claude
- Controller
- 자바
- JavaScript
- jquery
- JDBC
- 파이썬
- JSP
- list
- ArrayList
- CSS
- db
- Java
- 알고리즘
- codeup
- Spring
- oracle
- function
- FOR
- 코딩테스트
- 프로그래머스
- Ajax
- class
- HTML
- Git
- 코드업
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
