Agent

2026. 4. 22. 14:25·RAG

 

Tool은 왜 필요할까?

LLM은 기본적으로 학습이 끝난 시점까지의 데이터를 바탕으로 답변을 생성한다. 그래서 최신 날씨, 실시간 주가, 오늘 일정, 현재 베스트셀러처럼 지금 시점의 외부 정보가 필요한 질문에는 한계가 있다. 이런 한계를 보완하기 위해 등장하는 것이 Tool이다. Tool을 사용하면 모델은 스스로 외부 시스템을 호출해 필요한 정보를 가져오거나, 특정 작업을 실행할 수 있다. (LangChain Docs)

Tool이란?

Tool은 모델이 외부 세계와 연결되기 위해 사용하는 인터페이스다. 쉽게 말해, 모델이 호출할 수 있는 함수라고 보면 된다. LangChain에서는 보통 callable function에 입력 스키마를 붙인 형태로 Tool을 정의하며, 이 입력 스키마는 타입 힌트로 표현된다. 또한 docstring은 “이 도구가 언제, 어떤 목적으로 쓰이는지”를 모델이 이해하는 데 중요한 역할을 한다. (LangChain Docs)

즉, Tool의 핵심은 다음 두 가지다.

  • 호출 가능한 함수
  • 그 함수가 어떤 입력을 받는지 설명하는 스키마

이 구조 덕분에 모델은 단순히 문장을 생성하는 데서 멈추지 않고, 필요할 때 검색·조회·계산·저장 같은 행동까지 수행할 수 있다. (LangChain Docs)

Tool은 어떻게 만들까?

LangChain에서 가장 기본적인 Tool 정의 방식은 @tool 데코레이터를 사용하는 것이다. 함수에 타입 힌트와 docstring을 붙이고 @tool을 적용하면, 에이전트가 사용할 수 있는 Tool로 변환된다. 공식 문서에서도 가장 단순한 Tool 정의 방법으로 이 패턴을 안내한다. (LangChain Docs)

from langchain.tools import tool

@tool
def get_weather(location: str) -> str:
    """특정 지역의 날씨 정보를 반환합니다."""
    return f"오늘 {location} 날씨는 비가 옵니다."

여기서 중요한 점은, 위 예시는 개념 설명용 예시라는 것이다. 실제 날씨를 조회하는 것이 아니라, 입력받은 지역명을 문자열에 끼워 넣어 반환하는 단순한 형태다. 즉, Tool이 자동으로 최신 정보를 만들어내는 것이 아니라, Tool 내부에서 실제 외부 API나 데이터베이스를 호출해야 진짜 동적 동작이 가능하다. (LangChain Docs)

Tool과 모델을 연결하면 Agent가 된다

Tool을 정의한 뒤에는 모델과 함께 에이전트를 만들 수 있다. LangChain의 create_agent는 모델과 Tool 목록을 받아 에이전트를 생성하며, 이때 전달한 Tool들은 기본적으로 정적으로 등록된 도구 집합으로 동작한다. 즉, 에이전트는 이 목록 안에서 필요한 Tool을 골라 호출한다. (LangChain Docs)

from langchain.agents import create_agent
from langchain.chat_models import init_chat_model

model = init_chat_model("gpt-5-nano")
agent = create_agent(model, tools=[get_weather])

이후 invoke()로 메시지를 넘기면, 에이전트는 현재 질문에 대해 Tool이 필요한지 판단하고, 필요하다고 보면 Tool을 호출한 뒤 그 결과를 바탕으로 최종 응답을 만든다. LangChain 문서에서도 에이전트의 기본 루프를 모델 호출 → Tool 실행 → 다시 모델 호출의 반복 구조로 설명한다. (LangChain Docs)

result = agent.invoke({
    "messages": [
        {"role": "user", "content": "서울 날씨 어때요?"}
    ]
})

print(result["messages"][-1].content)

위 코드에서 result["messages"][-1].content를 출력하는 이유는 실행이 끝난 뒤 가장 마지막 메시지, 즉 최신 응답 내용을 확인하기 위해서다. 보통 이 값은 최종 assistant 응답이며, Tool이 실제로 어떤 값을 주고받았는지 자세히 보려면 전체 messages 흐름을 함께 확인하는 것이 더 정확하다. 에이전트 상태는 messages를 중심으로 관리된다. (LangChain Docs)

그런데 Agent가 Tool을 안 쓸 수도 있다

여기서 한 가지 중요한 점이 있다. 에이전트를 만들었다고 해서 모델이 항상 Tool을 호출하는 것은 아니다. 어떤 질문은 모델이 내부 지식만으로도 답할 수 있다고 판단할 수 있고, 이 경우 Tool 없이 바로 응답을 생성할 수도 있다. 그래서 특정 작업에서 Tool 사용을 더 강하게 유도하고 싶다면 system prompt를 통해 행동 원칙을 명시하는 경우가 많다. 다만 이것은 “경향을 강하게 주는 것”이지, 모든 상황에서 절대적으로 보장하는 장치는 아니다. (LangChain Docs)

agent = create_agent(
    model,
    tools=[get_weather],
    system_prompt="추측하지 말고, 필요한 경우 반드시 tool을 사용하여 답변하시오."
)

이런 방식은 특히 계산, 검색, 조회처럼 정확한 근거가 필요한 작업에서 유용하다. 모델이 추측으로 답하기보다 실제 도구를 쓰도록 유도할 수 있기 때문이다. (LangChain Docs)

실전에서는 외부 API와 연결된다

Tool의 진짜 가치는 외부 시스템과 연결될 때 드러난다. 예를 들어 베스트셀러 목록을 알려주는 Tool은 내부에 고정된 문자열을 반환하는 대신, 서점 API에 요청을 보내고 그 결과를 다시 에이전트가 활용하도록 만들 수 있다. 이렇게 하면 모델은 학습 데이터에 없는 최신 정보도 사용할 수 있다. Tool은 결국 LLM의 지식을 확장하는 장치이자, LLM이 행동할 수 있게 만드는 수단이라고 볼 수 있다. (LangChain Docs)

from langchain.tools import tool
from typing import List, Dict, Any
import requests

@tool
def fetch_aladin_bestseller_top10() -> List[Dict[str, Any]]:
    """알라딘 베스트셀러 Top 10을 조회합니다."""
    url = "http://www.aladin.co.kr/ttb/api/ItemList.aspx"
    params = {
        "ttbkey": "YOUR_KEY",
        "QueryType": "Bestseller",
        "MaxResults": 10,
        "start": 1,
        "SearchTarget": "Book",
        "output": "js",
        "Version": "20131101"
    }
    resp = requests.get(url, params=params)
    resp.raise_for_status()
    return resp.json().get("item", [])[:10]

이제 에이전트는 “현재 알라딘 베스트셀러 Top 10이 뭐야?” 같은 질문에 대해, 단순히 기억을 기반으로 대답하는 것이 아니라 실제 데이터를 조회한 뒤 응답할 수 있다. 바로 이 점이 Tool의 핵심적인 필요성이다. (LangChain Docs)

메모리 기반 에이전트는 왜 필요할까?

단일 질의응답만 처리할 때는 Tool만 있어도 충분할 수 있다. 하지만 여러 번 대화를 주고받는 환경에서는, 이전 대화 맥락을 기억한 상태로 Tool을 호출해야 더 자연스럽고 정확한 응답이 가능하다. LangChain 문서에서도 short-term memory를 같은 대화 스레드 안에서 이전 상호작용을 기억하는 기능으로 설명한다. (LangChain Docs)

예를 들어 사용자가 처음에는 “내 이름은 Jay야”라고 말하고, 다음 턴에서 “내 일정 정리해줘”라고 요청할 수 있다. 이때 에이전트가 이전 정보를 기억하고 있으면, 단순한 응답 생성뿐 아니라 Tool 호출 시에도 더 일관된 문맥을 유지할 수 있다. (LangChain Docs)

단기 메모리: Checkpointer

LangChain의 short-term memory는 보통 checkpointer를 통해 구현한다. 체크포인터는 대화 상태를 저장하는 장치이며, thread_id를 기준으로 같은 대화 스레드의 문맥을 이어간다. 공식 문서에서는 InMemorySaver()를 예시 checkpointer로 사용하며, 에이전트 생성 시 checkpointer 인자로 전달하도록 안내한다. (LangChain Docs)

from langchain.agents import create_agent
from langgraph.checkpoint.memory import InMemorySaver

agent = create_agent(
    model,
    tools=[get_weather],
    checkpointer=InMemorySaver(),
)

cfg = {"configurable": {"thread_id": "1"}}

response = agent.invoke(
    {"messages": [{"role": "user", "content": "안녕하세요! 저는 Bloom AI의 Jay 입니다."}]},
    cfg,
)
print(response["messages"][-1].content)

같은 thread_id를 유지하면, 이후 호출에서도 이전 대화 맥락이 이어진다. 즉, short-term memory는 “한 대화 안에서 이어지는 기억”이라고 이해하면 된다. (LangChain Docs)

장기 메모리: Store

short-term memory가 같은 스레드 안의 기억이라면, long-term memory는 대화가 달라져도 유지되는 기억이다. LangChain에서는 long-term memory를 store 기반으로 관리하며, 서로 다른 세션이나 스레드 사이에서도 사용자 정보나 애플리케이션 수준의 데이터를 저장하고 불러올 수 있다. 공식 문서에 따르면 long-term memory는 LangGraph store 위에 구축되며, JSON 문서 형태로 namespace와 key 기준으로 저장된다. (LangChain Docs)

즉, 단기 메모리는 “지금 이 대화에서의 기억”, 장기 메모리는 “여러 대화에 걸쳐 유지되는 기억”이라고 정리할 수 있다. 둘을 함께 사용하면 에이전트는 더 개인화되고 연속성 있는 상호작용을 제공할 수 있다. (LangChain Docs)

마무리

정리하면, Tool은 단순히 “함수 하나 붙이는 기능”이 아니다. Tool은 LLM이 외부 세계와 연결되도록 만드는 핵심 장치다. 이를 통해 모델은 학습 시점 이후의 정보도 다룰 수 있고, 검색·조회·계산·저장 같은 실제 행동도 수행할 수 있다. 그리고 여기에 메모리까지 결합되면, 에이전트는 이전 대화를 기억하면서 더 자연스럽고 일관되게 Tool을 사용할 수 있게 된다. (LangChain Docs)

결국 LLM 애플리케이션이 “정해진 흐름 속에서 모델을 활용하는 시스템”이라면, Agent는 “필요한 Tool을 스스로 선택하고, 메모리를 활용해 행동하는 시스템”이라고 볼 수 있다. Tool은 그 Agent를 가능하게 만드는 가장 중요한 구성 요소 중 하나다. (LangChain Docs)


원하면 다음엔 이 글을 더 다듬어서 초보자용 블로그 톤으로 바꾸거나, 코드 위주 실습형 포스트 형태로 다시 정리해주겠다.

'RAG' 카테고리의 다른 글

LLM Application - Langchain  (1) 2026.04.22
'RAG' 카테고리의 다른 글
  • LLM Application - Langchain
Juson
Juson
  • Juson
    Juson의 데이터 공부
    Juson
  • 전체
    오늘
    어제
    • 분류 전체보기 (95)
      • RAG (2)
      • AI (2)
        • NLP (0)
        • Generative Model (0)
        • Deep Reinforcement Learning (2)
        • LLM (0)
      • Logistic Optimization (0)
      • Machine Learning (37)
        • Linear Regression (2)
        • Logistic Regression (2)
        • Decision Tree (5)
        • Naive Bayes (1)
        • KNN (2)
        • SVM (2)
        • Clustering (4)
        • Dimension Reduction (3)
        • Boosting (6)
        • Abnomaly Detection (2)
        • Recommendation (4)
        • Embedding & NLP (4)
      • Reinforcement Learning (5)
      • Deep Learning (10)
        • Deep learning Bacis Mathema.. (10)
      • Optimization (2)
        • OR Optimization (0)
        • Convex Optimization (0)
        • Integer Optimization (0)
      • SNA 분석 (0)
      • 포트폴리오 최적화 공부 (0)
        • 최적화 기법 (0)
        • 금융 베이스 (0)
      • Finanancial engineering (0)
      • 프로그래머스 데브코스(Boot camp) (15)
        • SQL (9)
        • Python (5)
        • Machine Learning (1)
      • Python (22)
      • Project (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
Juson
Agent
상단으로

티스토리툴바