컨텍스트 개요 (Context)

컨텍스트 개요 (Context)

컨텍스트 엔지니어링이란

AI 애플리케이션이 작업을 수행하려면, 올바른 정보와 도구를 올바른 형식으로 제공해 주는 동적 시스템이 필요해요. 이렇게 컨텍스트를 구성하는 일을 컨텍스트 엔지니어링(context engineering) 이라고 합니다. 컨텍스트는 크게 두 가지 축으로 나눠서 볼 수 있어요.

  1. 가변성(mutability) 기준:
    • 정적 컨텍스트(static context): 실행 중에 변하지 않는 불변 데이터예요. 예를 들면 사용자 메타데이터, 데이터베이스 연결, 도구 등이 여기 속해요.
    • 동적 컨텍스트(dynamic context): 애플리케이션이 실행되면서 계속 변하는 가변 데이터예요. 대화 이력, 중간 결과, 도구 호출로 얻은 관찰값 같은 것들이죠.
  2. 수명(lifetime) 기준:
    • 런타임 컨텍스트(runtime context): 단일 실행(invocation)에 국한된 데이터예요.
    • 대화 간 컨텍스트(cross-conversation context): 여러 대화나 세션에 걸쳐 유지되는 데이터예요.

런타임 컨텍스트

런타임 컨텍스트는 지역 컨텍스트, 그러니까 코드가 실행되는 데 필요한 데이터와 의존성을 뜻해요. 헷갈리기 쉬운 두 가지와는 다릅니다.

  • LLM 컨텍스트: LLM 프롬프트에 전달되는 데이터예요.
  • 컨텍스트 창(context window): LLM에 전달할 수 있는 최대 토큰 수를 말해요.

런타임 컨텍스트는 일종의 의존성 주입(dependency injection) 입니다. 이를 잘 활용하면 LLM 컨텍스트를 최적화할 수 있어요. 데이터베이스 연결, 사용자 ID, API 클라이언트 같은 의존성을 코드에 하드코딩하지 않고, 런타임에 도구와 노드에 제공할 수 있거든요. 예를 들어 런타임 컨텍스트의 사용자 메타데이터로 사용자 선호도를 가져와 컨텍스트 창에 넣어 줄 수 있습니다.

LangGraph에서 컨텍스트 관리

LangGraph는 가변성과 수명 두 축을 결합해 컨텍스트를 관리하는 세 가지 방식을 제공해요.

컨텍스트 유형 설명 가변성 수명 접근 방법
정적 런타임 컨텍스트(static runtime context) 시작 시 전달되는 사용자 메타데이터, 도구, DB 연결 정적 단일 실행 invoke/streamcontext 인자
동적 런타임 컨텍스트 — 상태(state) 단일 실행 중에 변하는 가변 데이터 동적 단일 실행 LangGraph 상태(state) 객체
동적 대화 간 컨텍스트 — 스토어(store) 대화 간에 공유되는 영구 데이터 동적 대화 간 LangGraph 스토어

정적 런타임 컨텍스트

정적 런타임 컨텍스트는 사용자 메타데이터, 도구, 데이터베이스 연결처럼 실행 시작 시 invoke/streamcontext 인자로 애플리케이션에 전달되는 불변 데이터를 의미해요. 이 데이터는 실행 중에 변하지 않습니다.

@dataclass
class ContextSchema:
    user_name: str

graph.invoke(
    {"messages": [{"role": "user", "content": "hi!"}]},
    context={"user_name": "John Smith"}
)
  • 에이전트 프롬프트
  • 워크플로 노드
  • 도구(툴)

Runtime 객체를 통해 static context와 활성 스토어, 스트림 라이터 같은 유틸리티에 접근할 수 있어요. 자세한 내용은 Runtime 문서를 참고하세요.

에이전트 프롬프트에서

from dataclasses import dataclass
from langchain.agents import create_agent
from langchain.agents.middleware import dynamic_prompt, ModelRequest

@dataclass
class ContextSchema:
    user_name: str

