3장. 컨텍스트 엔지니어링
학습 목표
- 컨텍스트 창 예산과 컨텍스트 부패의 의미를 설명하고, 요청 하나의 예산표를 짠다.
- 질문에서 필요한 정보를 거꾸로 따져 필요한 자료만 골라 넣는다.
- 긴 문서와 질문을 품질이 높아지는 순서로 배치하고, 문서에 출처와 버전을 붙인다.
- 긴 문서에서 근거를 먼저 인용하게 하고, 인용이 결론을 충분히 뒷받침하는지 확인한다.
- 대화 요약과 압축, 검색 증강의 원리를 설명하고, 검색 실패와 답변 실패를 나눠 진단한다.
- 신뢰할 수 없는 외부 내용을 지시와 분리해 배치한다.
들어가며
한 컨설팅 회사의 분석가가 연간 보고서 다섯 편을 통째로 넣고 “올해 업계의 핵심 변화 세 가지”를 물었습니다. 컨텍스트 창은 충분히 컸고 요청은 오류 없이 처리되었습니다. 그런데 답에 나온 세 가지 중 하나는 세 번째 보고서의 부록에 딸린 각주 한 줄을 과장한 것이었고, 정작 다섯 보고서가 공통으로 강조한 변화는 빠져 있었습니다. 분석가는 “다 넣었는데 왜 놓쳤을까”라고 물었습니다. 답은 질문 안에 있습니다. 다 넣었기 때문에 놓친 것입니다. 모델이 각주를 지어낸 것은 아닙니다. 무엇이 중요한지 가려낼 단서 없이 수십만 토큰을 받았고, 넓은 창 안에서 관련 없는 각주가 핵심 신호와 같은 자리를 놓고 경쟁했을 뿐입니다.
이 장은 지시문 바깥, 곧 모델이 한 번에 보는 모든 것을 다룹니다. 컨텍스트가 왜 한정된 자원인지에서 시작해 예산표를 짜는 법, 필요한 정보만 고르는 법, 문서의 메타데이터와 배치 순서, 인용을 먼저 받는 법과 인용 기능, 검색 증강의 원리와 실패 진단, 대화 요약과 압축, 오래 일하는 에이전트의 전략, 프롬프트 캐싱, 신뢰할 수 없는 내용의 자리를 차례로 봅니다. 깊이 읽기에서는 긴 창과 검색 사이의 선택, 도구 설계, 대화 상태를 서버에 맡길 때의 주의점을 다룹니다.
핵심 개념
컨텍스트는 책상 위 공간이다
책상이 넓으면 서류를 많이 펼칠 수 있지만, 서류가 많을수록 지금 필요한 한 장을 찾기 어려워집니다. Anthropic 문서는 컨텍스트 창(context window)을 응답을 만들 때 참조하는 모든 텍스트와 응답 자체를 담는, 학습 데이터와 구분되는 “작업 기억”이라 설명하고, 크다고 자동으로 좋아지지는 않는다고 강조합니다. 출력을 같은 창에서 세는지는 벤더와 모델마다 다릅니다. 토큰이 늘수록 정확도와 회상 능력이 떨어지는 컨텍스트 부패(context rot) 때문입니다.
Anthropic의 컨텍스트 엔지니어링 글은 이를 주의력 예산으로 설명합니다. 트랜스포머에서는 모든 토큰이 다른 모든 토큰과 관계를 맺어 토큰이 n개면 관계는 n²개로 늘고, 새 토큰마다 한정된 주의력을 나눠 씁니다. 그래서 목표는 “원하는 결과를 낼 가능성을 최대로 높이는, 가능한 한 작은 고신호 토큰 집합”, 곧 쓸모 있는 정보가 촘촘한 최소한의 토큰을 찾는 것입니다. 프롬프트 엔지니어링이 지시문을 다듬는 일이라면, 컨텍스트 엔지니어링은 모델이 보는 토큰 전체를 매번 골라 담는 일입니다.
참고
컨텍스트 창은 한 번에 읽을 수 있는 양일 뿐, 모델이 아는 지식의 최신성과는 관계가 없습니다. 창이 커져도 학습 이후의 사실은 검색이나 첨부로 줘야 합니다.
컨텍스트 창 예산표
예산을 짜려면 무엇이 창을 차지하는지부터 알아야 합니다. Anthropic 문서에 따르면 시스템 프롬프트, messages 안의 모든 메시지(도구 결과, 이미지, 문서 포함), 도구 정의, 그리고 모델이 그 턴에 생성하는 출력(사고 포함)이 모두 창에 들어갑니다. 프롬프트 캐시로 읽은 토큰도 창을 차지합니다. 캐싱은 요금을 낮출 뿐 창의 자리를 비워 주지 않습니다. 토큰 수는 언어와 표기에 따라 달라지므로, 한국어 자료도 글자 수로 어림하지 말고 토큰 계산 기능으로 실제 입력을 재 봅니다.
| 구성 요소 | 예산 질문 | 줄이는 방법 |
|---|---|---|
| 시스템 지시 | 매 요청 반복되는 고정 비용인가 | 중복 규칙 정리, 캐싱 |
| 도구 정의 | 이번 작업에 필요 없는 도구까지 실렸는가 | 도구 정리, 필요할 때 불러오기 |
| 예시 | 개수가 실험으로 정해졌는가 | 2장의 개수 실험 |
| 문서·검색 결과 | 질문에 답하는 데 필요한 부분인가 | 선별, 발췌 |
| 대화 이력·도구 결과 | 이미 소화한 내용이 남아 있는가 | 요약, 오래된 도구 결과 정리 |
| 출력 여유 | 답과 사고가 들어갈 자리가 남았는가 | max_tokens 설정, 분할 생성 |
출력 여유는 특히 자주 잊힙니다. 창이 넓어도 한 요청의 출력에는 별도의 상한이 있어, Anthropic 문서 기준으로 100만 토큰 창을 가진 최신 모델도 한 요청의 출력은 최대 128k(약 12만 8천) 토큰입니다. 긴 보고서 전체를 다시 쓰게 하면 입력은 들어가도 출력이 상한에 걸려 잘리고, stop_reason은 max_tokens가 됩니다. 공식 문서는 한도를 올리거나 이어서 생성하라고 안내합니다. 결과물이 긴 작업은 처음부터 구간을 나누고, 용어표 같은 공통 기준을 구간마다 함께 넣습니다.
필요한 정보만 골라 넣기
자료를 넣기 전에 질문에서 거꾸로 따져 봅니다.
- 질문을 하위 쟁점으로 쪼갠다. “하반기 가격 전략의 위험 요인”은 원가 변화, 경쟁사 가격, 수요 변화로 나뉜다.
- 쟁점마다 필요한 자료를 적는다. 원가 변화에는 매입 단가표, 경쟁사 가격에는 9월 가격 조사.
- 필수와 보조를 나눈다. 빠지면 답이 틀리는 자료와 있으면 답이 풍부해지는 자료.
- 원문과 발췌 중 고른다. 조항 비교처럼 문구가 중요하면 원문, 배경 설명이면 발췌나 요약.
- 예산이 넘치면 보조 자료부터 뺀다. 뺄 순서를 미리 정해 둔다.
- 근거가 없는 쟁점을 표시한다. 자료가 없는 쟁점은 모델에게도 “자료 없음”으로 알려, 일반 지식으로 메우지 않게 한다.
목적은 비용 절감만이 아닙니다. 다른 제품, 다른 연도, 다른 부서의 자료가 섞인 컨텍스트는 그 자체로 오답의 재료가 됩니다.
문서에 출처·버전·적용 범위를 붙인다
내용만 넣으면 모델은 어떤 문서가 최신이고 어떤 문서가 어디에 적용되는지 알 수 없습니다. 문서마다 메타데이터를 붙입니다.
<documents>
<document index="1">
<source>출장비 규정 제4조</source>
<version>2026-07-01 개정</version>
<applies_to>정규직, 국내 출장</applies_to>
<document_content>{{RULE_4}}</document_content>
</document>
<document index="2">
<source>출장비 규정 제4조</source>
<version>2025-01-01 개정(폐지됨)</version>
<applies_to>2026-06-30 이전 출장 정산에만 적용</applies_to>
<document_content>{{RULE_4_OLD}}</document_content>
</document>
</documents>
Anthropic 가이드는 여러 문서를 넣을 때 각 문서를 <document>로 감싸고 <document_content>, <source> 같은 하위 태그로 내용과 메타데이터를 나누라고 권합니다. 개정일, 시행일, 적용 대상은 모델이 “어느 문서를 따라야 하는가”를 판단하는 근거가 됩니다. 메타데이터가 없으면 같은 조항의 신구 버전이 함께 검색되었을 때 모델이 둘을 섞어 답할 수 있습니다.
메타데이터는 문서끼리 맞지 않을 때 더 중요해집니다. 그냥 “종합하라”고 하면 모델은 충돌을 한 문장에 억지로 녹이거나 한쪽을 조용히 버립니다. 공통으로 확인되는 내용, 수치나 정의가 다른 내용, 한쪽에만 있는 내용을 나눠 정리하게 하고, 해결 규칙을 정해 줍니다. 예를 들어 “같은 조항의 신구 버전이면 질문의 기준일에 시행 중인 쪽을 따른다”입니다. 규칙으로 풀리지 않는 충돌은 해결하지 말고 “충돌: 문서 1과 문서 3이 다름”으로 보고하게 합니다.
긴 문서는 앞에, 질문은 끝에
Anthropic은 2만 토큰이 넘는 긴 입력에서 긴 문서를 질문·지시·예시보다 앞에 두라고 권합니다. 공식 테스트에서 질문을 끝에 두면 특히 복잡한 다중 문서 입력에서 응답 품질이 최대 30%까지 좋아졌습니다. Gemini 가이드도 구체적인 질문을 맨 끝에 두고 “위의 정보를 바탕으로”처럼 앞의 자료를 잇는 표현을 쓰라고 권하며, OpenAI 가이드는 요청마다 바뀌는 맥락을 끝쪽에 두는 구성을 예로 듭니다. 이미지도 같습니다. Anthropic 문서는 이미지를 텍스트보다 먼저 두고, 여러 장이면 “Image 1:”, “Image 2:”처럼 라벨을 붙여 이름으로 가리키라고 안내합니다.
공식 권장은 출발점이지 모든 작업의 법칙이 아닙니다. 핵심 행동 제약은 앞에, 긴 자료는 그 뒤에, 구체적인 질문은 맨 끝에 두는 구성을 기본으로 삼고, 중요한 작업은 배치를 바꾼 버전과 비교해 확인합니다.
인용을 먼저 받는다
긴 문서에서 답을 받을 때 가장 큰 위험은 문서에 없는 내용이 섞이는 것입니다. 공식 가이드는 작업 전에 관련 부분을 먼저 인용하게 하라고 권합니다. 모델은 인용을 고르며 관련 내용에 집중하고, 사람은 인용과 원문을 바로 대조할 수 있습니다. Anthropic의 환각 줄이기 문서는 두 가지를 더합니다. 관련 인용이 없으면 없다고 밝히게 하고, 답을 쓴 뒤 주장마다 뒷받침하는 인용을 찾게 해 찾지 못한 주장은 철회하게 하는 것입니다.
1. 질문과 관련된 원문 문장을 <quotes> 안에 번호를 붙여 그대로 옮긴다.
관련 문장이 없으면 "관련 인용 없음"이라고만 쓴다.
2. <quotes>에 있는 내용만 근거로 <answer>에 답하고, 주장마다 인용 번호를 붙인다.
3. 인용 번호를 붙일 수 없는 주장은 답에서 뺀다.
인용이 있다고 근거가 충분한 것은 아닙니다. 확인할 것이 세 가지 더 있습니다.
| 확인 | 질문 | 방법 |
|---|---|---|
| 일치 | 인용이 원문과 글자 그대로 같은가 | 원문 문자열 검색으로 기계 대조 |
| 관련성 | 인용이 그 주장을 실제로 뒷받침하는가 | 표본을 뽑아 사람이 확인 |
| 충분성 | 예외 조건이나 반대 근거가 빠지지 않았는가 | “이 결론을 뒤집을 조항이 있는가”를 따로 묻기 |
인용 기능과 검색 결과 블록
프롬프트로 인용을 받는 대신 벤더의 인용 기능을 쓸 수도 있습니다. Anthropic의 Citations 기능은 문서에 인용을 켜면 인용한 부분의 텍스트 블록에 원문 위치(일반 텍스트는 문자 위치, PDF는 쪽 번호, 사용자 정의 블록은 블록 번호)를 붙여 돌려줍니다. 인용 없이 나온 주장이 있는지는 따로 확인합니다. 공식 문서가 드는 장점은 셋입니다. 인용된 텍스트(cited_text)는 출력 토큰으로 계산되지 않고, API가 인용을 파싱하므로 제공된 문서를 가리키는 유효한 위치가 보장되며, 자체 평가에서 프롬프트 방식보다 관련성 높은 문장을 인용했다는 것입니다.
일반 텍스트와 PDF는 문장 단위로 인용되고, 녹취록이나 글머리표처럼 단위를 직접 정하려면 사용자 정의 블록으로 넣습니다. 이 기능은 구조화 출력과 함께 쓸 수 없어, 인용을 켠 문서와 output_config.format을 한 요청에 넣으면 400 오류가 납니다. 둘 다 필요하면 호출을 나눕니다.
자체 검색 결과는 Anthropic의 search_result 블록(출처, 제목, 내용)으로 넣으면 웹 검색처럼 출처가 붙은 인용을 받을 수 있습니다. Gemini의 Google 검색 그라운딩은 모델이 검색이 필요한지 스스로 판단해 검색하고, 응답 구간마다 출처 URL을 붙입니다. 자주 갱신되는 공개 정보에는 검색 그라운딩을, 사내 자료에는 사내 검색 결과를 쓰고, 둘을 함께 쓰면 답의 문장마다 어느 쪽 근거인지 구분되게 합니다.
검색 증강의 원리
검색 증강 생성(RAG, retrieval-augmented generation)은 모델이 모르는 자료를 질문 시점에 찾아 넣는 방식입니다. 도서관 사서가 질문을 듣고 관련 책 몇 권만 골라 책상에 올려 주는 모습과 같습니다.
| 단계 | 하는 일 | 흔한 실수 |
|---|---|---|
| 1. 색인 | 문서를 조각(청크)으로 나눠 검색할 수 있게 저장 | 조각이 원래 맥락을 잃음 |
| 2. 질의 생성 | 질문에서 핵심어와 조건을 뽑음 | 질문 원문을 그대로 검색 |
| 3. 검색 | 저장소에서 후보 조각을 찾음 | 의미 검색만 써서 정확한 문자열을 놓침 |
| 4. 재정렬·선별 | 관련도로 다시 줄 세워 상위 몇 개만 남김 | 창에 여유가 있다고 모두 넣기 |
| 5. 배치 | 출처 태그를 붙여 앞쪽에, 질문은 끝에 | 문서 경계 없이 이어 붙이기 |
| 6. 생성 | 인용을 먼저 받고 답하게 함 | 근거 표시 없이 답하게 하기 |
Anthropic의 맥락 검색(Contextual Retrieval) 글은 1단계의 문제를 짚습니다. 문서를 자르면 “매출이 전 분기보다 3% 늘었다” 같은 조각이 어느 회사, 어느 기간의 이야기인지 잃어버립니다. 해결책은 조각마다 문서 전체를 참고한 짧은 설명(보통 50~100토큰)을 붙여 임베딩하고, 같은 텍스트로 BM25 색인도 만드는 것입니다. 임베딩 검색은 뜻이 비슷한 글에 강하지만 오류 코드나 모델명처럼 글자가 정확히 같아야 하는 검색어에 약하고, 단어 일치 기반의 BM25가 그 약점을 메웁니다. 글의 실험에서 검색 실패율은 맥락 임베딩만으로 35%, BM25를 더하면 49%, 재정렬까지 더하면 67% 줄었습니다.
모든 문제에 검색이 필요한 것도 아닙니다. 같은 글은 지식 베이스가 20만 토큰보다 작다면 검색 단계를 만들지 않고 자료 전부를 넣은 뒤 프롬프트 캐싱으로 비용과 지연을 줄여도 된다고 말합니다. 자료가 작다면 가장 단순한 방법이 가장 좋은 방법일 수 있습니다.
검색 실패와 답변 실패를 나눠 진단한다
RAG가 틀린 답을 냈을 때 프롬프트부터 고치는 것은 흔한 실수입니다. 먼저 어느 단계에서 실패했는지 가릅니다.
- 정답 근거가 저장소에 있었는가. 없다면 자료 문제다.
- 검색 결과 상위에 정답 근거가 있었는가. 없다면 검색 문제다. 질의 생성, 색인, 검색 방식을 고친다.
- 근거가 컨텍스트에 들어갔는가. 재정렬이나 선별에서 잘렸다면 선별 기준을 고친다.
- 근거가 들어갔는데도 답이 틀렸는가. 이때 비로소 생성 단계, 곧 지시·배치·인용 방식을 고친다.
이 판별에는 질문별로 정답의 근거가 되는 문서를 미리 짝지어 둔 평가 세트가 필요합니다. 5장에서 다루는 평가 세트의 쓰임 하나가 바로 이것입니다.
대화 요약과 압축
대화가 길어지면 이력을 줄여야 합니다. 가장 흔한 방법은 앞부분을 요약하는 것이지만, 요약은 세부 문구를 잃습니다. 특히 요약을 여러 번 거치면 수치, 날짜, 조건이 “적정 수준”, “가까운 시일” 같은 표현으로 뭉개집니다. 그래서 요약을 “줄거리”가 아니라 “업무 상태 기록”으로 설계합니다.
<conversation_state>
확정된 조건: 납품 수량 1,200개, 납기 11월 14일, 포장은 개별 비닐
미해결 질문: 로고 인쇄 색상(고객이 시안 확인 후 회신 예정)
결정 이력: 10월 20일 단가 협의 완료(견적서 Q-2026-118)
다음 행동: 시안 회신이 오면 인쇄 사양 확정
</conversation_state>
확정된 값은 원래 표현 그대로 남기고, 결정과 제안을 구분하고, 각 항목이 어디서 나왔는지 되짚을 수 있게 합니다. 대화의 흐름은 최근 몇 턴을 원문으로 남겨 유지합니다.
벤더의 기능을 쓸 수도 있습니다. Anthropic은 서버 측 압축(compaction)을 베타로 제공해, 오래된 턴을 모델이 쓴 요약으로 바꾸고 대화를 이어 가게 합니다. 기본 요약이 필요한 정보를 빠뜨리면 직접 요약 지시를 쓰고, 더 세밀하게는 컨텍스트 편집 기능으로 오래된 도구 결과나 사고 블록을 규칙에 따라 지웁니다. 무엇을 반드시 남길지는 업무 담당자가 정합니다.
오래 일하는 에이전트의 컨텍스트 전략
몇 시간씩 도구를 호출하는 에이전트는 컨텍스트가 금방 찹니다. Anthropic 글이 소개하는 기법과 어울리는 상황은 다음과 같습니다.
| 기법 | 하는 일 | 어울리는 작업 |
|---|---|---|
| 압축 | 창이 거의 찼을 때 요약으로 새로 시작 | 주고받기가 많고 흐름이 중요한 작업 |
| 도구 결과 정리 | 이미 반영한 예전 도구 결과의 원문을 지움 | 가장 안전하고 가벼운 압축 |
| 구조화된 메모 | 진행 상황을 창 밖의 메모에 적어 두고 나중에 불러와 읽음 | 단계가 뚜렷한 장기 작업 |
| 하위 에이전트 | 집중된 작업을 깨끗한 창의 하위 에이전트에 맡기고 압축된 요약(대개 1,000~2,000토큰)만 받음 | 병렬 탐색이 도움이 되는 조사·분석 |
| 적시 로딩 | 파일 경로, 저장된 질의, 링크 같은 가벼운 식별자만 들고 있다가 필요할 때 도구로 불러옴 | 자료가 크고 자주 바뀌는 작업 |
적시 로딩은 느리지만 낡은 색인 문제를 피하고 컨텍스트를 가볍게 유지합니다. 일부 자료를 미리 넣고 나머지는 필요할 때 찾게 하는 혼합 방식도 있습니다.
프롬프트 캐싱과 배치
프롬프트 캐싱은 요청마다 반복되는 앞부분을 저장해 두고 다음 요청에서 다시 쓰는 기능입니다. 핵심은 앞부분이 글자 하나까지 같아야 한다는 점입니다. Anthropic은 tools, system, messages 순서로 앞부분을 만들고, 캐시 지점까지 100% 동일해야 적중합니다. OpenAI도 지원 모델에서 캐싱을 기본으로 켜 두며 렌더링된 앞부분 전체가 일치해야 재사용합니다.
| 원칙 | 이유 |
|---|---|
| 고정 내용(도구 정의, 시스템 지시, 참고 자료, 예시)을 앞에 | 요청마다 같은 앞부분이 생긴다 |
| 바뀌는 내용(요청 시각, 사용자별 정보, 질문)을 뒤에 | 바뀌는 값이 앞에 있으면 그 뒤가 모두 새로 계산된다 |
| 도구 정의를 자주 바꾸지 않기 | Anthropic에서는 도구 정의가 바뀌면 캐시 전체가 무효다 |
| 사용량 필드로 적중 확인 | 너무 짧은 프롬프트는 오류 없이 캐시되지 않는다 |
비용 구조도 알아 둡니다. Anthropic 문서 기준으로 캐시 쓰기는 기본 입력 가격보다 조금 비싸고(5분 캐시 1.25배), 캐시 읽기는 훨씬 쌉니다(대부분 모델에서 기본 입력 가격의 10%). 기본 수명은 5분이며 쓸 때마다 갱신되고, 1시간짜리 선택지도 있습니다. OpenAI는 최신 모델 기준 1,024토큰 이상의 프롬프트를 캐시하며, 캐싱이 출력 생성 방식을 바꾸지는 않는다고 밝힙니다.
신뢰할 수 없는 내용의 자리
웹 페이지, 수신 이메일, 사용자가 올린 파일, 도구 결과처럼 통제할 수 없는 출처의 내용에는 모델을 조종하려는 문장이 숨어 있을 수 있습니다. 이것을 간접 프롬프트 인젝션이라고 합니다. 사용자가 직접 공격하는 직접 인젝션과 달리, 사용자는 믿을 만하지만 모델이 대신 읽는 제3자의 내용이 공격 경로가 됩니다. OWASP의 LLM 애플리케이션 10대 위험(2025)은 이것을 첫 번째 위험으로 꼽고, RAG나 미세 조정으로도 완전히 막히지 않는다고 말합니다.
Anthropic 문서가 권하는 배치 원칙은 다음과 같습니다.
- 제3자 내용은 시스템 프롬프트나 일반 사용자 텍스트가 아니라 도구 결과(
tool_result) 안에만 넣는다. - 그 내용이 무엇이고 어디서 왔는지(“모르는 발신자의 수신 메일 본문”) 도구 설명이나 결과 구조에 밝힌다.
- 도구·문서·검색에서 온 내용은 신뢰할 수 없는 데이터이며 시스템 프롬프트나 사용자의 원래 요청을 덮어쓸 수 없다고 시스템 프롬프트에 명시한다.
- 외부 문자열은 가능하면 JSON 객체에 담아 넣는다. JSON 이스케이프가 경계를 분명히 해서 공격자가 따옴표나 태그를 닫고 지시 영역으로 빠져나가지 못하게 한다.
- 반대로 내 지시는 도구 결과 안에 넣지 않는다. 의심받거나 무시될 수 있다.
- 뚫렸을 때를 대비해 최소 권한을 준다. 필요 없는 비밀 정보에 접근시키지 않고, 도구 권한을 좁히고, 위험한 행동에는 사람의 승인을 둔다.
사용자가 직접 규칙을 무너뜨리려는 직접 인젝션(탈옥)에 대해 Anthropic 문서는 가벼운 모델로 입력을 먼저 검사하기, 알려진 공격 문구로 입력 검증하기, 거절 방법을 시스템 프롬프트에 정해 두기, 반복 시도하는 사용자에 대응하기를 권합니다. OWASP의 대책도 같은 방향입니다. 행동 범위 제한, 출력 형식 검증, 입출력 필터링, 최소 권한, 위험한 행동의 사람 승인, 외부 내용 분리 표시, 공격을 가정한 시험입니다. 가장 신뢰받는 자리에는 가장 신뢰할 수 있는 내용만 둡니다.
깊이 읽기
긴 창에 다 넣을까, 검색할까
창이 커지면서 “검색 없이 다 넣으면 되지 않나”라는 질문이 늘었습니다. 답은 작업에 따라 다릅니다. Google의 긴 컨텍스트 문서는 단일 정보를 찾는 시험에서는 높은 정확도가 나오지만, 여러 정보를 동시에 찾아야 할 때는 같은 정확도가 나오지 않는다고 설명합니다. 또 질문을 보낼 때마다 입력 토큰 비용을 다시 내고, 입력이 길수록 첫 토큰까지의 지연도 늘어납니다.
| 상황 | 기울어지는 선택 |
|---|---|
| 자료가 작고(예: 20만 토큰 미만) 잘 안 바뀜, 같은 자료로 질문이 반복 | 통째로 넣고 캐싱 |
| 자료가 크거나 자주 바뀜 | 검색 증강 |
| 한 질문에 여러 곳의 정보를 모아야 함 | 검색 + 인용, 또는 질문을 나눠 여러 번 |
| 문서 전체의 흐름이나 구조를 봐야 함(전체 요약, 일관성 검토) | 통째로 넣기, 필요하면 구간별 처리 |
| 정확한 문자열(번호, 코드)로 찾아야 함 | 검색에 BM25 같은 단어 일치 방식 포함 |
도구 설계도 컨텍스트 설계다
에이전트에게 도구는 손이자 눈입니다. 도구 정의와 도구 결과도 컨텍스트를 차지하므로, 도구를 어떻게 설계하느냐가 컨텍스트의 품질을 좌우합니다. Anthropic 글은 도구가 토큰 효율적인 정보를 돌려주고 기능이 서로 최소한으로만 겹쳐야 한다고 말하며, “사람 엔지니어가 어느 도구를 써야 할지 확실히 말할 수 없다면 에이전트도 더 잘할 수 없다”고 지적합니다.
Anthropic의 도구 정의 문서는 도구 설명을 도구마다 적어도 서너 문장으로 아주 자세히 쓰는 것이 도구 성능에 가장 중요한 요소라고 합니다. 무엇을 하는지, 언제 쓰고 언제 쓰지 않는지, 매개변수의 뜻, 돌려주지 않는 정보를 적습니다. 비슷한 동작은 action 매개변수를 가진 도구 하나로 묶고, 여러 서비스에 걸치면 서비스 이름을 접두어로 붙입니다. 도구 결과에는 다음 판단에 필요한 필드와 의미 있는 식별자만 담습니다. 부풀려진 결과는 컨텍스트를 낭비합니다.
대화 상태를 서버에 맡길 때
대화 이력을 벤더 서버에 맡길 수도 있습니다. OpenAI Responses API는 previous_response_id로 응답을 잇거나 Conversations API로 대화를 오래 유지되는 객체로 저장합니다. 공식 문서에 따르면 previous_response_id로 이어도 앞선 응답들의 입력 토큰은 다시 입력 요금으로 청구되고, 저장된 응답은 기본 30일간 보관되고 store를 false로 두면 응답 객체를 저장하지 않습니다. 다만 악용 감시 로그(기본 최대 30일)처럼 별도 보존 정책이 있으니 데이터 정책 문서를 함께 확인합니다. 대화 객체는 이 30일 기한을 따르지 않습니다. 비용 예산과 보관 규정에 맞춰 방식을 고릅니다.
추론 모델과 도구를 함께 쓸 때는 이전 추론의 흔적도 넘깁니다. OpenAI는 함수 호출 뒤에 추론 항목을 함께 돌려주라고 강하게 권하고, 저장하지 않는 모드에서는 암호화된 추론 내용(encrypted_content)을 넘기라고 안내합니다. Anthropic은 assistant 턴을 사고 블록까지 API가 돌려준 그대로 덧붙이라고 권하며, 일부 최신 모델에서는 사고 블록 앞의 대화를 고치면 오류가 나거나 블록이 버려진다고 설명합니다. 규칙을 바꿀 일이 있으면 이력을 고쳐 쓰지 말고 1장의 대화 중 시스템 메시지처럼 덧붙입니다.
실무 장면
푸른물류: 규정 400개를 뒤지는 질의응답 봇
물류 기업 ‘푸른물류’는 사내 규정 문서 400개를 검색해 답하는 질의응답 봇을 운영한다. 직원들의 불만은 세 가지다. 답이 그럴듯하지만 어느 규정인지 알 수 없고, 출장비 질문에 휴가 규정이 섞여 나오며, 7월에 개정된 숙박비 한도를 물으면 예전 금액이 나올 때가 있다.
담당자 문 과장은 먼저 실패한 질문 50개를 모아 단계별로 판별했다. 정답 근거가 저장소에 없던 질문은 3개였다. 검색 상위 30개 안에 정답 근거가 없던 질문이 14개였는데, 대부분 “제4조의2”처럼 조항 번호로 물은 질문이었다. 나머지 33개는 근거가 컨텍스트에 들어갔는데도 답이 틀렸다. 문 과장은 지금 구조도 살폈다. 질문이 맨 위에 있고, 그 아래로 검색 결과 30개가 경계 표시 없이 줄줄이 붙은 뒤 “답하라”로 끝났다.
진단에 따라 단계마다 다른 처방을 내렸다.
- 자료. 근거가 없던 세 질문은 규정이 아니라 공지 게시판에만 있던 내용이었다. 해당 공지를 규정 담당 부서에 넘겨 규정으로 편입하게 했다.
- 검색. 조항 번호와 규정 이름처럼 정확한 문자열로 찾는 질문을 위해 의미 검색에 단어 일치 검색을 더했다. 질의 생성 단계에서 질문의 업무 분류(출장, 휴가, 구매)를 먼저 판정해 검색 필터로 쓰게 했다.
- 선별. 후보를 관련도로 재정렬해 상위 5개만 남겼다.
- 배치와 메타데이터. 남긴 규정마다
<document>태그와 규정 번호, 개정일, 적용 대상을 붙여 앞쪽에 두고, 질문은 맨 끝으로 옮겼다. 폐지된 버전은 기본 검색에서 제외하되, 질문에 과거 날짜가 있으면 그 시점에 유효한 버전을 함께 넣게 했다. - 생성. 답하기 전에 관련 조문을
<quotes>에 옮기게 하고, 답변 끝에 규정 번호와 개정일을 적게 했다. 같은 조항의 신구 버전이 모두 들어오면 질문의 기준일에 맞는 쪽을 따르고, 판단할 수 없으면 두 버전을 모두 보여 주라고 했다.
“창이 넉넉하니 검색 결과를 50개로 늘리자”는 의견은 받아들이지 않았다. 실패의 상당수가 관련 없는 규정이 섞여서 생겼고, 늘리면 그 문제가 커질 뿐이었다. 개선 후 같은 50개 질문을 다시 돌리자 대부분이 정답 근거와 함께 맞게 답했고, 입력 토큰은 이전의 4분의 1 수준으로 줄었다. 직원들은 답에 붙은 규정 번호로 원문을 바로 찾을 수 있게 됐다.
새빛일보: 3년 치 공약을 한 기사로
지역 신문 ‘새빛일보’ 데이터팀의 장 기자는 시장 선거를 앞두고 후보 네 명의 공약이 지난 3년 동안 어떻게 바뀌었는지 비교하는 기사를 준비한다. 자료는 보도자료, 토론회 녹취, 공약집 PDF, 시의회 회의록으로 합계 수백만 토큰이다. 처음에는 후보별로 자료를 몽땅 넣고 “공약 변화를 정리하라”고 했지만 결과는 들쭉날쭉했다. 어떤 후보는 철회한 공약이 현재 공약처럼 정리됐고, 다른 후보의 발언이 섞이기도 했다.
장 기자는 기사의 질문에서 거꾸로 따졌다. 기사가 답해야 할 것은 “분야별로 각 후보의 현재 공약은 무엇이고, 언제 무엇이 바뀌었는가”다. 분야는 교통, 주거, 돌봄, 재정 넷이다. 그래서 작업 단위를 “후보 한 명 × 분야 하나”로 나눴다. 열여섯 개 작업마다 예산표를 짰다.
| 구성 요소 | 내용 | 원칙 |
|---|---|---|
| 고정 지시 | 기사 기준, 인용 규칙, 출력 형식 | 모든 작업에서 같게 두어 캐싱 |
| 자료 | 해당 후보·분야의 발언과 문서만 | 날짜·출처·발언자 메타데이터 필수 |
| 질문 | 현재 공약, 변경 시점, 변경 내용 | 맨 끝 |
| 출력 여유 | 분야별 정리표 한 장 | 표 형식, 인용 번호 필수 |
자료를 고르는 일은 검색으로 했다. 후보 이름과 분야 핵심어로 찾은 뒤 발언자가 그 후보인 것만 남겼다. 녹취는 발언 단위로 잘라 발언자, 날짜, 행사명을 붙였다. 다른 후보의 발언이 섞이던 문제는 이 메타데이터로 사라졌다.
생성 단계에서는 인용을 먼저 받았다. 모델은 공약 문장을 원문 그대로 옮기고 날짜순으로 늘어놓은 뒤, 이전 발언과 달라진 지점을 표시했다. 철회 여부처럼 해석이 필요한 부분은 “확인 필요”로 남기게 했다. 장 기자는 인용을 원문과 기계로 대조하는 스크립트를 동료에게 부탁해, 글자가 다른 인용을 모두 걸러 냈다.
마지막 합치기 단계에는 원자료 대신 열여섯 개 정리표만 넣어 분야별 비교표를 만들게 했다. 작업마다 쓴 진행 메모에는 확인이 끝난 인용과 남은 확인 항목을 적어, 며칠에 걸쳐 작업해도 어디까지 했는지 잃지 않았다.
버린 선택지도 기록했다. 모든 자료를 한 번에 넣고 비교표를 바로 만들게 하는 방식은 여러 정보를 동시에 찾아야 하는 작업이라 놓치는 공약이 생길 위험이 컸다. 자료를 요약한 뒤 그 요약으로 비교하는 방식은 날짜와 수치가 뭉개질 위험이 있어, 요약 대신 원문 인용을 쌓는 방식을 택했다. 기사는 공약 문장마다 출처와 날짜를 달고 나갔고, 독자 문의에 답할 근거도 그대로 남았다.
자주 틀리는 지점
- 창이 크면 다 넣는 것이 유리하다. 컨텍스트 부패 때문에 관련 없는 정보는 오히려 품질을 떨어뜨리고 비용과 지연을 늘립니다.
- 창이 넓으면 출력도 길게 받을 수 있다. 출력에는 별도의 상한이 있습니다. 긴 결과물은 구간을 나눠 받습니다.
- 질문을 먼저 써야 모델이 목적을 안다. 긴 입력에서는 문서를 앞에, 질문을 끝에 두는 배치가 공식 권장입니다. 핵심 행동 제약은 앞에 둡니다.
- RAG가 틀리면 프롬프트를 고친다. 자료, 검색, 선별, 생성 중 어느 단계의 실패인지 먼저 가립니다.
- 요약하면 정보 손실이 없다. 요약은 수치와 조건을 뭉갭니다. 확정된 값은 상태 기록으로 원문 그대로 남깁니다.
- 외부 자료일수록 시스템 프롬프트에 넣어야 잘 반영된다. 신뢰할 수 없는 내용을 가장 신뢰받는 자리에 두면 인젝션 위험이 커집니다.
- 캐싱을 켜면 알아서 절약된다. 바뀌는 값이 앞쪽에 있으면 그 뒤가 매번 새로 계산되어 캐시가 거의 맞지 않습니다. 고정 내용을 앞으로, 변수를 뒤로 옮깁니다.
한눈에 정리
| 주제 | 기억할 것 |
|---|---|
| 컨텍스트 부패 | 토큰이 늘수록 회상과 정확도가 떨어진다. 작은 고신호 토큰 집합이 목표 |
| 예산표 | 지시·도구·예시·자료·이력·출력 여유. 캐시 토큰도 창을 차지한다 |
| 선별 | 질문을 쟁점으로 쪼개 필요한 자료를 거꾸로 정하고, 뺄 순서를 미리 정한다 |
| 배치 | 핵심 제약은 앞, 긴 자료는 그 뒤, 질문은 끝. 이미지는 텍스트보다 먼저 |
| 인용 | 먼저 인용, 없으면 없다고, 인용 없는 주장은 철회. 일치·관련성·충분성 확인 |
| RAG | 조각의 맥락 보강, 의미 검색 + 단어 일치, 재정렬. 작은 자료는 통째로 + 캐싱 |
| 요약 | 줄거리가 아니라 상태 기록. 확정 값은 원문 그대로 |
| 캐싱 | 앞부분이 글자 하나까지 같아야 적중. 고정은 앞, 변수는 뒤 |
| 외부 내용 | 도구 결과 안에, 출처 표시, JSON 인코딩, 최소 권한, 위험 행동은 사람 승인 |
공식 문서로 확인하기
- Anthropic — Prompting best practices: long context: 문서 배치, 태그 구조, 인용 먼저 받기를 읽는다.
- Anthropic — Effective context engineering for AI agents: 컨텍스트 부패, 적시 로딩, 압축, 구조화된 메모, 하위 에이전트, 도구 설계를 읽는다.
- Anthropic — Contextual Retrieval: 조각 맥락 보강, BM25, 재정렬의 효과와 작은 지식 베이스에 대한 조언을 읽는다.
- Anthropic — Prompt caching: 캐시 순서, 무효화 조건, 수명과 가격 배수를 확인한다.
- Anthropic — Mitigate jailbreaks and prompt injections: 간접 인젝션 대비 배치 원칙을 읽는다.
- OWASP — LLM01:2025 Prompt Injection: 직접·간접 인젝션과 일곱 가지 대책을 확인한다.
셀프 체크
3-1. 컨텍스트 부패를 한 문장으로 정의하고, “창이 크니 관련 자료를 모두 넣자”는 제안에 반대하는 근거를 두 가지 들라.
3-2. 요청 하나의 컨텍스트 예산표에 들어가야 할 구성 요소 다섯 가지를 쓰고, 그중 가장 자주 잊히는 것이 무엇인지와 잊었을 때 생기는 증상을 쓰라.
3-3. 60쪽 분량 감사 보고서 두 건과 질문 하나를 넣는 프롬프트 골격을 태그로 적어 보라. 문서마다 출처와 작성일을 붙이고, 인용을 먼저 받게 한다.
3-4. 검색 증강 답변이 틀렸을 때 실패 단계를 가리는 질문 네 개를 확인 순서대로 쓰고, 마지막 질문에서야 지시문을 고치는 이유를 한 문장으로 설명하라.
3-5. 담당자가 바뀌어, 모델과 몇 주 동안 나눈 행사 기획 대화를 새 담당자의 새 대화로 넘겨야 한다. 넘길 기록에 원문 그대로 남겨야 할 정보의 종류 세 가지를 들고, 그 기록의 형식을 예로 보여라.
3-6. 한 에이전트가 같은 긴 지침을 쓰면서, 요청마다 사용자의 권한 등급에 따라 도구 목록의 일부를 빼거나 더해 보낸다. 프롬프트 캐싱 관점에서 어떤 손해가 생기는지 설명하고, 권한 차이를 지키면서 손해를 줄이는 방법을 하나 제안하라.
3-7. 경쟁사 누리집을 읽어 요금표를 정리하는 조사 에이전트를 만든다. 가져온 웹 페이지 본문을 프롬프트의 어느 자리에 어떤 모양으로 넣을지, 그리고 페이지 속 숨은 지시에 뚫렸을 때 피해를 줄이는 장치를 각각 두 가지씩 쓰라.
실습 과제
실습
긴 문서 배치 A/B 실험 (60분)
- 30쪽 이상인 공개 보고서 두 건을 준비한다.
- 두 문서를 비교해야 답할 수 있는 질문 다섯 개를 만든다.
- 버전 A는 질문을 맨 위에 쓰고 그 아래에 두 문서를 붙인다. 버전 B는 문서별 태그와 출처·작성일을 붙여 앞에 두고, 인용을 먼저 받은 뒤 질문을 끝에 둔다.
- 각 답변의 주장 하나하나를 원문과 대조해 근거가 있는 주장의 비율을 센다. 버전 B는 인용이 원문과 글자 그대로 일치하는지도 확인한다.
완료 기준: 두 버전의 근거 비율, 원문과 다른 인용의 개수, 검수에 걸린 시간을 표로 비교하면 완료다.
실습
컨텍스트 예산표와 상태 기록 만들기 (45분)
- 최근에 모델과 길게 나눈 업무 대화 하나를 고른다(20턴 이상이 좋다).
- 그 대화를 이어 가기 위해 꼭 필요한 정보를 “확정된 조건, 미해결 질문, 결정 이력, 다음 행동”으로 나눠 상태 기록을 쓴다. 확정 값은 원문 표현 그대로 옮긴다.
- 같은 대화를 모델에게 자유롭게 요약하게 한 결과와 내 상태 기록을 나란히 놓는다.
- 새 대화를 두 번 시작한다. 한 번은 자유 요약으로, 한 번은 상태 기록으로 이어 가며 같은 후속 질문 세 개를 던진다.
완료 기준: 두 방식에서 확정 조건이 정확히 유지된 개수를 세어 표로 남기고, 자유 요약에서 뭉개진 정보가 있다면 그 예를 하나 적으면 완료다.