에이전트 시리즈 (1): 에이전트란 무엇인가 — 단순히 도구를 호출할 수 있는 LLM이 아니다
요약
단순히 도구를 호출하는 LLM이나 대화 기록을 관리하는 챗봇과 달리, 에이전트는 목표 달성을 위해 어떤 도구를 언제 사용할지 스스로 결정하는 자율성을 가집니다. 본 글은 LLM, 챗봇, 에이전트의 기술적 차이점을 시나리오를 통해 설명하며 에이전트의 핵심인 '자율적 의사결정'을 강조합니다.
핵심 포인트
- LLM은 언어 추론 능력을 갖춘 '두뇌' 역할을 하지만, 상태가 없는(stateless) 특성을 가짐
- 챗봇은 LLM에 대화 기록 관리 기능을 추가하여 문맥(Context)을 유지하는 형태임
- 에이전트의 핵심 차별점은 도구 호출 여부가 아니라, 도구를 호출할 시점과 방법을 스스로 결정하는 '자율성'에 있음
- 에이전트는 실시간 데이터 획득 및 복합적인 사고 과정을 통해 능동적으로 문제를 해결함
당신은 에이전트(Agent)를 사용하고 있다고 생각할지 모릅니다. 하지만 그렇지 않습니다. 2023년, "AI 에이전트 (AI Agent)"는 하룻밤 사이에 유행어가 되었습니다. 모든 기업이 에이전트를 구축했다고 주장했습니다. 모든 제품에 에이전트라는 라벨을 붙였습니다. 하지만 그들에게 물어보십시오. 당신의 에이전트와 일반적인 LLM 호출의 근본적인 차이점은 무엇입니까? 대부분의 사람들은 3초간 침묵하다가 이렇게 말합니다: "...도구를 호출할 수 있다는 점입니다." 그것이 틀렸을까요? 아닙니다. 하지만 핵심을 놓치고 있습니다. 이는 "자동차와 자전거의 차이점이 무엇인가"라는 질문에 "자동차는 바퀴가 네 개다"라고 답하는 것과 같습니다. 기술적으로는 맞지만, 엔진에 대해서는 언급하는 것을 잊은 것입니다. 이 글의 목표는 단 하나입니다. 에이전트가 실제로 무엇인지, 그리고 왜 LLM이나 챗봇 (Chatbot)과 근본적으로 다른지 이해하도록 돕는 것입니다. 이것을 제대로 파악한다면, 단순히 LLM API 호출을 감싸서 "우리의 에이전트 시스템"이라고 부르는 대신 더 나은 기술적 결정을 내릴 수 있을 것입니다.
시나리오로 시작하기
사용자를 위해 경쟁사를 분석하는 AI 도구를 만들고 싶다고 가정해 봅시다. 사용자가 회사 이름을 입력하면, 도구가 경쟁 분석 보고서를 생성합니다.
옵션 A: 직접적인 LLM 호출
사용자 입력: Notion의 경쟁사를 분석해줘
↓ LLM이 직접 보고서 생성
↓ 출력 (학습 데이터에 기반하며, 잠재적으로 오래된 정보)
옵션 B: 챗봇 (Chatbot)
사용자 입력: Notion의 경쟁사를 분석해줘
↓ LLM이 답변을 생성하고 대화 기록을 기억함
사용자 후속 질문: 가격 전략에 집중해줘
↓ LLM이 문맥(Context)을 유지하며 대화를 이어감
↓ 다회차 대화 (Multi-turn conversation), 여전히 학습 데이터에 기반함
옵션 C: 에이전트 (Agent)
사용자 입력: Notion의 경쟁사를 분석해줘
↓ 에이전트의 사고: 최신 데이터가 필요해, 먼저 검색부터 해보자
↓ 검색 도구(Search tool) 호출 → 최신 경쟁사 정보 획득
↓ 에이전트의 사고: 가격을 비교해야겠어, 계산을 해보자
↓ 계산 도구(Calculation tool) 호출 → 결과 획득
↓ 에이전트의 사고: 이제 충분한 정보가 확보되었어
↓ 보고서 출력 (실시간 데이터에 근거하며, 출처 포함)
차이점이 보이십니까? 에이전트는 "내가 무엇을 해야 하는가"를 능동적으로 생각하고, 다음 행동을 자율적으로 결정합니다. 그것이 핵심입니다. 도구를 호출할 수 있는지 여부가 아니라, 어떤 도구를 언제 호출할지를 누가 결정하느냐가 핵심입니다.
세 가지 개념, 세 가지 단계
LLM: 언어 능력을 갖춘 "두뇌"
대규모 언어 모델 (Large Language Model, LLM)은 근본적으로 하나의 함수입니다:
입력: 텍스트 (프롬프트)
출력: 예측된 다음 토큰 (완료될 때까지 반복)
LLM의 능력은 방대한 양의 텍스트로부터 학습된 통계적 패턴에서 비롯됩니다. 언어를 이해하고 추론할 수 있지만, 기억력도, 지각 능력도, 행동 능력도 없습니다. 모든 호출은 상태가 없는 (stateless) 방식입니다. 이전에 무엇에 대해 이야기했는지 전혀 알지 못합니다. 독립적인 LLM은 오직 질문에만 답하는 명석한 학자와 같습니다. 지식은 매우 깊지만, 창문이 없는 방에 갇혀 있어 외부에서 무슨 일이 일어나는지 알지 못하며, 당신을 위해 선제적으로 무엇인가를 수행할 수도 없습니다.
챗봇 (Chatbot): 기억력을 가진 LLM
챗봇 = LLM + 대화 기록 관리 (conversation history management)입니다. 챗봇은 한 가지 단순한 문제를 해결합니다. 바로 LLM이 이 대화에서 나눈 내용을 "기억"하게 만드는 것입니다. 구현 방법 또한 간단합니다. 모든 프롬프트 앞에 대화 기록을 붙여넣으면 됩니다.
의사코드 (Pseudocode): 챗봇의 핵심 로직
messages = []
while True:
user_input = get_user_input()
messages.append({"role": "user", "content": user_input})
# LLM에 전체 기록을 전송
response = llm.invoke(messages)
messages.append({"role": "assistant", "content": response})
print(response)
챗봇의 한계: 대화는 할 수 있지만, 행동할 수는 없습니다. 정보를 선제적으로 찾아보거나, API를 호출하거나, 코드를 실행할 수 없습니다. 오직 이미 알고 있는 내용을 바탕으로 답변할 수 있을 뿐입니다. 만약 LLM이 명석한 학자라면, 챗봇은 그 학자에게 전화기를 쥐여준 것과 같습니다. 마침내 대화는 가능해졌지만, 그들은 여전히 방 안에 갇혀 있습니다.
에이전트 (Agent): 자율적인 행위자
에이전트는 챗봇 위에 두 가지 핵심적인 능력, 즉 도구 사용 (tool use)과 자율적 의사결정 루프 (autonomous decision-making loop)를 추가합니다. 하지만 여기서 자주 오해하는 핵심 포인트가 있습니다. 도구 그 자체가 무언가를 에이전트로 만드는 것이 아닙니다. 중요한 것은 어떤 도구를 언제 사용할지를 누가 결정하느냐입니다.
도구를 사용하는 챗봇 (Chatbot with tools) = 당신이 "날씨를 확인해줘"라고 말하면, 날씨 API를 호출합니다. 에이전트 (Agent) = "이 질문에 답하기 위해서는 날씨를 확인해야 한다"라고 스스로 판단한 뒤, 선제적으로 호출합니다. 이것이 수동적 응답 (passive response)과 능동적 계획 (active planning)의 차이입니다.
에이전트의 4가지 요소
에이전트를 이해하는 가장 명확한 프레임워크는 이를 네 가지 구성 요소로 나누는 것입니다. 이 프레임워크는 지능적 행동에 관한 인지 과학 (cognitive science) 연구에서 유래되었으며, 오늘날 주류 엔지니어링 관점을 나타냅니다.
┌─────────────────────────────────────────────────────────┐
│ Agent │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Perception │ │ Memory │ │ Action │ │ │ │ │ │ · User msgs │ │ · Chat hist │ │ · Call tools│ │ │ │ · Tool results · Tool results · Run code │ │ │ │ │ │ · Environment│ · External KB│ │ · Call APIs │ │ └──────┬──────┘ └──────┬──────┘ └──────▲──────┘ │ │ │ │ │ │ │ └──────────┬───────┘ │ │ │ ▼ │ │ │ ┌─────────────┐ │ │ │ │ │ │ Reasoning ───────────────────┘ │ │ │ │ │ │ │ · Plan steps│ │ │ · Choose tool │ │ · Decide done │ └─────────────┘ │ └─────────────────────────────────────────────────────────┘
인식 (Perception): 에이전트가 "볼 수 있는" 것. 최소한 사용자 입력이 포함됩니다. 더 발전된 형태로는 도구 반환 값 (tool return values), 데이터베이스 쿼리 결과, 스크린샷, 파일 내용 등이 있습니다. 인식은 에이전트의 인지 범위 (awareness)를 정의합니다. 즉, 볼 수 없는 것에 대해서는 행동할 수 없습니다.
기억 (Memory): 에이전트가 "기억할 수 있는" 것. 이는 여러 수준에서 작동합니다: 현재 대화 기록 (단기 기억, short-term memory), 벡터 데이터베이스 (vector databases)에 저장된 과거 경험 (장기 기억, long-term memory), 그리고 정적인 외부 지식 베이스 (semantic memory, 의미론적 기억). 이 시리즈의 후반부에서 기억 시스템에 대해 별도의 기사를 다룰 예정입니다.
추론 (Reasoning): 에이전트의 "두뇌"이며, 챗봇과의 가장 본질적인 차이점입니다. 여기서 LLM은 "질문 답변자"가 아닌 컨트롤러 (controller) 역할을 수행합니다. LLM의 임무는 다음과 같습니다: 작업을 분해하고, 단계를 계획하며, 다음에 사용할 도구를 선택하고, 작업이 완료되었는지 결정하는 것입니다.
Action (행동): 에이전트가 "할 수 있는 것". 도구 호출 (Tool calls)은 가장 일반적인 행동입니다 — 검색, 데이터베이스 쿼리, 이메일 전송, 코드 실행 등. 행동의 범위는 에이전트의 역량 경계 (capability boundary)를 정의합니다 — 더 많은 도구는 더 많은 작업을 처리할 수 있음을 의미하지만, 동시에 상황이 잘못될 위험도 높아집니다 (이는 나중에 다룰 주제인 Harness Engineering에서 다룹니다). 이 네 가지 요소는 에이전트 아키텍처 (Agent architecture)를 이해하기 위한 토대이며, 이 시리즈의 나머지 부분을 관통하는 핵심 실타래입니다: 인지 (Perception) + 메모리 (Memory) → 제6장: 메모리 관리 (Memory Management), 추론 (Reasoning) → 제2장: ReAct 패러다임 (The ReAct Paradigm), 제3장: 계획 및 해결 (Plan-and-Solve), 행동 (Action) → 제4장: 도구 호출 (Tool Calling), 제5장: 의도 인식 (Intent Recognition).
두 가지 에이전트 패러다임: 조립 라인 (Assembly Line) vs. 탐험 가이드 (Expedition Guide)
실제 에이전트 시스템은 실행 흐름 (execution flow)을 누가 제어하느냐에 따라 두 진영으로 나뉩니다:
워크플로 주도형 에이전트 (Workflow-Driven Agent)
대표적인 도구: Dify, n8n, Coze, Zapier
핵심 아이디어: 개발자가 플로우차트 (flowchart)를 그리며, LLM은 그 안의 하나의 노드 (node) 역할을 합니다.
플로우차트 (개발자가 사전에 정의):
사용자 질문 수신 ↓
[LLM 노드] 질문 유형 분류 ↓
"결제 관련 질문"인 경우 → [도구 노드] 결제 시스템 쿼리
"불만 사항"인 경우 → [도구 노드] 고객 지원 티켓 생성 ↓
[LLM 노드] 최종 답변 생성 ↓
사용자에게 전송
실행 경로(execution path)는 개발자에 의해 미리 설계됩니다. LLM은 자연어 이해 및 생성을 처리하지만, "다음에 무엇이 일어날지"에 대한 로직은 플로우차트에 하드코딩 (hardcoded)되어 있습니다.
장점:
- 동작이 예측 가능함; 출시 전에 모든 경로를 완전히 테스트할 수 있음
- 문제가 발생했을 때 디버깅이 쉬움 (고장 난 노드가 명확함)
- LLM이 복잡한 작업 계획 (task planning)을 이해할 필요가 없음
가장 적합한 분야: - 고객 서비스 봇 (질문 유형이 고정되어 있고 프로세스가 알려져 있음)
- 승인 흐름 자동화 (단계가 고정되어 있고 조건이 명확함)
- 양식 처리, 데이터 ETL (구조화되어 있고 예측 가능함)
AI 네이티브 에이전트 (AI Native Agent)
대표적인 프레임워크: LangGraph, AutoGen, CrewAI
핵심 아이디어: LLM이 컨트롤 센터 (control center)이며 무엇을 할지 결정합니다.
사용자 질문 도착 ↓ [LLM 추론 (reasoning)]: 현재 데이터가 필요함, 먼저 검색을 수행해야 함 ↓ [검색 도구 (search tool) 호출] → 결과 반환 ↓ [LLM 추론 (reasoning)]: 결과 중 숫자에 대한 검증이 필요함 ↓ [계산 도구 (calculation tool) 호출] → 결과 반환 ↓ [LLM 추론 (reasoning)]: 이제 답변하기에 충분한 정보가 확보됨 ↓ 최종 답변 출력
"다음에 무엇을 할 것인가"에 대한 모든 단계는 실행 시점 (runtime)에 LLM에 의해 동적으로 결정됩니다. 그 누구도 흐름을 하드코딩 (hardcoded) 하지 않았습니다. 이것이 AI 네이티브 에이전트 (AI Native Agent)의 본질입니다. LLM은 도구가 아니라, 지휘자 (conductor)입니다.
강점:
- 경계가 불분명한 개방형 작업 (open-ended tasks) 처리 가능
- 중간 결과에 따라 전략을 조정함
- 다단계 추론 (multi-step reasoning)이 필요한 문제에 적합함
최적의 활용 사례:
- 개방형 조사 (사용자 질문이 다양하여 목록화가 불가능함)
- 자동 버그 수정 (코드 분석에 기반한 동적 결정이 필요함)
- 복잡한 데이터 분석 (여러 차례의 검색 및 계산이 필요함)
기억해야 할 비유
여행 계획을 세운다고 상상해 보세요:
워크플로 기반 에이전트 (Workflow-Driven Agent) = 고속 열차. 정해진 선로, 정해진 정차역, 정해진 출발 시간. 매우 효율적이며 길을 잃지 않지만, 선로가 있는 곳으로만 갈 수 있습니다.
AI 네이티브 에이전트 (AI Native Agent) = 숙련된 여행 가이드. 당신이 "역사적 특색이 있는 곳에 가고 싶어"라고 말하면, 가이드는 몇 가지 질문을 던지고, 실시간으로 리뷰를 확인하며, 오늘 날씨에 따라 일정을 조정하고, "관광지가 일시적으로 폐쇄되었습니다"와 같은 상황에 즉각적으로 대처합니다. 유연하지만, 때로는 우회로로 안내할 수도 있습니다.
에이전트 vs 일반 LLM 호출: 언제 사용할 것인가
이것은 여러분이 내릴 가장 중요한 엔지니어링적 판단이며, 과잉 엔지니어링 (over-engineering)이 가장 빈번하게 발생하는 지점입니다.
많은 이들이 빠지는 함정: 에이전트가 정교하게 들리기 때문에, 문제의 성격과 상관없이 에이전트를 선택하려 합니다. 하지만 에이전트에는 비용이 따릅니다. 더 긴 응답 시간, 더 높은 토큰 소비량, 더 복잡한 디버깅 (debugging)이 그것입니다.
다음 의사결정 나무 (decision tree)를 사용하세요:
당신의 작업에 에이전트가 필요한가?
│
├─ 작업 단계가 고정되어 있고 열거 가능한가?
│ └─ 예 → LLM + 고정된 프롬프트 (fixed Prompt), 또는 워크플로 기반 에이전트 사용
│
└─ 작업에 단 한 번의 LLM 호출만 필요한가 (도구 미사용)?
│ └─ Yes → LLM API를 직접 호출, 에이전트(Agent) 불필요
│ ├─ 중간 결과에 따라 다음 단계를 결정해야 하는가?
│ └─ Yes → 에이전트(Agent) 필요
│ ├─ 작업에 3개 이상의 상호 의존적인 단계가 있는가?
│ └─ Yes → 에이전트(Agent) 필요
│ └─ 사전에 예측할 수 없는 상황을 처리해야 하는가?
└─ Yes → 에이전트(Agent) 필요 (특히 AI Native Agent 필요)
실제 사례:
| 시나리오 | 권장 접근 방식 | 이유 |
|---|---|---|
| 문서 요약 | 직접적인 LLM 호출 | 단일 호출, 고정된 프롬프트 (fixed Prompt) |
| FAQ 챗봇 | 챗봇 (Chatbot) | 다회차 대화 (Multi-turn) 필요, 도구 미사용 |
| 고객 서비스 라우팅 | 워크플로 기반 에이전트 (Workflow-Driven Agent) | 고정된 흐름, 열거 가능한 케이스 |
| 자동 버그 분석 및 수정 | AI Native Agent | 코드 분석에 기반한 동적 결정 |
| 경쟁사 조사 보고서 | AI Native Agent | 개방형 주제, 다회차 검색 필요 |
| 코드 리뷰 | AI Native Agent | 코드 구조에 따른 동적 처리 |
단순히 할 수 있다고 해서 에이전트(Agent)를 사용하지 마세요
만약 잘 설계된 프롬프트 (Prompt)로 해결할 수 있는 작업이라면, 프롬프트를 사용하세요. 에이전트(Agent)가 추가하는 복잡성(디버깅의 어려움, 높은 지연 시간 (latency), 높은 비용)은 작업이 진정으로 동적 의사결정을 필요로 할 때만 가치가 있습니다. Anthropic의 공식 가이드라인은 이를 명확히 밝히고 있습니다: "LLM은 자율성과 유연성이 진정으로 가치를 제공할 때만 자율 에이전트 (autonomous agents)로 사용되어야 합니다. 그렇지 않다면 직접적인 API 호출이 더 신뢰할 수 있고 예측 가능합니다."
최소한의 AI Native Agent란 어떤 모습인가
이론은 충분합니다. 이제 실제 코드를 보겠습니다. 아래는 LangGraph로 구축된 최소한의 ReAct 에이전트 (ReAct Agent)입니다 (이는 가장 기초적인 AI Native Agent 패러다임이며, 다음 글에서 심도 있게 다룹니다):
의존성 설치: pip install langchain-anthropic langgraph
from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool
from langgraph.prebuilt import create_react_agent
1.
도구 정의 (에이전트의 "손")
@tool
def search_web ( query : str ) -> str :
""" 현재 정보를 위해 웹을 검색합니다 """
# 실제 사용 시에는 실제 검색 API (예: Tavily)에 연결하세요.
return f" 검색 결과: '{ query }'에 대한 최신 정보 ... "
@tool
def calculate ( expression : str ) -> str :
""" 수학적 표현식을 계산합니다 """
try :
result = eval ( expression )
# 주의: 프로덕션 환경에서는 eval을 사용하지 마세요.
return str ( result )
except Exception as e :
return f" 계산 오류: { e } "
2. 에이전트 생성 (LLM은 컨트롤 센터 역할을 합니다)
llm = ChatAnthropic ( model = " claude-sonnet-4-6 " )
tools = [ search_web , calculate ]
agent = create_react_agent ( llm , tools )
3. 실행
result = agent . invoke ({ " messages " : [( " user " , " Apple의 현재 시가총액은 얼마인가요? 그것은 1조 달러보다 얼마나 더 많은가요? " )] })
print ( result [ " messages " ][ - 1 ]. content )
이 코드를 실행하면, 에이전트는 자동으로 다음 과정을 수행합니다:
- Apple의 시가총액을 검색해야 한다고 결정합니다.
- search_web을 호출합니다.
- 결과를 확인합니다...
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기