티스토리 뷰
Tool Calling이 진짜 중요한 이유 — LLM이 답변만 하는 걸 넘어서 외부 기능을 쓰게 만드는 방법
octo54 2026. 4. 10. 12:28Tool Calling이 진짜 중요한 이유 — LLM이 답변만 하는 걸 넘어서 외부 기능을 쓰게 만드는 방법
RAG까지 오면 한 번 이런 생각이 듭니다.
“이제 문서도 찾고, 답도 하네. 그럼 거의 다 된 거 아닌가?”
근데 막상 서비스로 가면 바로 한계가 보입니다.
사용자가 묻는 건 꼭 “설명”만이 아니거든요.
- 오늘 환율 알려줘
- 내 주문 상태 조회해줘
- 이 숫자들 평균 계산해줘
- 이 API에서 최신 데이터 가져와줘
- 사용 가능한 일정 찾아줘
이건 문서 검색만으로는 안 됩니다.
왜냐면 여기서는 지식을 말하는 것이 아니라, 외부 기능을 실제로 써야 하기 때문이죠.
그래서 Tool Calling이 중요합니다.
LangChain 문서는 tools를 “에이전트가 할 수 있는 일을 확장하는 장치”로 설명하고, 실시간 데이터 조회, 코드 실행, 외부 데이터베이스 질의, 실제 액션 수행까지 가능하게 만든다고 안내합니다. 또 create_agent는 LangChain v1에서 에이전트를 만드는 표준 방식이고, tools는 일반 Python 함수나 @tool로 감싼 함수로 줄 수 있다고 설명해요. (LangChain Docs)
왜 Tool Calling이 필요한가
LLM은 기본적으로 “생성”에는 강합니다.
설명하고, 요약하고, 문장을 정리하는 건 잘하죠.
그런데 아래는 못 합니다.
- 지금 시각의 날씨를 스스로 확인하기
- 내 서비스 DB를 직접 조회하기
- 계산 결과를 100% 정확하게 보장하기
- 내부 API를 호출해 최신 상태를 가져오기
이런 건 모델이 “생각해서 아는” 게 아니라,
도구를 불러서 확인해야 하는 일입니다.
OpenAI도 Responses API를 agentic loop로 설명하면서, 한 번의 요청 안에서 web search, file search, code interpreter, custom functions 같은 여러 도구를 호출할 수 있다고 안내합니다. LangChain 역시 tools를 통해 모델이 대화 맥락에 따라 언제 도구를 부를지, 어떤 인자를 넣을지 결정한다고 설명합니다. (OpenAI Developers)
즉, Tool Calling은 이렇게 이해하면 됩니다.
LLM이 “답변 생성기”에서 “판단 후 실행하는 시스템”으로 넘어가는 순간
이게 진짜 큽니다.
오늘 글에서 얻어갈 것
이번 글은 딱 이 흐름으로 갑니다.
- Tool이 정확히 뭔지
- 왜 RAG 다음에 Tool Calling을 배우는 게 좋은지
- LangChain에서 @tool과 create_agent로 가장 작은 예제를 만드는 법
- 언제 tool이 필요하고, 언제 그냥 체인으로 충분한지
1. Tool은 결국 “설명 가능한 함수”다
처음엔 tool이라는 말이 커 보이는데,
막상 구현은 생각보다 소박합니다.
LangChain 문서 기준으로 tool은 잘 정의된 입력과 출력을 가진 callable function입니다. 그리고 그 함수의 이름, 설명, 인자 이름이 모델 프롬프트의 일부가 되기 때문에, 문서화가 중요하다고 안내합니다. @tool 데코레이터는 이 metadata를 붙이고 런타임 주입 같은 기능도 지원합니다. (LangChain Docs)
그러니까 tool은 쉽게 말하면 이런 거예요.
- Python 함수 하나를 만든다
- 함수 이름과 설명을 잘 적는다
- 모델이 필요할 때 그 함수를 호출하게 한다
즉, “복잡한 AI 기술”이라기보다
모델이 사용할 수 있게 노출된 함수 인터페이스에 가깝습니다.
2. RAG와 Tool Calling은 뭐가 다를까
여기서 많이 헷갈립니다.
RAG
- 문서를 찾는다
- 문서를 읽게 한다
- 문서를 근거로 답하게 한다
Tool Calling
- 외부 기능을 실행한다
- 결과를 받아온다
- 그 결과를 바탕으로 답하거나 다음 행동을 한다
예를 들어:
“우리 정책 문서에서 환불 규정 알려줘”
→ RAG가 잘 맞습니다.
“내 주문번호 1234 환불 가능 상태 확인해줘”
→ 문서만으로 안 됩니다. 주문 조회 API 같은 tool이 필요합니다.
LangChain의 RAG 가이드도 검색과 생성을 결합하는 구조를 설명하고, Agents 문서는 tools를 plain Python functions 또는 coroutines로 줄 수 있다고 설명합니다. (LangChain Docs)
즉:
RAG는 지식을 찾는 기술
Tool Calling은 기능을 실행하는 기술
둘은 경쟁 관계가 아니라, 서비스에서는 자주 같이 붙습니다.
3. 가장 작은 예제부터 시작해보자
처음엔 외부 API까지 바로 붙이지 말고,
mock tool로 시작하는 게 좋습니다.
예를 들어 “환율 조회” tool을 하나 만들겠습니다.
실제 API 호출 대신, 학습용으로 고정 값을 반환하게 할게요.
설치
pip install -U langchain langchain-openai
코드
import os
from langchain.agents import create_agent
from langchain.tools import tool
@tool
def get_exchange_rate(base: str, quote: str) -> str:
"""Get the exchange rate for a currency pair like USD/KRW or EUR/USD."""
mock_rates = {
("USD", "KRW"): 1380.5,
("EUR", "USD"): 1.09,
("JPY", "KRW"): 9.2,
}
rate = mock_rates.get((base.upper(), quote.upper()))
if rate is None:
return f"No exchange rate data for {base.upper()}/{quote.upper()}."
return f"The exchange rate for {base.upper()}/{quote.upper()} is {rate}."
def main() -> None:
if not os.environ.get("OPENAI_API_KEY"):
raise ValueError("OPENAI_API_KEY 환경변수가 설정되어 있지 않습니다.")
agent = create_agent(
model="openai:gpt-4o-mini",
tools=[get_exchange_rate],
system_prompt=(
"You are a helpful finance assistant. "
"Use the exchange-rate tool when the user asks for a currency rate. "
"Do not invent rates."
),
)
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "USD를 KRW로 바꾸면 환율이 얼마인지 알려줘.",
}
]
}
)
print(result["messages"][-1].content)
if __name__ == "__main__":
main()
LangChain Agents 문서는 create_agent에 tools를 넘겨 정적 도구를 구성하는 방식을 보여주고, tools는 plain Python functions나 @tool 데코레이터를 쓴 함수로 줄 수 있다고 설명합니다. Quickstart 예시도 create_agent(model=..., tools=[...], system_prompt=...)와 agent.invoke({"messages": [...]}) 패턴을 보여줘요. (LangChain Docs)
4. 이 코드가 실제로 하는 일
이 코드를 보면 구조가 꽤 단순합니다.
@tool
이 함수가 모델이 사용할 수 있는 도구라는 뜻입니다.
도구 이름, 설명, 인자 정보가 모델에게 전달됩니다. LangChain은 tool의 이름, 설명, argument names가 모델 프롬프트 일부가 된다고 설명합니다. (LangChain Docs)
create_agent(...)
LangChain v1에서 에이전트를 만드는 표준 방식입니다. create_agent는 더 단순한 인터페이스로 에이전트를 만들게 해주고, 내부적으로 LangGraph 기반 구조를 사용합니다. (LangChain Docs)
agent.invoke(...)
사용자 메시지를 넣으면,
모델은 질문을 보고 “이건 tool을 써야 하는 질문인가?”를 판단합니다.
- 써야 하면 tool 호출
- 결과를 받음
- 최종 답변 생성
즉, 모델이 직접 환율을 아는 척하는 게 아니라
필요한 순간 함수를 호출해서 확인하는 흐름입니다.
5. 왜 tool 설명이 그렇게 중요한가
이거 진짜 중요합니다.
LangChain 문서도 tools should be well-documented라고 아주 직접적으로 말합니다.
이름, 설명, 인자 이름이 모델 프롬프트 일부가 되기 때문이죠. (LangChain Docs)
예를 들어 이런 tool은 별로입니다.
@tool
def x(a: str, b: str) -> str:
return "..."
모델 입장에서는:
- 이게 뭘 하는지
- 언제 써야 하는지
- a, b가 무슨 뜻인지
잘 모릅니다.
반면 이런 식이면 훨씬 낫습니다.
@tool
def get_exchange_rate(base: str, quote: str) -> str:
"""Get the exchange rate for a currency pair like USD/KRW or EUR/USD."""
이러면 모델이 판단하기 쉬워져요.
그래서 tool calling 품질은
모델 성능만이 아니라 tool schema 설계 품질에도 크게 좌우됩니다.
6. Tool Calling이 그냥 체인보다 좋은 경우
항상 agent를 쓸 필요는 없습니다.
이건 솔직하게 말해야 해요.
그냥 체인으로 충분한 경우
- 입력이 정해져 있다
- 실행 순서가 고정되어 있다
- tool 호출 여부를 모델이 판단할 필요가 없다
예:
- 항상 문서 검색 후 답변
- 항상 JSON 응답 생성
- 항상 텍스트 요약
Tool Calling이 좋은 경우
- 사용자 질문에 따라 어떤 기능이 필요한지 달라진다
- 때로는 tool이 필요하고, 때로는 필요 없다
- 여러 tool 중 무엇을 쓸지 모델이 선택해야 한다
예:
- 계산할지, 문서를 찾을지, DB를 조회할지 질문마다 다름
- “오늘 날씨”면 weather tool
- “정책 규정”이면 RAG
- “총합 계산”이면 calculator tool
LangChain 문서도 simple queries에는 two-step RAG chain이 빠르고 효과적일 수 있고, 더 일반적인 구현에는 agent가 tool을 실행하는 RAG agent가 적합하다고 설명합니다. (LangChain Docs)
즉, “항상 agent가 정답”은 아닙니다.
하지만 질문에 따라 분기되는 서비스에서는 tool calling이 확실히 강합니다.
7. 두 개 이상의 tool을 붙이면 진짜 감이 온다
이제 조금 더 현실적인 예제로 가보겠습니다.
이번엔 두 개를 붙일게요.
- 계산기 tool
- 환율 조회 tool
import os
from langchain.agents import create_agent
from langchain.tools import tool
@tool
def calculate(expression: str) -> str:
"""Calculate a simple arithmetic expression like '120 * 3 + 5'."""
try:
result = eval(expression, {"__builtins__": {}}, {})
return f"Result: {result}"
except Exception as e:
return f"Calculation error: {e}"
@tool
def get_exchange_rate(base: str, quote: str) -> str:
"""Get the exchange rate for a currency pair like USD/KRW or EUR/USD."""
mock_rates = {
("USD", "KRW"): 1380.5,
("EUR", "USD"): 1.09,
("JPY", "KRW"): 9.2,
}
rate = mock_rates.get((base.upper(), quote.upper()))
if rate is None:
return f"No exchange rate data for {base.upper()}/{quote.upper()}."
return f"The exchange rate for {base.upper()}/{quote.upper()} is {rate}."
def main() -> None:
if not os.environ.get("OPENAI_API_KEY"):
raise ValueError("OPENAI_API_KEY 환경변수가 설정되어 있지 않습니다.")
agent = create_agent(
model="openai:gpt-4o-mini",
tools=[calculate, get_exchange_rate],
system_prompt=(
"You are a practical assistant. "
"Use tools when numeric accuracy or external lookup is needed. "
"Do not pretend you computed or looked something up if you did not use a tool."
),
)
questions = [
"120 * 3 + 5 계산해줘.",
"USD를 KRW로 환율 알려줘.",
]
for q in questions:
result = agent.invoke({"messages": [{"role": "user", "content": q}]})
print(f"질문: {q}")
print("답변:", result["messages"][-1].content)
print("-" * 50)
if __name__ == "__main__":
main()
이 코드가 좋은 이유는,
모델이 질문 유형을 보고 어떤 tool이 맞는지 스스로 고르는 감각을 보여주기 때문입니다.
Agents 문서는 LLM agent가 tools와 결합되어 task를 해결하고, stop condition이 올 때까지 tool 사용과 reasoning을 반복할 수 있다고 설명합니다. (LangChain Docs)
8. Tool Calling에서 진짜 많이 하는 실수
이건 꼭 적어야 합니다.
실수 1. tool 설명을 너무 대충 씀
모델이 언제 써야 할지 모릅니다.
설명과 인자 이름이 prompt 일부이기 때문에, 여기서 이미 품질이 갈립니다. (LangChain Docs)
실수 2. system prompt가 애매함
예를 들어:
- “적절히 tool을 써라”
이 정도만 적으면 들쭉날쭉할 수 있어요.
차라리 이렇게 분명한 게 낫습니다.
- 수치 정확도가 필요하면 계산 tool을 써라
- 실시간/외부 데이터가 필요하면 조회 tool을 써라
- tool 없이 추측하지 마라
실수 3. tool 결과 형식이 들쭉날쭉함
tool이 문자열을 반환하더라도 일정한 형식이 좋습니다.
그래야 모델이 결과를 해석하기 쉽습니다.
실수 4. agent가 필요 없는 곳까지 agent로 만듦
모든 걸 tool calling으로 몰아가면 오히려 복잡해집니다.
고정 파이프라인이면 체인이 더 단순하고 안정적일 수 있어요. (LangChain Docs)
9. Tool Calling과 Structured Output은 같이 가면 더 좋다
여기서부터 서비스 느낌이 납니다.
LangChain structured output 문서는 create_agent가 structured output을 자동 처리할 수 있고, schema를 주면 최종 상태의 structured_response 키로 검증된 결과를 돌려준다고 설명합니다. 모델/provider가 지원하면 provider-native structured output을, 아니면 tool strategy를 선택할 수 있다고도 안내해요. (LangChain Docs)
즉, 이렇게 갈 수 있습니다.
- 중간에는 tool을 호출한다
- 마지막 답은 Pydantic/JSON으로 받는다
예를 들어:
- 환율 조회 tool 사용
- 최종 응답은 { "base": "USD", "quote": "KRW", "rate": 1380.5, "summary": "..." }
이건 다음 글들에서 더 다루면 좋지만,
미리 감만 잡아도 좋습니다.
10. 요즘 기준으로는 Responses API 흐름도 같이 알아둘 만하다
LangChain 시리즈니까 구현은 LangChain으로 가는 게 맞지만,
개념적으로는 OpenAI 쪽도 흐름이 바뀌고 있습니다.
OpenAI는 Responses API를 “agentic by default”라고 설명하며, built-in tools와 custom functions를 한 요청 안에서 호출할 수 있다고 안내합니다. 또 Assistants API는 2026년 8월 26일 종료 예정이고, Responses API와 Conversations API로 이동하라고 공지하고 있습니다. (OpenAI Developers)
이게 왜 중요하냐면,
요즘 Tool Calling은 더 이상 “부가 기능”이 아니라
LLM 앱 설계의 기본 축으로 가고 있다는 뜻이거든요.
LangChain은 이런 provider/tool 차이를 추상화해서 다루기 쉽게 해주는 쪽이고요. (LangChain Docs)
11. 오늘 글에서 꼭 가져가야 할 한 문장
오늘 내용을 한 줄로 줄이면 이겁니다.
Tool Calling은 LLM이 “그럴듯하게 말하는 것”에서 멈추지 않고, 필요할 때 실제 기능을 불러서 확인하고 행동하게 만드는 구조다.
이 감각이 생기면 다음 단계가 훨씬 쉬워집니다.
- 문서 검색 tool
- API 조회 tool
- 계산 tool
- DB 조회 tool
- 일정 탐색 tool
전부 결국 같은 패턴입니다.
마무리
RAG를 배우고 나면 한동안은 “문서를 잘 찾는 AI”에 꽂히게 됩니다.
근데 서비스는 거기서 끝나지 않더라고요.
실제 사용자들은 설명도 원하지만,
동시에 확인도 원하고, 계산도 원하고, 조회도 원하고, 실행도 원합니다.
그 순간부터 LLM은 그냥 잘 말하는 모델이 아니라
도구를 잘 쓰는 인터페이스가 되어야 해요.
저는 Tool Calling을 처음 제대로 붙였을 때
“아, 이제 좀 서비스 같다”는 느낌이 확 왔습니다.
설명만 하던 AI가
필요할 때는 확인하고, 계산하고, 조회하는 단계로 넘어가니까요.
그 차이가 꽤 큽니다. 진짜로.
다음 글 예고
다음 글에서는
LangChain으로 Tool Calling 제대로 다루기 — tool 설계, 설명문, 반환 형식이 품질에 미치는 영향
으로 이어가겠습니다.
여기서부터는 “tool을 붙였다”에서 끝나지 않고,
왜 어떤 tool은 잘 호출되고 어떤 tool은 이상하게 쓰이는지를 본격적으로 보게 될 거예요.
출처
- LangChain Tools 문서: tools는 실시간 데이터 조회, 코드 실행, 외부 DB 질의, 액션 수행 등 에이전트의 능력을 확장하며, callable function에 잘 정의된 입력/출력을 부여한 형태라고 설명합니다. (LangChain Docs)
- LangChain Agents 문서: tools는 plain Python functions/coroutines 또는 @tool 데코레이터로 정의할 수 있고, create_agent(..., system_prompt=...) 패턴을 지원합니다. (LangChain Docs)
- LangChain Quickstart: @tool 데코레이터, create_agent, agent.invoke({"messages": [...]}), checkpointer와 structured output을 포함한 실전형 agent 예시를 제공합니다. (LangChain Docs)
- LangChain v1 문서: create_agent는 LangChain 1.0에서 에이전트를 만드는 표준 방식이며, tools는 @tool 함수나 proper type hints/docstring을 가진 callables를 받을 수 있다고 설명합니다. (LangChain Docs)
- LangChain Structured Output 문서: create_agent는 structured output을 자동 처리하며, 결과는 structured_response 키에 담긴다고 설명합니다. (LangChain Docs)
- OpenAI Responses API 가이드: Responses API는 built-in tools와 custom functions를 한 요청 안에서 호출할 수 있는 unified interface라고 설명합니다. (OpenAI Developers)
- OpenAI Deprecations / migration 문서: Assistants API는 2026년 8월 26일 종료 예정이며 Responses API와 Conversations API로 마이그레이션하라고 안내합니다. (OpenAI Developers)
LangChain, Tool Calling, create_agent, @tool, AI Agent, Function Calling, 생성형AI, LLM개발, LangChain Python, 주니어개발자
'study > langchain' 카테고리의 다른 글
| RAG 품질이 안 나오는 이유 — chunk 크기, overlap, k값, 프롬프트 문제를 어떻게 봐야 하나 (0) | 2026.04.08 |
|---|---|
| 첫 번째 RAG 만들기 — Retriever로 찾고, 문서를 넣고, 근거 기반으로 답하게 하기 (0) | 2026.04.07 |
| 임베딩과 벡터스토어를 처음 이해하는 글 — RAG를 배우기 전에 꼭 알아야 할 검색의 언어 (0) | 2026.04.03 |
| LangChain으로 문서 하나 읽고 답하는 AI 만들기 — RAG 전에 꼭 알아야 할 가장 작은 문서 Q&A (0) | 2026.03.31 |
| LangChain 대화 히스토리 다루기 — 긴 대화를 자르고, 요약하고, 비용을 관리하는 방법 (0) | 2026.03.30 |
- Total
- Today
- Yesterday
- flax
- 개발블로그
- node.js
- 딥러닝
- PostgreSQL
- JAX
- Prisma
- CI/CD
- kotlin
- Docker
- Redis
- 쿠버네티스
- 웹개발
- REACT
- rag
- seo 최적화 10개
- DevOps
- ai철학
- SEO최적화
- Python
- fastapi
- Next.js
- Express
- 백엔드개발
- nextJS
- JWT
- 생성형AI
- NestJS
- llm
- LangChain
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |

