컨텍스트 엔지니어링은 신뢰할 수 있는 AI 에이전트를 실제로 구현하는 기술이다.
출처: Dev.to
프롬프트 엔지니어링은 가장 먼저 배우는 기술이다.
컨텍스트 엔지니어링은 실제로 무언가를 배포하려 할 때 필요한 기술이다.
내가 이해하는 데 너무 오래 걸린 구분은 다음과 같다.
프롬프트 엔지니어링은 명확한 지시문을 작성하는 기술이다. 이는 중요하다. 잘 구성된 프롬프트는 모호성을 줄이고, 올바른 톤을 설정하며, 모델이 작업을 수행하는 데 충분한 정보를 제공한다.
하지만 프롬프트 엔지니어링은 단일 입력에만 적용된다. 다음과 같은 질문에 답하지 못한다:
- 모델이 12번째 턴에 있고 대화 기록이 4,000 토큰이라면 어떻게 되는가?
- 6개의 문서를 검색했지만 그 중 3개만 컨텍스트 창에 들어간다면?
- 시스템 프롬프트의 제약조건이 검색 파이프라인이 주입한 내용과 충돌한다면?
- 에이전트가 스스로 만든 파라미터로 도구를 호출한다면?
이것들은 프롬프트 문제가 아니라 아키텍처 문제이며, 실제 프로덕션 AI 시스템이 실패하는 지점이다.
컨텍스트 엔지니어링은 모델이 응답을 생성할 때 보는 모든 것을 의도적으로 설계하는 실천이다. 여기에는 현재 프롬프트뿐 아니라 시스템 지시문, 검색된 데이터, 대화 기록, 도구 스키마, 주입된 상태, 출력 형식 가이드가 모두 포함된다.
핵심 통찰: 컨텍스트는 유한하고 비용이 많이 드는 자원이며, 출력 품질을 직접 결정한다. 이를 수동적으로 쌓아두는 것이 아니라 의도적으로 관리하는 것이 데모와 대규모 운영 시스템을 구분짓는다.
이 용어는 비교적 새롭다. Andrej Karpathy가 2025년에 처음 사용했으며, 실제로는 이름 없는 상태에서 이미 심각한 에이전트 구축자들이 하고 있던 일을 가리킨다. 현재 나는 LLM 시스템 설계를 생각할 때 가장 유용한 프레이밍이라고 본다.
신뢰할 수 있는 AI 에이전트 컨텍스트는 네 가지 레이어로 구성된다. 어느 하나라도 부주의하게 설계하면 예측 불가능한 출력이 발생한다.
역할 정의, 규칙, 제약조건
대부분의 개발자는 이를 한 문단의 지시문으로 작성한다. 프로덕션 버전은 계약 형태로 만든다:
당신은 [역할]이며 다음 제약조건을 따른다: [목록].
[조건 A]가 발생하면 항상 [행동 X]를 수행한다.
[조건 B]가 발생하면 항상 [행동 Y]를 수행한다.
이 제약조건 내에서 작업을 수행할 수 없을 경우, 다음과 같이 응답한다: [구체적인 폴백].
출력 형식: [정확한 사양].
“작업을 수행할 수 없을 경우” 조항은 대부분 빠뜨리는 부분이며, 에이전트가 즉흥적으로 행동하지 않고 에스컬레이션해야 할 때 이를 방지한다.
메모리
턴 사이에 지속되는 정보를 의미한다. 네 가지 유형이 있다.
| 유형 | 저장 내용 | 구현 방법 |
|---|---|---|
| In‑context | 최근 턴, 작업 상태 | 직접 주입, 트렁케이션 관리 |
| Episodic | 과거 세션, 이벤트 | 외부 저장소, 관련성에 따라 검색 |
| Semantic | 사실, 지식, 선호도 | 벡터 스토어 또는 지식 그래프 |
| Procedural | 작업 수행 방법 | 프롬프트 템플릿, 도구 정의 |
대부분의 에이전트 프레임워크는 In‑context 메모리를 자동으로 처리하지만(품질이 낮음), 나머지 세 유형은 명시적인 설계가 필요하다.
가장 흔한 실패: In‑context 메모리가 무제한으로 커져 시스템 프롬프트와 RAG 컨텍스트를 압박한다. 해결책: 토큰 예산을 강제하고, 요약을 적극적으로 수행한다.
작업 레이어
현재 턴에 대한 구체적인 목표를 정의한다. 흔히 하는 실수는 작업을 너무 포괄적으로 잡는 것이다.
- “사용자의 요청을 도와라” → 작업 레이어가 아니다.
- “다음 문서에서 모든 날짜를 추출하고 ISO‑8601 문자열로 반환한다” → 올바른 작업 레이어.
작업을 더 좁게 정의하면 출력이 일관되고 평가도 쉬워진다.
출력 형식
모델이 생성해야 할 정확한 포맷을 지정한다. “JSON 형식”이 아니라 정확한 스키마를 제시한다. “명확하고 간결하게”가 아니라 단어 수 범위, 헤딩 구조, 포함/제외할 내용을 명시한다.
출력 레이어 사양에는 품질 게이트도 포함한다: 무엇이 유효한 출력인지, 유효하지 않을 경우 모델이 어떻게 응답해야 하는지.
흔한 증상 및 해결책
증상
에이전트가 5턴까지는 안정적으로 동작하지만 10턴 이후 성능이 떨어진다.
근본 원인: 대화 기록이 예산 없이 계속 늘어난다.
해결책: 코드에 토큰 예산을 설정한다. 기록이 한계에 가까워지면 가장 오래된 턴을 압축된 에피소드 기록으로 요약하고, 요약본을 주입한 뒤 원본 턴을 삭제한다.
증상
에이전트가 만든 파라미터로 도구를 호출하거나, 작업에 맞지 않는 도구를 호출한다.
근본 원인: 도구 설명이 모호하다. 모델이 공백을 메우기 위해 설득력 있는 값을 만들어낸다.
해결책: 도구 설명에 명시적인 반조건을 추가한다. “[조건]일 때는 이 도구를 호출하지 말라”는 “[조건]일 때는 호출한다”만큼 중요하다. 입력 스키마를 필드 이름만이 아니라 정확히 명시한다.
증상
올바른 문서를 검색했음에도 모델이 틀린 답을 낸다.
근본 원인: 검색 문제가 아니라 주입 문제다. 청크 형식, 청크 크기, 컨텍스트 내 위치, 메타데이터가 모델이 검색된 내용을 활용하는 방식에 큰 영향을 미친다.
해결책: 일관된 청크 주입 형식을 사용하고, 내용 앞에 메타데이터를 붙인다.
SOURCE: [id] [relevance score] | [content]
이 형식이 원시 내용 주입보다 일관적으로 성능이 좋다. RAG 컨텍스트는 작업 지시 바로 앞에 배치하고, 뒤에 두지 않는다.
증상
세션 초반에 시스템 프롬프트 제약조건이 적용되지만 8번째 턴부터 무시된다.
근본 원인: 주의 집중 희석. 컨텍스트가 길어질수록 초기 토큰에 대한 모델의 주의가 감소한다.
해결책: 중요한 제약조건을 작업 레이어에 다시 주입한다. 장기 실행 에이전트의 경우 매 N턴마다 “제약조건 재주입 블록”을 삽입한다.
증상
에이전트가 출력은 생성했지만, 겉보기엔 타당해 보이지만 실제로는 틀렸다. 오류 신호가 없었다.
근본 원인: 생성 후 평가 단계가 없다.
해결책: 고위험 작업에서는 첫 응답을 평가하는 두 번째 LLM 호출을 추가한다. 평가 항목은 근거성, 포맷 준수, 선언된 신뢰도이다. 이는 전체 파이프라인에 비해 비용이 크지 않으며, 목표에 맞는 평가자만 호출하면 된다.
컨텍스트 창의 어텐션 예산
컨텍스트 창은 유한한 어텐션 예산을 가진다. 어텐션은 고르게 분배되지 않으며, 컨텍스트의 시작과 끝, 그리고 구조적으로 두드러진 토큰(헤더,