AI Agent vs LLM: 왜 단순히 OpenAI API를 호출하는 것만으로는 에이전트가 될 수 없는가 (그리고 무엇이 필요한가)
요약
단순한 LLM API 호출 루프와 진정한 AI 에이전트의 기술적 차이점을 설명합니다. 에이전트가 되기 위해 필요한 자율적 도구 사용, 계획 및 재계획, 단계 간 메모리, 오류 복구라는 네 가지 핵심 속성을 정의합니다.
핵심 포인트
- 단순 LLM 호출 루프는 에이전트가 아닌 배치 처리 방식임
- 에이전트는 추론을 바탕으로 도구 사용 시점을 스스로 결정해야 함
- 실행 결과에 따라 계획을 수정하는 재계획 능력이 필수적임
- 작업 과정의 상태를 유지하는 단계 간 메모리가 필요함
- 예상치 못한 오류 발생 시 스스로 적응하는 복구 능력이 중요함
"우리는 에이전트를 만들었고, API를 루프(loop)로 호출했습니다." 아니요. 당신은 몇 단계를 더 거친 챗봇(chatbot)을 만든 것입니다. 실제 차이점은 다음과 같습니다.
고백부터 시작하고 싶습니다. 저도 초기에 이 실수를 저질렀고, 심지어 고객에게 우리가 "에이전트 (agent)"를 구축했다고 자신 있게 말하기도 했습니다. 하지만 실제로 우리가 만든 것은 가끔 함수(function)를 호출하는 챗봇(chatbot)에 불과했습니다.
이 실수는 이해할 수 있습니다. 표면적인 패턴이 비슷해 보이기 때문입니다. LLM을 호출합니다. 프롬프트 (prompt)를 제공합니다. 응답을 받습니다. 이를 몇 번 반복하고 도구 호출 (tool call)을 추가하면, 마치 에이전트 (agent)처럼 느껴집니다. 하지만 LLM 래퍼 (wrapper)와 실제 에이전트 (agent) 사이에는 실질적이고 기술적인 구분이 존재하며, 이 구분은 매우 중요합니다. 왜냐하면 이 구분이 당신의 시스템이 실제 운영 환경의 복잡하고, 다단계이며, 실패 가능성이 높은 작업을 처리할 수 있는지 여부를 결정하기 때문입니다.
정확하게 정의를 내린 다음, 두 가지 버전을 모두 구축하여 경계선이 정확히 어디인지 확인할 수 있도록 하겠습니다.
무엇이 에이전트(Agent)를 만드는가 (단순한 LLM 호출이 아닌)
에이전트 (agent)는 단순한 LLM 래퍼 (wrapper)가 갖지 못한 네 가지 속성을 가지고 있습니다.
자율적인 도구 사용 (Autonomous tool use): 시스템이 당신이 작성한 하드코딩된 순서가 아니라, 현재 상태에 대한 추론을 바탕으로 어떤 도구를 언제 호출할지 스스로 결정합니다.
계획 및 재계획 (Planning and replanning): 시스템이 계획을 세우고, 단계를 실행하고, 결과를 관찰하며, 학습한 내용을 바탕으로 계획을 수정합니다. 고정된 프롬프트 (prompt)를 사용한 단일 API 호출은 이를 수행할 수 없습니다. 스스로의 출력을 보고 다음에 무엇을 할지 결정하지 못하기 때문입니다.
단계 간 메모리 (Memory across steps): 시스템이 단일 작업 실행 내에서 이미 무엇을 시도했는지, 무엇이 작동했고 무엇이 작동하지 않았는지에 대한 상태 (state)를 유지합니다.
오류 복구 (Error recovery): 도구 호출 (tool call)이 실패하거나 예상치 못한 출력을 반환할 때, 시스템은 충돌하거나 일반적인 실패를 반환하는 대신 적응합니다.
만약 당신의 시스템이 최소한 처음 두 가지를 수행하지 못한다면, 그것은 에이전트 (agent)가 아니라 LLM 래퍼 (wrapper)입니다. 이것은 비하하는 말이 아닙니다. LLM 래퍼 (wrapper)는 유용하며 종종 적절한 도구가 되기도 합니다. 하지만 에이전트 (agent)가 아님에도 에이전트라고 부르는 것은, 당신이 구축한 것과 이해관계자들이 기대하는 것 사이에 불일치를 만듭니다.
LLM 래퍼 (LLM Wrapper) (대부분의 사람들이 가장 먼저 구축하는 것)
import anthropic
client = anthropic.Anthropic()
...
이것은 적절한 작업, 즉 단발성 질의응답 (single-turn question answering)을 위한 용도로는 완벽하게 괜찮은 코드입니다. 문제는 사람들이 이것을 루프 (loop) 안에 넣고 에이전트적 (agentic)이라고 부를 때 발생합니다.
def "agent"_with_a_loop(tasks: list[str]) -> list[str]:
"""
이것은 에이전트 (agent)가 아닙니다. 이것은 LLM 호출입니다.
...
이것은 배치 처리 (batch processing) 루프입니다. 작업 1의 결과에 따라 작업 2가 변경되어야 하는지에 대해 추론 (reason)하지 않습니다. 도구 (tools)를 사용하지 않습니다. 외부에서 별도로 덧붙인 예외 처리 (exception handling) 이상의 실패 복구 능력도 없습니다. 이것을 에이전트라고 부르는 지점에서 혼란이 시작됩니다.
실제 에이전트: 도구 사용을 포함한 ReAct 패턴
진정한 에이전트는 추론과 행동을 루프 안에서 수행하는 ReAct 패턴 (Reasoning and Acting)을 구현하며, 여기서 각 행동은 다음 추론 단계에 정보를 제공하는 관찰 (observation)을 생성합니다.
import anthropic
import json
...
"고객 4521의 주문 상태를 찾고, 마지막 주문이 30일보다 더 전이라면 업데이트 내용을 이메일로 보내라"와 같은 목표를 가지고 이를 실행하며 어떤 일이 일어나는지 지켜보십시오. 에이전트는 search_database를 호출하고, 결과를 관찰하며, 날짜 조건이 충족되는지에 대해 추론한 다음, 그제서야 send_email을 호출할지 결정합니다. 만약 데이터베이스 호출에서 에러가 반환되었다면, 에이전트는 이를 자신의 컨텍스트 (context)에서 확인하고 다른 검색 전략을 시도할 수 있습니다. 이것이 바로 재계획 (replanning) 속성입니다.
이것은 고정된 시퀀스 스크립트 (fixed-sequence script)가 할 수 없는 부분입니다. search_database()를 호출한 다음 무조건적으로 send_email()을 호출하는 스크립트는 결과에 대해 추론하는 것이 아닙니다. 그것은 단지 중간 어디쯤에 LLM이 포함된 예정된 시퀀스를 실행하는 것뿐입니다.
테스트: LLM 호출을 If-문으로 대체할 수 있는가?
누군가 저에게 자신의 "에이전트" 아키텍처를 보여줄 때 제가 사용하는 실질적인 테스트 방법은 다음과 같습니다.
만약 LLM 호출을 결정론적인(deterministic) if-문으로 대체할 수 있고 결과적으로 동일한 동작을 얻을 수 있다면, 당신은 에이전트적 추론 (agentic reasoning)을 가진 것이 아닙니다. 당신은 단지 자연어 생성 (natural language generation)이 필요한 부분에만 LLM을 덧붙인 스크립트를 가지고 있는 것입니다.
# 이것은 LLM을 호출함에도 불구하고, 에이전트적이지 않습니다.
def fake_agent(customer_id: int):
customer = search_database(f"id:{customer_id}")
...
여기서 LLM은 텍스트 생성 (text generation)을 수행하고 있을 뿐, 어떤 행동을 취할지에 대해 추론 (reasoning)하고 있는 것이 아닙니다. 결정 로직 (decision logic)은 모두 당신의 Python if-문에 들어 있습니다. 이는 수많은 유스케이스 (use cases)에서 매우 합리적인 아키텍처이지만, 에이전트는 아닙니다. 그것은 LLM을 글쓰기 도구로 사용하는 스크립트입니다.
진정한 에이전트 버전은 모델이 대화 기록 (conversation history)에 대한 자체적인 추론을 통해, 주문 날짜를 확인할지, 결과가 이메일을 보낼 만한 가치가 있는지, 이메일에 무엇을 써야 하는지, 그리고 이메일 전송이 실패했을 때 재시도할지 여부를 스스로 결정하게 합니다. 당신이 하드코딩한 제어 흐름 (control flow)을 통해서가 아니라 말입니다.
메모리 (Memory): 대부분의 래퍼 (Wrapper) 구현체가 생략하는 속성
진정한 에이전트는 상호작용 전반에 걸쳐 상태 (state)를 유지하며, 이는 나중에 결정을 내릴 때 이전의 관찰 (observations) 내용을 참조할 수 있음을 의미합니다.
class AgentSession:
"""
작업 실행 전반에 걸친 메모리. 이것이 바로
...
이것이 없다면, 단순한 에이전트 루프 (agent loop)는 이미 시도했다는 기억이 없기 때문에 실패하는 동일한 도구 (tool)를 반복해서 호출할 수 있습니다. 이는 초기 에이전트 구현에서 가장 흔히 발생하는 프로덕션 버그 중 하나로,
만약 당신의 작업이 각 단계의 결과가 다음 결정에 영향을 미치는 여러 단계를 필요로 한다면, 예를 들어 세 가지 시스템을 확인하고 그 결과에 따라 무엇을 할지 결정하는 방식으로 이 애플리케이션을 처리해야 한다면, 실제 에이전트 아키텍처 (agentic architecture)가 필요합니다. LLM 래퍼 (LLM wrapper)는 작업 중간에 발견된 사항에 맞춰 적응할 수 없기 때문에 실패할 것입니다.
각각이 특정 프로덕션 사용 사례에 언제 적합한지를 포함하여, AI agent vs LLM 아키텍처에 대한 전체적인 분석은 이곳에 담기에는 너무 방대한 의사결정 프레임워크를 다루고 있습니다.
다음 단계: RAG vs 에이전트 아키텍처 (Agentic Architecture)
이제 LLM과 에이전트의 구분이 명확해졌으므로, 대부분의 팀이 직면하는 다음 아키텍처 결정은 RAG 대 에이전트 AI (agentic AI)이며, 이 둘 또한 LLM 대 에이전트만큼이나 자주 혼동됩니다. RAG는 LLM의 응답을 사용자의 특정 문서에 근거(grounding)시키는 문제를 해결합니다. 에이전트 아키텍처는 여러 시스템에 걸쳐 다단계 동작을 수행하는 문제를 해결합니다. 이들은 서로 다른 문제에 대한 서로 다른 도구이며, 저희가 게시한 **RAG vs 에이전트 AI 비교 (RAG vs agentic AI comparison)**에서는 에이전트가 RAG를 자신의 도구 중 하나로 사용하는 하이브리드 패턴을 포함하여 각각이 어디에 적합한지를 정확히 다룹니다.
Dextra Labs 발행 | AI 컨설팅 및 엔터프라이즈 에이전트 개발
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기