컨텍스트 엔지니어링: 프롬프트를 넘어 시스템을 설계하는 법
컨텍스트 엔지니어링: 프롬프트를 넘어 시스템을 설계하는 법
컨텍스트 엔지니어링을 단순한 메모리나 RAG가 아니라 모델이 봐야 할 정보 설계로 정리한 글입니다.
안녕하세요 mouseco 입니다. :)
컨텍스트 엔지니어링은 제가 처음 이해했던 것보다 범위가 조금 더 넓었습니다.
처음에는 "메모리를 잘 저장하고, 필요한 자료를 잘 검색하고, 긴 내용을 요약하는 기술" 정도로 생각하기 쉬운데요. 공식 자료들을 다시 보면 핵심은 조금 다릅니다.
컨텍스트 엔지니어링은 모델이 다음 답변을 만들 때 실제로 보게 되는 컨텍스트 창 안의 정보 구성을 설계하는 일에 가깝습니다.
즉 프롬프트 문장만 예쁘게 쓰는 게 아니라, 시스템 지시문, 사용자 요청, 이전 대화, 도구 설명, 도구 실행 결과, 검색 자료, 메모리, 출력 형식까지 합쳐서 "이번 턴에 무엇을 보여줄 것인가"를 정하는 작업입니다.
목차
- 한 문장 정의
- 프롬프트 엔지니어링과 다른 점
- 컨텍스트에 들어가는 것들
- 컨텍스트 엔지니어링이 아닌 것
- 네 가지 전략은 전체 정의가 아니라 실전 도구다
-
- Write: 기억할 것은 밖에 쓴다
-
- Select: 지금 필요한 것만 고른다
-
- Compress: 줄이되 판단 근거는 남긴다
-
- Isolate: 섞이면 망가지는 작업은 분리한다
- 실무 워크플로우: 이번 턴의 컨텍스트를 설계하는 7단계
한 문장 정의
컨텍스트 엔지니어링은 LLM이 다음 추론 단계에서 봐야 할 정보를 가장 적절한 형태로 고르고, 배치하고, 유지하는 설계입니다.
LangChain은 컨텍스트 엔지니어링을 에이전트가 매 단계에서 필요한 정보를 컨텍스트 창에 채우는 기술로 설명합니다. Anthropic도 비슷하게, LLM 추론 시점에 들어가는 토큰 묶음을 최적화하는 전략으로 설명합니다.
제가 보기엔 이 정의에서 중요한 단어는 "다음 추론 단계"입니다. 컨텍스트 엔지니어링은 한 번 잘 써두는 문서가 아니라, 매번 모델을 호출하기 전에 무엇을 보여줄지 결정하는 과정입니다.
조금 더 실무적으로 말하면 이런 질문에 답하는 일입니다.
- 무엇을 모델에게 보여줄 것인가
- 무엇은 지금 보여주지 않을 것인가
- 어떤 자료는 원문으로 넣고, 어떤 자료는 요약해서 넣을 것인가
- 검색 결과와 도구 실행 결과를 어디까지 믿을 것인가
- 오래된 대화와 최신 요청이 충돌하면 무엇을 우선할 것인가
- 어떤 형식으로 압축할 것인가
- 어떤 작업은 다른 컨텍스트로 분리할 것인가
- 출력 형식과 검증 기준을 컨텍스트 안에 어떻게 넣을 것인가
프롬프트 엔지니어링과 다른 점
프롬프트 엔지니어링은 보통 "요청 문장"에 집중합니다.
너는 시니어 개발자야.
아래 코드를 리뷰해줘.
버그, 성능, 가독성 순서로 정리해줘.
컨텍스트 엔지니어링은 여기에 더 많은 질문을 붙입니다.
리뷰에 필요한 파일은 어떤 기준으로 고를 것인가?
전체 레포를 다 넣을 수 없다면 무엇을 압축할 것인가?
이전 리뷰에서 합의한 스타일 가이드는 어디에 저장할 것인가?
테스트 결과와 빌드 로그는 원문으로 넣을 것인가, 요약해서 넣을 것인가?
보안 관련 파일은 별도 컨텍스트로 격리할 것인가?
최종 출력은 사람이 읽는 리뷰인가, CI가 읽는 JSON인가?
프롬프트가 "이 일을 해줘"에 가깝다면, 컨텍스트 엔지니어링은 "이 일을 하게 만들기 위해 이번 호출에 어떤 정보와 도구 상태를 보여줄 것인가"에 가깝습니다.
그래서 컨텍스트 엔지니어링은 프롬프트 엔지니어링을 대체한다기보다는 감싸는 개념에 가깝습니다. 좋은 프롬프트도 컨텍스트의 일부입니다. 다만 프롬프트만으로는 부족하고, 검색 자료, 툴 결과, 메모리, 상태, 출력 스키마까지 같이 설계해야 하는 상황이 많아진 것입니다.
컨텍스트에 들어가는 것들
여기서 말하는 컨텍스트는 단순히 "참고 자료"가 아닙니다. 모델이 다음 답변을 만들 때 실제로 받는 토큰 전체를 말합니다.
보통 아래 요소들이 컨텍스트에 들어갑니다.
| 요소 | 예시 | 주의할 점 |
|---|---|---|
| 시스템/개발자 지시 | 역할, 금지 조건, 출력 규칙 | 너무 길면 실제 작업 지시를 밀어냅니다. |
| 사용자 요청 | 최신 질문, 추가 조건 | 이전 요청보다 최신 요청이 우선입니다. |
| 대화 기록 | 앞선 합의, 실패한 시도 | 오래된 내용이 새 결정을 덮지 않게 해야 합니다. |
| 도구 설명 | 사용 가능한 API, MCP, CLI | 도구가 많으면 선택이 흐려질 수 있습니다. |
| 도구 실행 결과 | 검색 결과, 테스트 로그, DB 조회 | 원문을 다 넣을지 요약할지 정해야 합니다. |
| 검색/RAG 자료 | 공식 문서, 코드, PDF, 위키 | 관련성보다 권위와 최신성이 중요할 때가 있습니다. |
| 메모리/상태 | 사용자 선호, 프로젝트 규칙, 진행 상태 | 오래된 메모리는 오히려 오염원이 될 수 있습니다. |
| 출력 형식 | JSON schema, 표, 보고서 양식 | 검수 가능한 형식으로 고정하는 편이 좋습니다. |
이걸 보면 컨텍스트 엔지니어링이 단순한 요약 기술이 아니라는 게 보입니다. 결국 "모델이 지금 무엇을 보고 판단하게 만들 것인가"를 설계하는 일입니다.
컨텍스트 엔지니어링이 아닌 것
제가 기존 초안에서 조금 헷갈렸던 부분이 여기입니다.
컨텍스트 엔지니어링은 단순히 긴 대화를 요약하는 기술만은 아닙니다. RAG 검색을 붙이는 것만도 아니고, 장기 메모리를 저장하는 것만도 아닙니다. 물론 이 셋은 중요한 구성 요소가 될 수 있습니다.
하지만 핵심은 저장 자체가 아니라 선택과 배치입니다.
예를 들어 문서 100개를 검색했다고 해서 컨텍스트 엔지니어링을 잘한 것이 아닙니다. 그중 이번 답변에 필요한 문서 3개를 고르고, 충돌하는 문서를 표시하고, 모델이 오해하지 않도록 출처와 한계를 붙여 넣어야 합니다.
반대로 100만 토큰 컨텍스트 모델을 쓴다고 해서 문제가 사라지는 것도 아닙니다. Anthropic은 컨텍스트가 길어질수록 모델의 주의가 분산될 수 있다고 설명합니다. 그래서 좋은 컨텍스트는 "많은 정보"가 아니라 작지만 신호가 강한 정보에 가깝습니다.
네 가지 전략은 전체 정의가 아니라 실전 도구다
Write / Select / Compress / Isolate는 컨텍스트 엔지니어링의 전부라기보다는 실무에서 자주 쓰는 네 가지 전략으로 보는 게 더 정확합니다.
Write: 지금 창에 다 담지 못할 정보를 바깥에 저장합니다.Select: 저장된 정보 중 이번 호출에 필요한 것만 고릅니다.Compress: 긴 내용을 다음 판단에 필요한 형태로 줄입니다.Isolate: 섞이면 안 되는 작업이나 정보를 분리합니다.
이 네 가지는 LangChain이 에이전트 컨텍스트를 설명할 때 쓰는 좋은 틀입니다. 다만 컨텍스트 엔지니어링의 핵심은 이 네 단어 자체가 아니라, 매 호출마다 컨텍스트 창을 더 잘 구성하는 데 있습니다.
1. Write: 기억할 것은 밖에 쓴다
Write는 현재 대화창 안에만 두면 사라질 정보를 외부 상태로 남기는 동작입니다. 여기서 외부 상태는 파일, DB, 벡터 저장소, 세션 메모리, 작업 로그, 사용자 프로필, 결정 기록이 될 수 있습니다.
언제 Write가 필요한가
- 사용자의 선호가 다음 작업에도 반복해서 필요할 때
- 프로젝트 규칙, 용어, 금지 사항이 계속 재사용될 때
- 긴 작업의 중간 결정이 다음 단계에 영향을 줄 때
- 에이전트가 도구를 여러 번 호출하며 상태를 이어가야 할 때
- 실패 원인을 다음 실행에서 피해야 할 때
나쁜 Write
사용자가 좋아하는 스타일: 깔끔함.
너무 추상적입니다. 다음 실행에서 어떤 행동으로 바꿔야 하는지 알 수 없습니다.
좋은 Write
user_style:
language: ko-KR
tone: 존댓말, 직접적, 과장 금지
avoid:
- "원하면 해드리겠습니다" 식의 열린 결말
- 근거 없는 칭찬
- 일반론만 나열하는 글
prefer:
- 먼저 결론
- 실제 적용 예시
- 검수 가능한 체크리스트
좋은 메모리는 모델이 다음 행동을 바꾸게 만듭니다.
OpenAI Cookbook의 장기 메모리 예제도 구조화된 사용자 프로필과 메모리 노트를 상태 객체로 관리하고, 필요한 시점에 주입하는 패턴을 보여줍니다. 중요한 포인트는 내부 시스템의 모든 필드를 덤프하지 말고, 의사결정에 도움이 되는 토큰만 넣어야 한다는 점입니다. 참고: OpenAI Cookbook - Context Personalization
Write 템플릿
[저장할 메모리 후보를 추출해줘]
입력:
아래 대화/작업 로그에서 다음 실행에도 재사용할 가치가 있는 정보만 골라라.
저장 기준:
- 사용자의 반복 선호
- 프로젝트 고유 규칙
- 이미 결정된 방향
- 다시 확인하면 시간 낭비인 사실
- 다음 실행의 품질을 바꿀 수 있는 제약
제외 기준:
- 일회성 감탄
- 임시 상태
- 이미 문서화된 일반 지식
- 개인정보나 민감 정보
- 불확실한 추정
출력 형식:
YAML 형태로 작성한다.
- memory_candidates:
- type:
- text:
- reason:
- reuse_scene:
- confidence: high|medium|low
2. Select: 지금 필요한 것만 고른다
Select는 저장된 정보 중 현재 작업에 필요한 것만 골라 컨텍스트에 넣는 동작입니다. 많은 RAG 실패가 여기서 납니다. 검색을 했다는 사실이 중요한 것이 아니라, 검색된 것 중 무엇을 넣을지 정하는 것이 중요합니다.
Select가 약할 때 생기는 문제
사용자: 이 기능의 버그 원인을 찾아줘.
시스템: 관련 있어 보이는 파일 80개, 최근 커밋 40개, 이슈 30개를 모두 넣음.
모델: 답변은 길지만 원인은 못 찾음.
컨텍스트가 많아질수록 모델은 더 똑똑해지는 것이 아니라 더 산만해질 수 있습니다.
Select 기준
| 기준 | 질문 | 예시 |
|---|---|---|
| 관련성 | 지금 질문에 직접 답하는가 | 에러 메시지가 나온 파일 |
| 최신성 | 현재 상태와 맞는가 | 최신 커밋 이후 문서 |
| 권위 | 신뢰할 수 있는 원천인가 | 공식 문서, 코드 원본 |
| 독립성 | 중복이 아닌가 | 같은 내용을 반복하는 블로그 제외 |
| 실행성 | 답변에 실제로 쓰이는가 | 설정값, 로그, 테스트 결과 |
Select 템플릿
[컨텍스트 선별자]
목표:
아래 후보 자료 중 현재 작업에 넣을 자료만 선택한다.
현재 작업:
{{task}}
후보 자료:
{{candidate_contexts}}
선택 기준:
1. 작업 해결에 직접 필요한 자료만 선택한다.
2. 같은 내용을 반복하는 자료는 가장 권위 있는 원천 1개만 남긴다.
3. 오래된 자료와 최신 자료가 충돌하면 충돌 사실을 표시한다.
4. 불확실한 자료는 "참고"로 낮은 우선순위에 둔다.
출력:
| 선택 | 자료명 | 이유 | 사용 위치 | 위험 |
|---|---|---|---|---|
3. Compress: 줄이되 판단 근거는 남긴다
Compress는 긴 정보를 짧게 만드는 동작입니다. 단순 요약과 다릅니다. 좋은 압축은 원문을 줄이면서도 의사결정에 필요한 근거, 숫자, 제약, 예외를 보존합니다.
나쁜 압축
회의에서는 일정과 디자인에 대해 논의했고, 몇 가지 수정 사항이 있었다.
이 문장은 안전해 보이지만 쓸모가 없습니다. 무엇을 언제까지 누가 해야 하는지 사라졌습니다.
좋은 압축
결정:
- 2026-04-30까지 모바일 배너 제거
- 라이트 테마에서 게시판 헤더 대비 개선
- 배포 전 관리자 테이블 색상 확인
보류:
- 콘텐츠 리팩터링은 아직 하지 않음
- DB 반영은 초안 검수 후 진행
위험:
- 기존 untracked 파일이 많아 커밋 분리 필요
좋은 압축은 나중에 작업을 이어받을 사람이 다시 실행할 수 있어야 합니다.
OpenAI Cookbook의 세션 메모리 예제는 트리밍과 요약을 구분합니다. 트리밍은 오래된 턴을 버리는 방식이라 예측 가능하고 빠르지만, 장기 조건을 잃을 수 있습니다. 요약은 긴 맥락을 유지할 수 있지만 요약 드리프트 위험이 있습니다. 그래서 중요한 사실은 구조화된 요약으로 남기고, 최근 도구 결과는 원문에 가깝게 보존하는 식의 절충이 필요합니다.
Compress 템플릿
[작업 이어받기용 압축]
아래 긴 대화/로그를 다음 작업자가 바로 이어서 실행할 수 있게 압축해라.
반드시 보존:
- 사용자의 최신 요청
- 이미 완료한 작업
- 아직 하지 않은 작업
- 파일 경로
- 명령어
- 결정된 제약
- 실패와 원인
- 다음 액션
버릴 것:
- 인사
- 반복 설명
- 감정적 표현
- 이미 해결된 추측
출력 형식:
## 현재 목표
## 완료
## 남은 작업
## 중요 제약
## 참고 경로
## 다음 명령
4. Isolate: 섞이면 망가지는 작업은 분리한다
Isolate는 서로 다른 목적의 컨텍스트를 분리하는 동작입니다. 하나의 긴 대화에 모든 것을 계속 넣으면, 모델은 어떤 기준을 우선해야 하는지 헷갈립니다.
분리해야 하는 경우
- 글쓰기와 코드 리뷰처럼 평가 기준이 다른 작업
- 의료, 금융, 법률처럼 안전 경계가 강한 작업
- 검색, 초안 작성, 편집, 배포처럼 단계별 실패 비용이 다른 작업
- 서로 다른 고객이나 프로젝트의 정보가 섞이면 안 되는 작업
- 한 작업의 임시 가정이 다른 작업의 사실처럼 쓰이면 안 되는 경우
Isolate 예시
콘텐츠 개선 작업을 한 컨텍스트에 모두 넣으면 이런 문제가 생깁니다.
리서치 자료, 초안, 편집 피드백, DB 업데이트 SQL, 배포 로그가 한 대화에 섞임.
모델이 아직 검수 전인 초안을 확정본으로 착각함.
분리하면 이렇게 됩니다.
1. research.md: 근거와 링크만 저장
2. draft.md: 독자가 읽을 본문만 작성
3. feedback.md: 편집 피드백과 수정 이유 저장
4. publish-log.md: DB 반영 여부와 배포 상태 기록
Isolate 템플릿
[작업 분리 설계]
현재 목표:
{{goal}}
섞이면 안 되는 정보:
- {{sensitive_or_noisy_context}}
작업을 아래 단위로 분리해라.
출력:
| 작업 단위 | 필요한 컨텍스트 | 제외할 컨텍스트 | 완료 기준 | 산출물 |
|---|---|---|---|---|
실무 워크플로우: 이번 턴의 컨텍스트를 설계하는 7단계
1단계: 모델 호출의 목적을 먼저 쓴다
컨텍스트를 설계하기 전에 이번 호출이 무엇을 해야 하는지부터 정해야 합니다. 같은 자료라도 "초안 작성"에 필요한 컨텍스트와 "팩트 검증"에 필요한 컨텍스트는 다릅니다.
성공 기준:
- 독자가 바로 복사해 쓸 수 있는 템플릿 5개 이상
- 공식 문서 근거 2개 이상
- 위험한 영역은 면책과 검증 경계 포함
- DB 반영 전 검수용 초안으로 저장
목적이 없으면 컨텍스트 선택도 흔들립니다.
2단계: 필요한 정보와 불필요한 정보를 나눈다
필요:
- 현재 DB 원문
- 참고 샘플 문서
- 공식 문서 링크
- 기존 사이트 톤
불필요:
- 오래된 빌드 산출물
- 중복 블로그
- 검수 전 추측
- 이전 작업의 감정적 대화
3단계: 저장할 상태를 정한다
작업이 한 번에 끝나지 않으면 상태 저장이 필요합니다. 다만 저장한 모든 상태를 매번 모델에게 보여줄 필요는 없습니다.
content_rewrite_state:
current_batch:
- context-engineering-write-select-compress-isolate
- prompt-architect-master-guide
- medical-expert-agent-prompt
publish_policy: "DB 반영 전 초안 검수"
style:
- 먼저 결론
- 실무 템플릿
- 실패 사례
- 체크리스트
4단계: 이번 호출에 넣을 자료를 고른다
공식 문서가 있으면 공식 문서를 우선합니다. 블로그는 보조 자료입니다. 의료, 금융, 법률은 기관, 논문, 공식 가이드라인 우선입니다.
여기서 중요한 건 "검색했다"가 아니라 "무엇을 넣지 않았는가"입니다.
5단계: 긴 자료를 압축한다
자료를 그대로 붙이지 말고, 아래 구조로 줄입니다.
문서명:
핵심 주장:
실무에 쓸 포인트:
주의할 점:
본문에 넣을 위치:
6단계: 도구 결과를 그대로 둘지 지울지 정한다
도구 호출 결과는 금방 컨텍스트를 부풀립니다. 테스트 로그, 검색 결과, DB 조회 결과를 전부 계속 들고 있으면 다음 판단이 흐려질 수 있습니다.
그래서 결과가 한 번 쓰였으면 원문을 지우고 핵심만 남길지, 아니면 원문 스니펫을 보존할지 정해야 합니다.
7단계: 결과물을 검수 가능한 형태로 만든다
최종 출력도 다음 작업의 컨텍스트가 될 수 있습니다. 사람이 검수하거나 다음 에이전트가 이어받을 수 있도록 제목, 표, JSON, 체크리스트처럼 구조를 잡아두면 좋습니다.
덧붙여: 실행 로그를 남긴다
어떤 자료를 봤는지, 어떤 기준으로 제외했는지, 무엇을 DB에 반영했는지 남깁니다. 나중에 "왜 이렇게 썼지?"를 줄이는 데 도움이 됩니다.
바로 복사해서 쓰는 마스터 템플릿
너는 컨텍스트 엔지니어다.
내 목표는 {{goal}}이다.
아래 정보를 보고, LLM 작업에 넣을 컨텍스트 설계를 해줘.
[작업 목표]
{{task_goal}}
[후보 자료]
{{candidate_materials}}
[제약]
- 토큰 낭비를 줄일 것
- 최신 요청을 우선할 것
- 검수 전 초안과 확정본을 구분할 것
- 불확실한 정보는 사실처럼 쓰지 말 것
[출력]
1. 반드시 넣을 컨텍스트
2. 넣지 말아야 할 컨텍스트
3. 외부에 저장할 메모리
4. 압축이 필요한 자료
5. 분리해야 할 작업
6. 최종 프롬프트 구조
7. 실패 가능성과 방지책
결과가 이상할 때 디버깅하는 법
답변이 뻔할 때
원인: 컨텍스트에 구체적인 사례, 실패 로그, 독자 상황이 없습니다.
수정:
일반론 금지.
아래 실제 상황을 기준으로 설명해라.
- 독자:
- 현재 문제:
- 이미 시도한 방법:
- 실패한 이유:
- 결과물이 쓰일 위치:
답변이 길기만 할 때
원인: Select가 약합니다. 자료를 너무 많이 넣었습니다.
수정:
아래 자료 중 최종 답변에 실제로 인용할 5개만 남기고 나머지는 제외해라.
각 제외 이유도 한 줄로 써라.
앞에서 정한 조건을 잊을 때
원인: Write가 약합니다. 결정 사항이 상태로 저장되지 않았습니다.
수정:
지금까지 확정된 결정만 "작업 계약서"로 압축해라.
이후 답변은 이 계약서를 최우선 기준으로 삼아라.
검색 자료가 답변을 오염시킬 때
원인: 검색 결과를 검증 없이 넣었습니다.
수정:
자료를 공식 문서, 논문, 블로그, 의견 글로 분류해라.
공식 문서와 논문을 우선하고, 의견 글은 참고로만 처리해라.
작업이 서로 섞일 때
원인: Isolate가 약합니다.
수정:
리서치, 초안 작성, 편집, 배포를 별도 산출물로 분리해라.
검수 전 초안은 배포 지시로 해석하지 마라.
체크리스트
- 지금 작업의 성공 기준이 한 줄로 쓰여 있는가
- 모델이 봐야 할 정보와 보지 않아야 할 정보가 나뉘었는가
- 장기 기억으로 남길 정보가 구조화되어 있는가
- 검색 결과를 권위와 관련성 기준으로 선별했는가
- 긴 히스토리를 이어받기용 요약으로 압축했는가
- 의료, 금융, 법률, 보안 등 위험 영역은 분리했는가
- 출력 형식이 사람이 검수하거나 시스템이 파싱할 수 있는가
- 실패했을 때 무엇을 바꿔야 하는지 기록했는가
주의할 점
컨텍스트 엔지니어링은 모든 정보를 모델에게 넣는 기술이 아닙니다. 오히려 덜 넣기 위해 더 많이 설계하는 기술에 가깝습니다.
가장 위험한 방식은 "혹시 모르니 다 넣자"입니다. 이 방식은 토큰 비용을 늘리고, 모델을 산만하게 만들고, 오래된 정보가 새 결정을 덮게 만듭니다.
또 하나의 위험은 요약을 사실처럼 믿는 것입니다. 요약은 압축된 해석입니다. 중요한 계약 조건, 의료 수치, 금융 데이터, 코드 diff, 에러 로그는 가능하면 원문 링크나 원문 스니펫을 함께 남겨야 합니다.
그리고 컨텍스트 엔지니어링을 장기 메모리와 같은 말로 쓰면 안 됩니다. 메모리는 컨텍스트를 구성하는 재료 중 하나입니다. 좋은 메모리도 이번 작업에 필요하지 않으면 넣지 않는 편이 낫습니다.
참고 문헌
- Anthropic - Effective context engineering for AI agents
- LangChain - Context Engineering
- OpenAI Cookbook - Context Engineering: Short-Term Memory Management
- OpenAI Cookbook - Context Personalization with Long-Term Memory Notes
- OpenAI - Harness engineering: leveraging Codex in an agent-first world
- OpenAI Cookbook - Structured Outputs for Multi-Agent Systems