Menu

컨텍스트 엔지니어링이란? 모델이 보는 것 설계하기

컨텍스트 엔지니어링은 호출마다 모델의 컨텍스트 윈도우에 들어가는 모든 것, 즉 지시, 문서, 도구 결과, 메모리, 대화 기록과 그 순서를 정하는 일입니다. 여러분이 입력하는 프롬프트는 그중 일부일 뿐입니다.

이 페이지의 모든 프롬프트는 수정한 뒤 ChatGPT, Claude 등 AI 앱에서 바로 열 수 있습니다.

컨텍스트 엔지니어링은 언어 모델이 답할 때 보는 모든 것을 정하는 작업입니다. 여러분이 입력한 질문뿐 아니라, 그 주변의 지시, 거기에 들어간 문서와 도구 결과, 사용자에 대해 저장된 메모리, 지금까지의 대화까지입니다. 이 모든 것이 하나의 컨텍스트 윈도우를 나눠 쓰고, 모델은 그 텍스트로만 답합니다. 이 용어는 더 많은 AI 제품이 컨텍스트 대부분을 자동으로 조립하는 에이전트가 되면서 2025년에 퍼졌습니다.

프롬프트 엔지니어링은 주로 요청을 어떻게 표현할지에 관한 것입니다. 컨텍스트 엔지니어링은 호출마다 모델 앞에 무엇을 어떤 순서로 둘지에 관한 것입니다.

프롬프트에서 컨텍스트로

채팅 앱에서는 컨텍스트 대부분을 여러분이 직접 씁니다. 앱이 시스템 프롬프트와 대화 기록을 더하고, 나머지는 여러분이 더합니다. 애플리케이션에서는 이 균형이 뒤집힙니다. 사용자는 한 문장을 입력하고, 모델을 둘러싼 코드가 지시, 사용자 프로필, 검색으로 찾은 도움말 세 개, 사용할 수 있는 도구 목록, 마지막 도구 호출의 출력을 더합니다. 사용자의 문장은 모델이 읽는 것의 작은 일부일 수 있습니다.

이런 시스템이 나쁜 답을 낼 때, 해결책이 표현에 있는 경우는 드뭅니다. 흔한 원인은 모델이 잘못된 자료를 가졌다는 것입니다. 빠진 사실, 오래된 도구 결과, 검색에는 관련 있어 보였지만 실제로는 무관한 문서 같은 것들입니다.

컨텍스트 윈도우에 들어가는 것

AI 애플리케이션의 전형적인 호출에는 다음 중 일부나 전부가 대략 이 순서로 들어갑니다.

  • 시스템 지시: 역할, 규칙, 출력 형식으로, 보통 앱 전체에서 고정됩니다. 시스템 프롬프트를 참고하세요.
  • 도구 정의: 모델이 호출할 수 있는 도구의 이름, 설명, 매개변수.
  • 예시: 기대하는 동작을 보여 주는 입력과 출력 샘플 몇 개.
  • 메모리: 사용자의 요금제, 언어, 선호처럼 이전 세션에서 저장한 사실.
  • 검색한 문서: 이 질문을 위해 지식 베이스를 검색해서 찾은 구절(검색 증강 생성, RAG).
  • 대화 기록: 이전 턴으로, 그대로 넣거나 요약해서 넣습니다.
  • 도구 결과: ReAct 루프에서처럼 이 작업 중에 한 검색, 코드 실행, API 호출의 출력.
  • 현재 메시지: 사용자가 방금 물은 것.

아래 블록은 고객지원 어시스턴트를 위해 조립한 컨텍스트 하나입니다. 부분을 하나씩 꺼 보세요. 맥락 부분이 없으면 모델은 고객의 요금제를 알 수 없고, 입력 부분이 없으면 제품 정보가 없는데, 제약 조건이 추측하지 말고 그렇다고 말하라고 지시합니다.

