책의 본문 마지막 장입니다. 지금까지 21개의 패턴과 두 장의 보충 장을 거치면서 LangChain, LangGraph, 구글 ADK, CrewAI 코드가 번갈아 등장했는데, 이 장은 그 도구들을 한자리에 모아 나란히 비교합니다. 분량은 짧지만, “그래서 무엇으로 만들어야 하는가”라는 실무 질문에 대한 책의 답이 담겨 있습니다.
핵심 축은 하나입니다. 추상화 수준. 저수준으로 갈수록 세밀하게 제어할 수 있고, 고수준으로 갈수록 적은 코드로 빠르게 만들 수 있습니다.
저수준 ◀──────────────────── 추상화 수준 ────────────────────▶ 고수준
(세밀한 제어) (매끄러운 개발 경험)
LangChain LangGraph 구글 ADK / CrewAI
───────── ───────── ─────────────────
체인(LCEL) 노드 + 엣지 + 상태 에이전트 팀, 역할, 프로세스
A → B → C 루프·재시도·분기 "누가 무엇을 맡는가"만 정의
한 방향 파이프 개발자가 배선을 직접 배선은 프레임워크가 알아서
LangChain
LangChain은 LLM으로 구동되는 애플리케이션을 개발하는 프레임워크입니다. 핵심 강점은 LangChain Expression Language(LCEL) 에 있습니다. LCEL을 활용하면 여러 구성 요소를 체인으로 ‘파이프’처럼 이어 붙일 수 있고, 한 단계의 출력이 다음 단계의 입력이 되는 명확한 순차 실행의 흐름이 만들어집니다.
LangChain은 방향성 비순환 그래프(Directed Acyclic Graphs, DAG) 형태의 워크플로를 염두에 두고 설계되었으며, 이는 처리 흐름이 루프 없이 한 방향으로만 이어진다는 뜻입니다.
다음과 같은 상황에 적합합니다.
- 단순 RAG: 문서를 검색하고, 프롬프트를 만들고, LLM에서 답변을 받는다.
- 요약: 사용자 텍스트를 받아 요약 프롬프트에 넣고, 결과를 반환한다.
- 추출: 텍스트 블록에서 구조화된 데이터(예: JSON)를 추출한다.
# 단순 LCEL 체인의 개념 예시
# (실행용 코드가 아니며 흐름만 예시로 보여 준다)
chain = prompt | model | output_parser
한 줄이지만 1장의 프롬프트 체이닝이 그대로 들어 있습니다. | 연산자가 “앞의 출력을 뒤의 입력으로”를 뜻하고, 세 단계가 정해진 순서로 한 번씩만 실행됩니다. LCEL 문법을 더 자세히 보고 싶다면 LangChain 시리즈의 LangChain 입문을 참고하세요.
LangGraph
LangGraph는 LangChain을 기반으로 만든 라이브러리로, 더 고도화된 에이전틱 시스템을 다루도록 설계되었습니다. 이 라이브러리를 쓰면 워크플로를 노드(함수 또는 LCEL 체인)와 엣지(조건부 로직)로 이루어진 그래프로 정의할 수 있습니다.
가장 큰 장점은 순환 구조를 만들 수 있다는 점이다. 덕분에 애플리케이션은 작업을 마칠 때까지 루프를 돌고, 재시도하고, 유연한 순서로 도구를 호출할 수 있다. 또 애플리케이션 상태를 명시적으로 관리하며, 이 상태는 노드 사이를 오가며 처리 과정 내내 갱신된다.
다음과 같은 상황에 적합합니다.
- 멀티 에이전트 시스템: 관리자(supervisor) 에이전트가 전문 영역별 워커 에이전트에게 작업을 라우팅하며, 목표가 달성될 때까지 이 과정을 반복할 수 있다.
- 계획 수립-실행(Plan-and-Execute) 에이전트: 에이전트가 계획을 세운 뒤 한 단계를 실행하고, 그 결과를 바탕으로 계획을 갱신하기 위해 루프로 돌아온다.
- 휴먼 인 더 루프: 그래프는 다음 노드로 이동할지 결정하기 전에 사람의 입력을 기다릴 수 있다.
세 가지 모두 앞 장에서 만난 패턴입니다. 7장의 멀티 에이전트 협업, 6장의 계획 수립, 13장의 휴먼 인 더 루프. 공통점은 “한 번 지나가면 끝”이 아니라 되돌아와야 한다는 것이고, 그래서 DAG로는 표현할 수 없습니다.
| 특징 | LangChain | LangGraph |
|---|---|---|
| 핵심 추상화 | 체인(LCEL 기반) | 노드 기반 그래프 |
| 워크플로 유형 | 선형(방향성 비순환 그래프) | 순환형(루프를 포함한 그래프) |
| 상태 관리 | 실행 단위로는 대체로 무상태(Stateless) | 명시적이고 지속되는 상태 객체(Stateful) |
| 주된 용도 | 단순하고 예측 가능한 시퀀스 | 복잡하고 유동적이며 상태를 유지하는 에이전트 |
어느 프레임워크를 선택해야 하는가?
- 애플리케이션의 단계 흐름이 명확하고 예측 가능하며 순차적으로 실행된다면 LangChain을 선택한다. 처리 과정을 A에서 B, B에서 C로 진행하는 식으로 정의할 수 있고 되돌아오는 루프가 필요 없다면, LCEL을 갖춘 LangChain이 가장 적합한 도구다.
- 애플리케이션이 추론하거나 계획을 세우거나 루프 형태로 동작해야 할 때는 LangGraph를 선택한다. 에이전트가 도구를 사용하고 그 결과를 되돌아보며, 필요하다면 다른 접근 방식으로 다시 시도해야 한다면, LangGraph가 갖춘 순환 구조와 상태 관리가 필요하다.
판단 기준을 한 줄로 줄이면 “화살표가 뒤로 가는가?” 입니다.
from typing import TypedDict
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, START, END
from IPython.display import display, Image
# LLM 인스턴스
llm = ChatOpenAI(model="gpt-4o-mini")
# 그래프 상태
class State(TypedDict):
topic: str
joke: str
story: str
poem: str
combined_output: str
# 노드
def call_llm_1(state: State):
"""초기 농담을 생성하는 첫 번째 LLM 호출"""
msg = llm.invoke(f"Write a joke about {state['topic']}")
return {"joke": msg.content}
def call_llm_2(state: State):
"""이야기를 생성하는 두 번째 LLM 호출"""
msg = llm.invoke(f"Write a story about {state['topic']}")
return {"story": msg.content}
def call_llm_3(state: State):
"""시를 생성하는 세 번째 LLM 호출"""
msg = llm.invoke(f"Write a poem about {state['topic']}")
return {"poem": msg.content}
def aggregator(state: State):
"""농담과 이야기를 하나의 출력으로 결합"""
combined = f"Here's a story, joke, and poem about {state['topic']}!\n\n"
combined += f"STORY:\n{state['story']}\n\n"
combined += f"JOKE:\n{state['joke']}\n\n"
combined += f"POEM:\n{state['poem']}"
return {"combined_output": combined}
# 워크플로 구축
parallel_builder = StateGraph(State)
# 노드 추가
parallel_builder.add_node("call_llm_1", call_llm_1)
parallel_builder.add_node("call_llm_2", call_llm_2)
parallel_builder.add_node("call_llm_3", call_llm_3)
parallel_builder.add_node("aggregator", aggregator)
# 노드를 연결하는 엣지 추가
parallel_builder.add_edge(START, "call_llm_1")
parallel_builder.add_edge(START, "call_llm_2")
parallel_builder.add_edge(START, "call_llm_3")
parallel_builder.add_edge("call_llm_1", "aggregator")
parallel_builder.add_edge("call_llm_2", "aggregator")
parallel_builder.add_edge("call_llm_3", "aggregator")
parallel_builder.add_edge("aggregator", END)
parallel_workflow = parallel_builder.compile()
# 워크플로 시각화
display(Image(parallel_workflow.get_graph().draw_mermaid_png()))
# 실행
state = parallel_workflow.invoke({"topic": "cats"})
print(state["combined_output"])
이 코드는 병렬로 동작하는 LangGraph 워크플로를 정의하고 실행합니다. 핵심 목적은 주어진 주제에 관해 농담, 이야기, 시를 동시에 생성한 뒤, 이를 하나의 서식화된 텍스트로 합치는 것입니다.
┌──────────────┐
┌────▶│ call_llm_1 │──── joke ────┐
│ └──────────────┘ │
┌───────┐│ ┌──────────────┐ ▼ ┌──────────────┐ ┌─────┐
│ START ├┼────▶│ call_llm_2 │──── story ──▶ aggregator ─────────────▶│ END │
└───────┘│ └──────────────┘ ▲ │combined_output│ └─────┘
│ ┌──────────────┐ │ └──────────────┘
└────▶│ call_llm_3 │──── poem ────┘
└──────────────┘
코드에서 볼 부분은 세 가지입니다.
- 상태는
TypedDict하나입니다. 각 노드는 상태 전체를 받지만 자기가 채울 키만 딕셔너리로 반환합니다({"joke": ...}). LangGraph가 이 부분 갱신을 공유 상태에 병합합니다. - 병렬성은 엣지로 표현됩니다.
START에서 세 노드로 엣지가 뻗어 나가면 세 노드가 동시에 실행되고, 세 노드 모두에서aggregator로 엣지가 모이면 셋이 다 끝난 뒤에aggregator가 실행됩니다. 3장의 병렬화 패턴이 그래프 모양 그대로 코드가 된 셈입니다. - 그런데 이 예제에는 루프가 없습니다. 바로 앞 절에서 “루프가 필요하면 LangGraph”라고 했지만, 예제 자체는 LangChain의
RunnableParallel로도 만들 수 있는 DAG입니다. LangGraph의 진가인 순환 구조는add_conditional_edges로 이전 노드로 되돌아가는 엣지를 추가할 때 드러납니다.aggregator뒤에 “품질이 부족하면 다시call_llm_1로”라는 조건부 엣지 하나만 붙이면 4장의 리플렉션 루프가 됩니다.
aggregator의 독스트링은 “농담과 이야기를 결합”이라고 되어 있지만, 실제 코드는 시까지 세 가지를 결합합니다. 원문 코드에서 시 노드를 나중에 추가하면서 주석을 고치지 않은 흔적으로 보입니다. LangGraph 기초를 더 보려면 LangGraph 입문을 참고하세요.
구글 ADK
구글의 Agent Development Kit, 즉 ADK는 여러 AI 에이전트가 상호작용하는 애플리케이션을 구축·배포하기 위한 고수준의 구조화된 프레임워크입니다. LangChain, LangGraph와는 결이 다릅니다. 에이전트 내부 로직을 구성하는 기본 빌딩 블록을 제공하는 방식이 아니라, 에이전트 간 협업을 오케스트레이션하기 위해 좀 더 방향성이 뚜렷하고 프로덕션을 지향하는 시스템을 갖추는 방식입니다.
세 프레임워크의 관계를 책은 이렇게 설명합니다.
- LangChain은 가장 기초적인 수준에서 동작하며, 모델 호출과 출력 파싱 같은 작업 시퀀스를 만들 수 있도록 컴포넌트와 표준 인터페이스를 갖추고 있다.
- LangGraph는 여기서 한 걸음 더 나아가 더 유연하고 강력한 제어 흐름을 도입하며, 에이전트의 워크플로를 상태를 지닌 그래프로 다룬다. 개발자는 함수나 도구에 해당하는 노드와 실행 경로를 정하는 엣지를 명시적으로 정의할 수 있다. 이 그래프 구조 덕분에 시스템은 노드 사이를 오가며 명시적으로 관리되는 상태 객체를 바탕으로 루프를 돌고 작업을 재시도하며 의사결정을 내릴 수 있다. 그 결과 개발자는 에이전트 하나의 사고 과정을 세밀하게 제어할 수도 있고, 멀티 에이전트 시스템을 처음부터 설계할 수도 있다.
- 구글 ADK는 이런 저수준 그래프 구성의 상당 부분을 감춘다. 개발자에게 모든 노드와 엣지를 직접 정의하라고 요구하는 대신, 멀티 에이전트 상호작용에 바로 쓸 수 있는 아키텍처 패턴을 미리 갖춰 둔다. 예를 들어
SequentialAgent와ParallelAgent같은 에이전트 유형이 기본 제공되어, 서로 다른 에이전트 사이의 제어 흐름을 자동으로 관리한다. 이 프레임워크는 에이전트 ‘팀’이라는 개념을 중심으로 설계되었고, 보통 주 에이전트가 전문화된 하위 에이전트에게 작업을 위임한다. 상태와 세션 관리도 프레임워크가 내부에서 알아서 처리하므로, LangGraph처럼 상태를 명시적으로 넘기는 방식보다 응집감은 높지만 세밀함은 덜하다.
따라서 LangGraph가 로봇 한 대나 로봇 팀의 복잡한 배선을 직접 설계하게 해 주는 정밀 도구라면, 구글 ADK는 이미 함께 일하는 법을 아는 로봇 군단을 만들고 운영하도록 짜인 공장 조립 라인에 가깝다.
from google.adk.agents import LlmAgent
from google.adk.tools import google_search
dice_agent = LlmAgent(
model="gemini-2.0-flash-exp",
name="question_answer_agent",
description="A helpful assistant agent that can answer questions.",
instruction="""Respond to the query using google search""",
tools=[google_search],
)
이 코드는 검색이 증강된 에이전트를 만듭니다. 이 에이전트는 질문을 받으면 기존 지식에만 의존하지 않습니다. 그 대신 지시에 따라 구글 검색(Google Search) 도구로 웹에서 관련 있는 실시간 정보를 찾고, 그 정보를 바탕으로 답변을 만들어 냅니다.
LangGraph 예제와 비교하면 차이가 선명합니다. 노드도, 엣지도, 상태 클래스도 없습니다. 모델, 이름, 설명, 지시, 도구라는 다섯 가지 선언만 있고, “도구를 언제 부를지 → 결과를 받아 → 다시 생각하고 → 답하는” 루프는 LlmAgent 안에 숨어 있습니다. 변수 이름이 dice_agent(주사위 에이전트)인데 name은 question_answer_agent인 것도 눈에 띄는데, 주사위 예제를 가져와 검색 에이전트로 바꾸면서 변수 이름만 남은 것으로 보입니다.
description 필드도 그냥 주석이 아닙니다. ADK에서 상위 에이전트가 하위 에이전트에게 작업을 위임할 때, 어떤 하위 에이전트에게 넘길지 고르는 근거로 이 설명을 읽습니다. 2장의 라우팅이 설정 한 줄로 들어가 있는 셈입니다.
CrewAI
CrewAI는 협업 역할과 구조화된 프로세스에 초점을 맞춰 멀티 에이전트 시스템을 구축하는 오케스트레이션 프레임워크입니다. 기초 수준의 툴킷보다 더 높은 추상화 수준에서 동작하며, 사람 팀을 본뜬 개념 모델을 제시합니다. 개발자는 로직의 세밀한 흐름을 그래프로 정의하지 않고, 누가 어떤 역할을 맡고 어떤 일을 수행할지 정합니다. 그러면 에이전트 사이의 상호작용은 CrewAI가 관리합니다.
핵심 구성 요소는 셋입니다.
| 구성 요소 | 정의 |
|---|---|
| 에이전트(Agent) | 기능뿐 아니라 구체적인 역할과 목표, 배경 서사를 담은 페르소나로도 정의되며, 이 페르소나가 에이전트의 동작과 소통 방식을 이끈다 |
| 태스크(Task) | 명확한 설명과 기대 결과를 지닌 개별 작업 단위로, 특정 에이전트에게 할당된다 |
| 크루(Crew) | 에이전트와 태스크 목록을 한데 묶는 단위. 사전에 정의된 프로세스(Process) 를 실행한다 |
프로세스가 워크플로를 결정하는데, 보통 두 가지 형태 중 하나를 따릅니다.
순차형(sequential) 계층형(hierarchical)
┌────────┐ ┌────────┐ ┌────────┐ ┌──────────┐
│ Task 1 │──▶│ Task 2 │──▶│ Task 3 │ │ 관리자 │
│Agent A │ │Agent B │ │Agent C │ │ 에이전트 │
└────────┘ └────────┘ └────────┘ └────┬─────┘
앞 태스크의 출력이 다음 태스크의 입력 ┌───────┼───────┐
▼ ▼ ▼
Agent A Agent B Agent C
관리자가 위임하고 조율
다른 프레임워크와 비교하면 CrewAI는 차별화된 위치를 차지합니다. 구체적으로는 개발자가 모든 노드와 조건부 엣지를 일일이 연결해야 하는 LangGraph식 저수준 상태 관리와 제어 흐름에서 벗어나 있습니다. 개발자는 상태 기계(state machine)를 만드는 대신 팀 설계도를 그립니다. 구글 ADK가 에이전트의 전체 수명 주기를 아우르는 종합적이고 프로덕션을 지향하는 플랫폼이라면, CrewAI는 에이전트 협업의 로직과 전문가 팀 시뮬레이션에 특히 집중합니다.
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, crew
@CrewBase
class ResearchCrew:
agents: list[Agent]
tasks: list[Task]
@crew
def crew(self) -> Crew:
"""연구 크루를 생성한다"""
return Crew(
agents=self.agents,
tasks=self.tasks,
process=Process.sequential,
verbose=True,
)
이 코드는 AI 에이전트 팀이 정해진 순서대로 태스크 목록을 처리하는 순차 워크플로를 설정합니다. 진행 상황을 추적할 수 있도록 상세 로깅(verbose)도 켜 둡니다.
self.agents와 self.tasks가 어디서 채워지는지 코드에는 보이지 않습니다. @CrewBase 데코레이터를 쓰는 CrewAI 프로젝트 구조에서는 보통 config/agents.yaml, config/tasks.yaml에 역할·목표·배경 서사와 태스크 설명을 적어 두고, @agent, @task 데코레이터가 붙은 메서드가 이를 읽어 목록을 채웁니다. 에이전트의 페르소나를 코드가 아니라 설정 파일로 관리한다는 점이 CrewAI다운 설계입니다. 계층형으로 바꾸려면 Process.hierarchical로 바꾸고 관리자 역할을 맡을 LLM(manager_llm)이나 에이전트를 지정하면 됩니다.
네 가지 프레임워크 비교
같은 과제, 예컨대 “주제를 받아 조사하고 보고서를 쓰는 시스템”을 네 프레임워크로 만든다면 개발자가 무엇을 정의하는가가 다릅니다.
| LangChain | LangGraph | 구글 ADK | CrewAI | |
|---|---|---|---|---|
| 개발자가 정의하는 것 | 단계의 순서 | 노드, 엣지, 상태 스키마 | 에이전트와 그 조합 방식 | 역할, 태스크, 프로세스 |
| 흐름의 모양 | 한 방향 파이프 | 임의의 그래프(루프 포함) | 미리 만든 패턴(Sequential·Parallel 등) | 순차형 또는 계층형 |
| 상태 관리 | 대체로 무상태 | 개발자가 명시적으로 | 프레임워크가 내부에서 | 프레임워크가 내부에서 |
| 비유 | 파이프라인 | 정밀한 배선도 | 공장 조립 라인 | 사람 팀의 조직도 |
| 책의 예제 | prompt, model, parser를 잇는 LCEL 체인 |
병렬 LLM 3개 + 집계 | 검색 도구를 쓰는 LlmAgent |
순차 ResearchCrew |
그 밖의 에이전트 개발 프레임워크
| 프레임워크 | 핵심 아이디어 | 강점 | 한계 |
|---|---|---|---|
| 마이크로소프트 AutoGen | 대화를 통해 작업을 해결하는 여러 에이전트를 오케스트레이션. 서로 다른 역량의 에이전트가 상호작용하며 복잡한 문제를 쪼개어 협업으로 푼다 | 유연하고 대화가 주도하는 접근 방식. 유동적이고 복잡한 멀티 에이전트 상호작용을 지원 | 대화 기반 패러다임이라 실행 경로를 예측하기 어렵고, 작업이 효율적으로 수렴하게 하려면 정교한 프롬프트 엔지니어링이 필요할 수 있다 |
| LlamaIndex | 본래 LLM을 외부·비공개 데이터 소스에 연결하도록 설계된 데이터 프레임워크 | 정교한 데이터 수집·검색 파이프라인. RAG를 수행하는 지식이 풍부한 에이전트, 컨텍스트를 인식하는 에이전트를 만드는 데 강하다 | 복잡한 에이전틱 제어 흐름과 멀티 에이전트 오케스트레이션을 위한 내장(native) 도구는 에이전트 우선 프레임워크에 비해 덜 발달. 데이터 검색과 종합이 핵심 과제일 때 가장 잘 맞는다 |
| Haystack | 언어 모델로 구동되며 확장 가능하고 프로덕션에 바로 투입할 수 있는 검색 시스템을 구축하는 오픈 소스 프레임워크. 모듈식이며 상호 운용 가능한 노드들이 문서 검색, 질의응답, 요약 파이프라인을 구성 | 대규모 정보 검색 작업의 성능과 확장성. 기업용 애플리케이션에 잘 맞는다 | 검색 파이프라인에 최적화된 탓에, 매우 유동적이고 창의적인 에이전틱 동작을 구현할 때는 더 경직될 수 있다 |
| MetaGPT | 사전에 정의된 표준 운영 절차(Standard Operating Procedures, SOP) 에 따라 역할과 작업을 할당. 에이전트 협업을 소프트웨어 개발 회사처럼 구조화하며, 에이전트는 제품 관리자나 엔지니어 같은 역할을 맡는다 | SOP가 주도하는 접근 방식은 매우 짜임새 있고 일관성 있는 출력을 만들어 내며, 코드 생성처럼 특화된 분야에서 큰 장점 | 한 분야에 지나치게 특화되어 있어, 핵심 설계 범위를 벗어난 범용 에이전틱 작업에는 적응력이 떨어진다 |
| SuperAGI | 자율 에이전트의 수명 주기 전반을 관리하는 오픈 소스 프레임워크. 에이전트 프로비저닝, 모니터링, 그래픽 인터페이스 같은 기능을 갖춤 | 프로덕션 수준의 완성도. 무한 루프 같은 흔한 실패 유형을 처리하는 메커니즘이 내장되어 있고, 에이전트 성능도 관측할 수 있다 | 플랫폼 하나에 모든 기능을 담은 구조라서, 더 가벼운 라이브러리 기반 프레임워크보다 복잡성과 추가 비용이 커질 수 있다 |
| Semantic Kernel | 마이크로소프트가 개발한, ‘플러그인’과 ‘플래너’ 체계를 통해 LLM을 기존 프로그래밍 코드와 통합하는 SDK. LLM이 네이티브 함수를 호출하고 워크플로를 오케스트레이션하며, 모델을 더 큰 소프트웨어 애플리케이션 안의 추론 엔진처럼 다룬다 | 기존 기업용 코드베이스, 특히 .NET·파이썬 환경과 매끄럽게 통합 | 플러그인과 플래너 아키텍처가 주는 개념적 부담 탓에, 더 단순한 에이전트 프레임워크보다 학습하기 어려울 수 있다 |
| Strands Agents | AI 에이전트를 구축·실행할 때 모델이 주도하는 접근 방식을 쓰는 AWS의 가볍고 유연한 SDK. 기본적인 대화형 도우미부터 복잡한 멀티 에이전트 자율 시스템까지 폭넓게 지원. 특정 모델에 얽매이지 않아 다양한 LLM 공급자를 지원하며, 외부 도구에 쉽게 접근할 수 있도록 MCP와 기본으로 통합 | 단순성과 유연성. 에이전트 루프를 직접 정의할 수 있어 쉽게 시작할 수 있다 | 가볍게 설계된 만큼, 고급 모니터링이나 수명 주기 관리 시스템 같은 주변 운영 인프라는 개발자가 더 많이 직접 구축해야 할 수 있다 |
일곱 프레임워크를 무엇에서 출발했는가로 묶어 보면 선택이 쉬워집니다.
- 대화에서 출발: AutoGen — 에이전트끼리 말을 주고받는 것 자체가 제어 흐름이다.
- 데이터·검색에서 출발: LlamaIndex, Haystack — 14장의 RAG가 주력이고 에이전트 기능은 그 위에 얹었다.
- 조직·절차에서 출발: MetaGPT — 소프트웨어 회사의 SOP를 그대로 본떴다.
- 운영에서 출발: SuperAGI — 프로비저닝, 모니터링, 실패 처리까지 한 플랫폼에 담았다.
- 기존 코드에서 출발: Semantic Kernel — 이미 있는 기업용 애플리케이션에 LLM을 끼워 넣는다.
- 모델에서 출발: Strands Agents — 루프는 모델에게 맡기고 SDK는 가볍게 유지하며, 도구는 10장의 MCP로 연결한다.
표의 한계 열을 보면 모든 항목이 같은 구조를 띱니다. 특정 목적에 최적화된 만큼 그 밖의 용도에서는 경직되거나(Haystack, MetaGPT), 많이 담은 만큼 무겁거나(SuperAGI, Semantic Kernel), 가벼운 만큼 직접 만들어야 할 것이 많습니다(Strands Agents). 공짜 점심은 없다는 말이 프레임워크 선택에도 그대로 적용됩니다.
정리
에이전틱 프레임워크 생태계는 에이전트 로직을 정의하는 저수준 라이브러리부터 멀티 에이전트 협업을 오케스트레이션하는 고수준 플랫폼까지 폭넓은 스펙트럼을 이룹니다.
- 가장 기초 수준에서 LangChain은 단순한 순차 처리 워크플로를 가능하게 한다.
- LangGraph는 더 복잡한 추론을 위해 상태를 지닌 순환 그래프를 도입한다.
- CrewAI나 구글 ADK 같은 고수준 프레임워크는 사전에 정의된 역할을 맡은 에이전트 팀을 오케스트레이션하는 데 초점을 맞춘다.
- LlamaIndex 같은 프레임워크는 데이터 집약적 애플리케이션에 특화되어 있다.
이런 다양성 앞에서 개발자는 핵심 트레이드오프를 마주한다. 그래프 기반 시스템이 주는 세밀한 제어와, 방향성이 뚜렷한 플랫폼이 주는 매끄러운 개발 경험 중에서 무엇을 택할지 고민해야 한다는 뜻이다.
결국 어떤 프레임워크가 맞는지는 애플리케이션에 필요한 것이 무엇인지에 달려 있습니다.
| 애플리케이션에 필요한 것 | 어울리는 선택 |
|---|---|
| 단순한 시퀀스 | LangChain (LCEL) |
| 유동적인 추론 루프 | LangGraph |
| 관리되는 전문가 팀 | CrewAI, 구글 ADK |
| 데이터 검색과 종합 | LlamaIndex, Haystack |
이렇게 발전해 가는 생태계 덕분에 개발자는 자기 프로젝트가 요구하는 정확한 추상화 수준을 선택해 점점 더 정교한 AI 시스템을 구축할 수 있습니다.
마치며
책 전체를 되돌아보면, 이 장의 결론은 1장부터 이미 암시되어 있었습니다. 21개의 패턴은 어떤 프레임워크에도 묶여 있지 않은 설계 개념이고, 프레임워크는 그 개념을 코드로 옮기는 도구일 뿐입니다. 같은 병렬화 패턴이 LangGraph에서는 START에서 세 갈래로 뻗는 엣지가 되고, ADK에서는 ParallelAgent 한 줄이 되며, CrewAI에서는 계층형 프로세스의 관리자가 됩니다.
그래서 프레임워크를 고르는 순서는 반대여야 합니다. 먼저 어떤 패턴이 필요한지 정하고 — 루프가 있는지, 사람이 끼어드는지, 여러 에이전트가 협업하는지, 검색이 핵심인지 — 그 다음에 그 패턴을 가장 적은 마찰로 표현해 주는 도구를 고릅니다. 저수준 도구로 시작하면 모든 배선을 직접 해야 하지만 막히는 곳이 없고, 고수준 도구로 시작하면 빠르지만 프레임워크가 미리 정해 둔 모양을 벗어나는 순간 비용이 급격히 올라갑니다.
패턴을 알면 프레임워크는 갈아 끼울 수 있다. 프레임워크만 알면 패턴은 보이지 않는다.