@dynamic_prompt
def personalized_prompt(request: ModelRequest) -> str:
    user_name = request.runtime.context.user_name
    return f"You are a helpful assistant. Address the user as {user_name}."

agent = create_agent(
    model="claude-sonnet-4-6",
    tools=[get_weather],
    middleware=[personalized_prompt],
    context_schema=ContextSchema
)

agent.invoke(
    {"messages": [{"role": "user", "content": "what is the weather in sf"}]},
    context=ContextSchema(user_name="John Smith")
)

에이전트에 대한 자세한 내용은 Agents 문서를 참고하세요.

워크플로 노드에서

from langgraph.runtime import Runtime

def node(state: State, runtime: Runtime[ContextSchema]):
    user_name = runtime.context.user_name
    ...

Graph API 문서에서 런타임 구성 추가를 확인할 수 있어요.

도구(툴)에서

from langchain.tools import tool, ToolRuntime

@tool
def get_user_email(runtime: ToolRuntime[ContextSchema]) -> str:
    """Retrieve user information based on user ID."""
    # simulate fetching user info from a database
    email = get_user_email_from_db(runtime.context.user_name)
    return email

자세한 내용은 도구 호출 가이드를 참고하세요.

동적 런타임 컨텍스트 (상태)

동적 런타임 컨텍스트는 단일 실행 중에 변할 수 있는 가변 데이터를 의미하며, LangGraph 상태(state) 객체를 통해 관리돼요. 여기에는 대화 이력, 중간 결과, 도구나 LLM 출력에서 파생된 값이 포함됩니다. LangGraph에서 상태 객체는 실행 중 단기 기억(short-term memory) 역할을 해요.

  • 에이전트에서
  • 워크플로에서

아래 예시는 상태를 에이전트 프롬프트에 반영하는 방법을 보여줘요. 상태는 에이전트의 도구에서도 접근할 수 있는데, 도구가 필요에 따라 상태를 읽거나 갱신할 수 있습니다. 자세한 내용은 도구 호출 가이드를 참고하세요.

from langchain.agents import create_agent
from langchain.agents.middleware import dynamic_prompt, ModelRequest
from langchain.agents import AgentState

class CustomState(AgentState):
    user_name: str

@dynamic_prompt
def personalized_prompt(request: ModelRequest) -> str:
    user_name = request.state.get("user_name", "User")
    return f"You are a helpful assistant. User's name is {user_name}"

agent = create_agent(
    model="claude-sonnet-4-6",
    tools=[...],
    state_schema=CustomState,
    middleware=[personalized_prompt],
)

agent.invoke({
    "messages": "hi!",
    "user_name": "John Smith"
})
from typing_extensions import TypedDict
from langchain.messages import AnyMessage
from langgraph.graph import StateGraph

class CustomState(TypedDict):
    messages: list[AnyMessage]
    extra_field: int

def node(state: CustomState):
    messages = state["messages"]
    ...
    return {
        "extra_field": state["extra_field"] + 1
    }

builder = StateGraph(State)
builder.add_node(node)
builder.set_entry_point("node")
graph = builder.compile()

메모리 켜기 (Turning on memory)

상태를 여러 실행에 걸쳐 유지하는 메모리를 활성화하는 방법은 memory 가이드를 참고하세요. 메모리는 에이전트의 상태를 여러 호출에 걸쳐 영속화할 수 있는 강력한 기능이에요. 이 기능을 쓰지 않으면 상태는 단일 실행에만 국한됩니다.

동적 대화 간 컨텍스트 (스토어)

동적 대화 간 컨텍스트는 여러 대화나 세션에 걸쳐 유지되는 영구적이고 가변적인 데이터를 의미하며, LangGraph 스토어(store) 를 통해 관리돼요. 여기에는 사용자 프로필, 선호도, 과거 상호작용 이력이 포함됩니다. LangGraph 스토어는 여러 실행에 걸친 장기 기억(long-term memory) 역할을 해요. 이를 통해 사용자 프로필, 선호도, 이전 상호작용 같은 영구적인 사실을 읽거나 갱신할 수 있습니다.

더 알아보기 (Learn more)