고객지원 어시스턴트의 컨텍스트
Parts
너는 메모 앱 Acme Notes의 고객지원 어시스턴트야.
아래 문서로만 답해. 문서가 질문을 다루지 않으면 그렇다고 말하고 상담원 연결을 제안해. 기능이나 가격에 대해 절대 추측하지 마.
고객 메모리: 이름 다나, 무료 요금제, 안드로이드 앱 사용.
<document source="help/offline-mode"> 오프라인 모드는 Pro 요금제에서 쓸 수 있습니다. 오프라인에서 만든 메모는 기기가 다시 연결되면 동기화됩니다. 20MB보다 큰 첨부 파일은 오프라인에서 쓸 수 없습니다. </document> <document source="help/plans"> 무료 요금제: 기기 최대 3대. Pro 요금제: 기기 무제한, 오프라인 모드, 30일간의 버전 기록. </document>
쉬운 말로 두세 문장, 많아야 네 문장. 고객의 이름을 불러 줘.
고객 질문: 인터넷 없이 비행기에서 앱을 쓸 수 있나요?
Try it
Example replyReplies vary between models and runs.

다나 님, 오프라인 모드는 Pro 요금제에 포함된 기능인데 현재 계정이 무료 요금제라서 지금은 쓰실 수 없어요. Pro에서는 비행 중에 만든 메모가 휴대폰이 다시 연결되면 자동으로 동기화됩니다. 알아 두실 제한이 하나 있는데, 20MB보다 큰 첨부 파일은 오프라인에서 쓸 수 없어요.

올바른 답은 두 출처를 합쳐야 나온다는 점을 눈여겨보세요. 메모리(무료 요금제)와 문서(오프라인 모드는 Pro 전용)입니다. 어느 하나만으로는 부족한데, 이것이 전형적인 경우입니다. 컨텍스트 엔지니어링의 많은 부분은 서로를 필요로 하는 조각들이 함께 도착하게 하는 것입니다.

컨텍스트가 잘못되는 네 가지 경우

  1. 정보가 빠짐. 모델은 빈틈을 그럴듯한 추측으로 채우고, 많은 할루시네이션이 여기서 나옵니다. 사실을 더하거나, 사실이 없을 때 무엇을 할지 모델에게 알려 주세요.
  2. 자료가 너무 많음. 관련 없는 문단 하나하나가 토큰을 쓰고 주의를 두고 경쟁합니다. Liu 등의 2023년 논문 "Lost in the Middle: How Language Models Use Long Contexts"는 테스트한 모델들이 긴 입력의 중간에 있는 정보보다 처음이나 끝에 있는 정보를 더 안정적으로 활용한다는 것을 발견했습니다. 최신 모델은 긴 입력을 더 잘 다루지만, 질문에 답하는 구절 몇 개만 보내는 것이 매뉴얼 전체를 붙여 넣는 것보다 여전히 싸고, 모델이 쓰기에도 쉽습니다.
  3. 오래된 정보. 열 단계 전의 도구 결과는 그 뒤로 바뀐 파일이나 잔액을 설명하고 있을 수 있습니다. 모델이 두 버전을 모두 보면 오래된 것을 쓸 수 있습니다.
  4. 충돌. 두 문서가 서로 다르거나, 메모리와 사용자의 말이 다를 수 있습니다. "사용자의 최신 메시지가 저장된 메모리보다 우선한다"처럼 어느 출처가 이기는지 모델에게 알려 주세요.

컨텍스트의 순서 정하기

순서는 결과와 비용을 모두 바꿉니다.

  • 변하지 않는 부분을 먼저. 시스템 지시, 도구 정의, 고정된 참고 자료는 호출 사이에 거의 바뀌지 않습니다. 여러 API 제공사가 프롬프트 캐싱을 제공하는데, 입력의 똑같은 앞부분에 대한 처리를 재사용하는 기능이라서 변하지 않는 앞부분이 있으면 반복 호출이 더 싸고 빨라집니다.
  • 긴 자료는 질문 앞에. 긴 문서나 많은 구절은 자료를 먼저 두고 질문과 마지막 지시를 그 뒤에 두세요. 예를 들어 Anthropic의 프롬프트 가이드는 긴 입력에 이 순서를 권장하며, 질문이 모델이 쓰기 시작하기 바로 앞에 오게 합니다.
  • 모든 조각에 이름을 붙이세요. 각 출처를 출처 이름과 함께 <document>, <memory>, <tool_result> 같은 태그로 감싸세요. 이름표가 있으면 모델이 데이터와 지시를 구분할 수 있고, 여러분은 답이 어디서 왔는지 인용하라고 요청할 수 있습니다. 형식은 구분자와 XML 태그에서 다룹니다.

긴 컨텍스트 줄이기

채팅의 매 턴은 대화 기록 전체를 다시 보내므로, 긴 세션은 무언가를 버려야 할 때까지 커집니다. 앱에 따라 오래된 메시지를 요약하거나 버리거나, 새 대화를 시작하라고 합니다. 의도적으로 줄이면 더 좋은 결과를 얻습니다.

  • 마지막 몇 턴은 그대로 두고, 그보다 오래된 턴은 요약으로 바꾸세요.
  • 도구 결과를 쓰고 나면, 그 결과가 보여 준 것을 한 줄로 적은 메모로 바꾸세요.
  • 모든 요약에 정확한 식별자를 남기세요. 파일 이름, 함수 이름, ID, 에러 메시지, 숫자입니다. 기록에 settings.prod.yaml이라고 되어 있던 것을 "설정 파일"이라고 적은 요약은 가장 중요했던 세부 사항 하나를 잃어버립니다.
  • 채팅 앱에서 대화가 흐트러지면 인수인계 메모와 함께 새 대화를 시작하세요. 아래 프롬프트가 그 메모를 씁니다.
긴 대화를 압축해 새로 시작하기
Fill in
이 대화가 길어지고 있어. 새 대화에 붙여 넣어서 기록 없이도 작업을 이어 갈 수 있도록 인수인계 메모를 써 줘. 다음을 포함해 줘: 1. 회원가입 폼 리팩터링의 목표를 한 문장으로. 2. 우리가 내린 결정과 각각의 이유. 3. 현재 상태: 무엇이 동작하고 무엇이 미완성인지. 4. 중요한 정확한 이름: 파일, 함수, 에러 메시지, 숫자. 정확히 그대로 옮겨 적어. 5. 남은 질문과 다음 단계. 결정을 설명하는 경우가 아니면 막다른 길은 빼 줘. 최대 500자.
Try it
Example replyReplies vary between models and runs.

목표: 회원가입 폼의 직접 작성한 검사 로직을 브라우저와 서버가 함께 쓰는 공통 검증 스키마 하나로 바꾼다.

결정 사항

  1. 스키마 파일은 signupSchema.ts 하나로 두고 SignupForm.tsx와 api/signup.ts가 가져다 쓴다. 두 규칙이 따로 놀지 않게 하기 위해서다.
  2. 에러 메시지는 한 글자도 바꾸지 않는다. 도움말 센터에서 그대로 인용하기 때문이다.

현재 상태

  1. 브라우저 검증은 스키마를 쓰고 있고 SignupForm.test.tsx는 통과한다.
  2. 서버는 아직 api/signup.ts의 예전 validateSignup()을 호출한다.

정확한 세부 사항: 비밀번호는 최소 8자, 숫자 하나 이상. 이메일 에러 문구: "올바른 이메일 주소를 입력해 주세요."

다음 단계: validateSignup()을 스키마로 바꾸고 API 테스트를 실행한다.

남은 질문: 이미 가입된 이메일에는 409를 돌려줄까, 400을 돌려줄까?

세션을 넘는 메모리

메모리는 대화보다 오래 사는 컨텍스트입니다. 한 세션이 끝날 때 저장소에 기록된 사실이 다음 세션에 불러와집니다. 채팅 앱은 저장된 메모리나, 프로젝트 안의 모든 대화에 더해지는 프로젝트 지침 같은 형태로 이를 제공합니다. 직접 만드는 애플리케이션에서 메모리는 코드가 읽어서 넣는 테이블이나 메모 파일입니다. 메모리를 쓸모 있게 유지하는 규칙이 두 가지 있습니다. 대화 기록이 아니라 계속 참인 사실(요금제, 언어, 선호하는 기술 스택)을 저장하세요. 그리고 현재 작업에 관련된 것만 불러오세요. 메모리도 다른 모든 것과 같은 공간을 두고 경쟁하기 때문입니다.

코드로 컨텍스트 조립하기

애플리케이션에서 컨텍스트 엔지니어링은 평범한 코드입니다. Anthropic Python SDK를 쓴 이 예시는 고정된 규칙과 메모리를 시스템 프롬프트에 넣고, 최근 기록만 남기고, 이름 붙인 문서를 질문 앞에 둡니다.

import anthropic

client = anthropic.Anthropic()
MODEL = "your-model-id"  # e.g. from your provider's model list

def build_context(question, docs, history, memory, max_messages=6):
    documents = "\n".join(
        f'<document source="{d["source"]}">\n{d["text"]}\n</document>' for d in docs
    )
    system = (
        "You are the support assistant for Acme Notes. Answer only from the documents. "
        "If they do not cover the question, say so.\n"
        f"<memory>\n{memory}\n</memory>"
    )
    # history holds complete user/assistant pairs, so an even slice starts with a user turn
    recent = history[-max_messages:]
    user = f"<documents>\n{documents}\n</documents>\n\n{question}"
    return system, recent + [{"role": "user", "content": user}]

# question, docs, history and memory come from your application
system, messages = build_context(question, docs, history, memory)
response = client.messages.create(model=MODEL, max_tokens=1024, system=system, messages=messages)
print(response.content[0].text)

이 함수의 결정 하나하나(어떤 문서를, 메시지를 몇 개, 메모리를 어디에)가 컨텍스트 엔지니어링의 선택이고, 표현을 바꿀 때 테스트하는 것과 똑같이 실제 질문으로 테스트해 볼 가치가 있습니다.

자주 묻는 질문

컨텍스트 엔지니어링이란 무엇인가요?

컨텍스트 엔지니어링은 언어 모델이 호출마다 받는 모든 것을 고르고, 배치하고, 줄이는 작업입니다. 시스템 지시, 예시, 검색한 문서, 도구 정의와 결과, 저장된 메모리, 대화 기록, 사용자의 메시지가 여기에 포함됩니다. 모델은 그 텍스트로만 답하므로, 무엇이 들어가고 무엇이 빠지는지가 답의 품질을 결정합니다.

컨텍스트 엔지니어링과 프롬프트 엔지니어링은 어떻게 다른가요?

프롬프트 엔지니어링은 주로 지시를 어떻게 표현할지에 관한 것입니다. 컨텍스트 엔지니어링은 입력 전체를 다루는데, 그 대부분은 사람이 입력하는 것이 아니라 코드가 조립합니다. 어떤 문서를 검색할지, 어떤 도구 결과를 남길지, 대화 기록을 얼마나 어떤 순서로 넣을지입니다. 채팅에서는 컨텍스트 대부분을 여러분이 직접 쓰고, 앱이나 에이전트에서는 대부분을 모델을 둘러싼 시스템이 고릅니다.

컨텍스트는 많을수록 좋은가요?

아니요. 관련 없거나 오래된 자료는 중요한 부분과 경쟁하고, 토큰을 쓰고, 현재 상태와 모순될 수 있습니다. 긴 입력에 대한 연구에서는 모델이 긴 컨텍스트의 중간에 놓인 정보를 놓칠 수 있다는 것이 발견되었습니다. 작업에 필요한 것을 넣고, 이름을 붙이고, 더 이상 필요 없는 것은 빼세요.

긴 대화는 왜 시간이 지날수록 나빠지나요?

매 턴마다 대화 전체가 다시 전송되므로, 예전의 실수, 버린 아이디어, 대체된 코드가 컨텍스트에 남아 계속 답변에 영향을 줍니다. 대화가 컨텍스트 윈도우를 넘으면 앱은 오래된 메시지를 버리거나 요약해야 합니다. 결정 사항과 현재 상태를 짧게 요약해서 새 대화를 시작하는 편이 계속 이어 가는 것보다 나은 경우가 많습니다.

컨텍스트 엔지니어링에서 RAG란 무엇인가요?

RAG(검색 증강 생성)는 질문과 관련된 구절을 여러분의 문서에서 검색해서, 모델이 답하기 전에 컨텍스트에 넣는 것입니다. 컨텍스트 엔지니어링의 주요 도구 중 하나로, 모델이 학습만으로는 알 수 없는 최신의 구체적인 사실을 얻고, 여러분은 그 구절로만 답하라고 지시할 수 있습니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기