Clip 1: workflow -> Agentic의 개념 복기하기
학습 목표
- Workflow와 Agent의 차이점을 실제 구현을 통해 이해하기 
- 구현한 Langgraph Routing RAG Workflow의 장단점 분석하기 
- Agent 기반 RAG로 전환해야 하는 이유 파악하기 
1. Workflow vs Agent 개념 복기
Workflow의 특징
Workflow는 미리 정의된 경로를 따라 실행되는 시스템입니다.
핵심 특징:
- 사전 정의된 경로: 노드와 엣지가 코드로 명확하게 정의됨 
- 예측 가능성: 어떤 입력이 들어와도 동일한 경로를 따름 
- 제어 가능성: 각 단계를 명확하게 제어하고 디버깅 가능 
- 구조화: 복잡한 프로세스를 명확한 단계로 분해 
Agent의 특징
Agent는 LLM이 자율적으로 도구를 선택하고 실행하는 시스템입니다.
핵심 특징:
- 동적 의사결정: LLM이 상황에 따라 어떤 도구를 사용할지 결정 
- 유연성: 예상치 못한 질문에도 적절히 대응 
- 자율성: 도구 선택과 실행 순서를 LLM이 제어 
- 적응성: 새로운 도구 추가 시 코드 수정 최소화 
주요 차이점
Workflow 방식 (고정된 경로):
Agent 방식 (동적 도구 선택):
2. 구현한 Langgraph Routing RAG Workflow 분석
현재 구현 구조
앞서 구현한 langgraph_rag.py는 다음과 같은 Workflow 구조를 가집니다:
┌─────────┐
│  START  │
└────┬────┘
     │
     ▼
┌──────────────┐
│  Route Node  │ ◄── 질문 분석: search or direct?
└──────┬───────┘
       │
       ├─────────────────┐
       │                 │
       ▼                 ▼
  [search]          [direct]
       │                 │
       ▼                 │
┌────────────────┐       │
│ Retrieve Node  │       │
│ (Hybrid Search)│       │
└────────┬───────┘       │
         │               │
         └───────┬───────┘
                 │
                 ▼
         ┌───────────────┐
         │ Generate Node │ ◄── 답변 생성
         └───────┬───────┘
                 │
                 ▼
             ┌─────┐
             │ END │
             └─────┘실행 흐름:
- Route Node: 질문 분석하여 검색 필요 여부 판단 ( - searchor- direct)
- Retrieve Node (조건부): - search판단 시 Hybrid Search 실행
- Generate Node: 검색 결과(또는 없이) 답변 생성 
실제 코드 구조 (langgraph_rag.py:268-300)
def build_graph() -> StateGraph:
    """Langgraph 워크플로우 구성"""
    workflow = StateGraph(State)
    # 노드 추가
    workflow.add_node("route", route_node)
    workflow.add_node("retrieve", retrieve_node)
    workflow.add_node("generate", generate_node)
    # 엣지 정의
    workflow.add_edge(START, "route")
    # 조건부 엣지: route → retrieve or generate
    workflow.add_conditional_edges(
        "route",
        should_retrieve,
        {
            "retrieve": "retrieve",
            "generate": "generate"
        }
    )
    # retrieve → generate
    workflow.add_edge("retrieve", "generate")
    workflow.add_edge("generate", END)
    return workflow.compile()3. Workflow 구현의 장단점
장점 ✅
1. 높은 예측 가능성
- 모든 경로가 명확하게 정의되어 있어 디버깅이 쉬움 
- 어떤 입력이 들어와도 동일한 흐름을 따름 
2. 제어 가능성
- 각 노드에서 정확히 무엇을 할지 코드로 명시 
- Route 단계에서 검색 필요 여부를 확실히 제어 
3. 성능 최적화
- 불필요한 검색을 방지하여 비용 절감 
- 일반적인 질문은 바로 답변 생성 
4. 명확한 구조
# search_app/langgraph_rag.py:93-133
def route_node(state: State) -> State:
    """Route 노드: 질문을 분석하여 검색 필요 여부 판단"""
    question = state["question"]
    messages = [
        SystemMessage(content="""당신은 질문을 분석하는 전문가입니다.
사용자의 질문이 농협 대출 상품에 대한 구체적인 정보를 요구하는지 판단하세요.
- 대출 상품 검색이 필요한 경우: "search"
- 일반적인 질문이나 인사말: "direct"
..."""),
        HumanMessage(content=question)
    ]
    response = llm.invoke(messages)
    route_decision = response.content.strip().lower()
    if "search" in route_decision:
        route_decision = "search"
    else:
        route_decision = "direct"
    return {**state, "route_decision": route_decision}단점 ❌
1. 유연성 부족
문제: 새로운 상황에 대응하려면 노드와 엣지를 계속 추가해야 함
예시:
- 현재: - route → retrieve → generate
- 추가 요구사항 1: "검색 결과가 불충분하면 웹 검색 추가" → 새로운 노드와 조건부 엣지 추가 필요 
- 추가 요구사항 2: "여러 번 검색해야 하는 복잡한 질문" → 루프 로직 추가 필요 
- 추가 요구사항 3: "데이터베이스에서 직접 통계 조회" → 또 다른 노드와 분기 추가 필요 
2. 복잡도 증가
새로운 기능을 추가할 때마다:
- 새로운 노드 함수 작성 
- 조건부 엣지 로직 수정 
- State 타입 확장 
- 테스트 케이스 추가 
# 기능 추가 시 필요한 수정 예시
class State(TypedDict):
    question: str
    route_decision: str
    documents: list
    answer: str
    debug: bool
    # 새 기능마다 필드 추가 필요
    web_search_results: list  # 추가 1
    database_query_result: dict  # 추가 2
    multi_search_count: int  # 추가 33. LLM의 능력을 완전히 활용하지 못함
현재 방식의 한계:
- Route 단계에서만 LLM이 판단 
- 이후는 고정된 경로를 따름 
- LLM이 "더 많은 정보가 필요하다"고 판단해도 추가 검색 불가 
예시 시나리오:
사용자: "30대 의사에게 가장 적합한 대출 상품은?"
[현재 Workflow]
1. Route: "search" 판단
2. Retrieve: "의사 대출" 검색 → 3개 결과
3. Generate: 답변 생성
   → 만약 결과가 불충분해도 추가 검색 불가
[이상적인 Agent]
1. LLM: "의사 대출" 검색 실행
2. LLM: 결과 검토 후 "30대에 특화된 정보가 부족함"
3. LLM: "청년 우대 대출" 추가 검색
4. LLM: 두 결과를 종합하여 답변4. 확장성 문제
새로운 검색 소스를 추가할 때마다 노드와 조건부 엣지가 계속 증가합니다:
문제점: 빨간색으로 표시된 노드들은 새로 추가해야 하는 검색 소스입니다. 각각의 추가마다 코드 수정이 필요합니다.
4. Agent로 전환해야 하는 이유
Agent 방식의 작동 원리
# Agent 방식 (개념)
agent = Agent(
    tools=[
        hybrid_search_tool,
        web_search_tool
    ]
)
# LLM이 자율적으로 도구를 선택하고 실행
result = agent.run("30대 의사에게 가장 적합한 대출 상품은?")
# 내부 실행 흐름 (LLM이 자동으로 결정)
# 1. hybrid_search_tool("의사 대출")
# 2. [결과 확인] "더 많은 정보 필요"
# 3. web_search_tool("30대 의사 대출 추천")
# 4. [결과 확인] "충분함"
# 5. 답변 생성Agent의 핵심 장점
1. 동적 도구 선택
Workflow: 코드에 정의된 순서대로 실행
Agent: LLM이 상황에 따라 필요한 도구만 선택2. 유연한 대응
Workflow: 예상하지 못한 질문 → 에러 또는 부적절한 답변
Agent: 예상하지 못한 질문 → 도구를 조합하여 해결3. 확장 용이성
# 새로운 도구 추가
tools.append(new_calculator_tool)  # Agent는 자동으로 활용4. 자연스러운 대화
Workflow: "이 질문은 검색이 필요합니다" (기계적)
Agent: "잠시만요, 관련 정보를 찾아보겠습니다" (자연스러움)5. 실전 비교: Workflow vs Agent
시나리오: "의사 전용 대출의 금리와 한도를 비교해줘"
Workflow 방식
# 1단계: Route (고정)
route_decision = route_node(question)  # "search" 반환
# 2단계: Retrieve (고정)
documents = hybrid_search(question, limit=3)  # 항상 3개
# 3단계: Generate (고정)
answer = generate_with_documents(documents)  # 무조건 답변 생성
# 문제: 3개 결과가 불충분해도 추가 검색 불가Agent 방식
# LLM이 자율적으로 판단하고 실행
agent_execution = [
    {"thought": "금리와 한도 정보가 필요하니 검색해야겠다"},
    {"action": "hybrid_search_tool", "input": "의사 전용 대출"},
    {"observation": "3개 상품 발견, 하지만 금리 정보가 부족함"},
    {"thought": "더 구체적인 금리 정보를 찾아야겠다"},
    {"action": "hybrid_search_tool", "input": "의사 전용 대출 금리"},
    {"observation": "상세 금리 정보 획득"},
    {"thought": "이제 충분한 정보를 수집했다"},
    {"final_answer": "의사 전용 대출 상품 비교..."}
]핵심 메시지:
Workflow는 명확한 경로를 제공하지만, Agent는 복잡한 상황에 유연하게 대응합니다. 대출 상담과 같이 다양한 질문과 맥락이 존재하는 도메인에서는 Agent가 더 효과적입니다.
6. 다음 단계: Agent 구현 방법
다음 Clip에서는 실제로 Agent를 구현합니다. 구현 방법은 다음과 같습니다:
웹 검색이 필요한 이유
대출 상담 Agent에 웹 검색을 추가하는 이유는 최신 금융 정보 검색이 필요하기 때문입니다.
실제 시나리오:
사용자: "2025년 기준금리가 어떻게 되나요? 현재 대출 받기 좋은 시기인가요?"
[문제점]
- 내부 DB: 농협 대출 상품 정보만 있음 (기준금리 정보 없음)
- 기준금리는 한국은행이 정기적으로 변경
- 금융 시장 동향은 실시간으로 변함
[해결책: Web Search 추가]
1. Hybrid Search: 농협 대출 상품 검색 (내부 DB)
2. Tavily Search: "2025년 한국은행 기준금리" 검색 (웹)
3. Agent: 두 정보를 종합하여 답변 생성Agent가 유연하게 대응하는 예시:
- 일반 대출 질문 → Hybrid Search만 사용 
- 기준금리, 시장 동향 질문 → Tavily Search만 사용 
- 복합 질문 → 두 도구를 모두 사용 
Tavily Search API 사용
Web Search는 Tavily Search API를 사용합니다.
Tavily 선택 이유:
- 무료 사용량: 한 달에 1,000건까지 무료 제공 
- 비용 효율: 추가 금액 없이 즉시 사용 가능 
- 간단한 API: REST API로 직접 호출 가능 
- 고품질 결과: 웹 검색 결과를 AI 친화적 형태로 제공 
참고: OpenAI 내장 Search Tool은 추가 비용이 발생하므로 Tavily를 사용합니다.
Agent 도구 구성
# Agent에 제공할 도구
tools = [hybrid_search_tool, tavily_search_tool]프론트엔드 구조
Vercel AI SDK Python 샘플을 클론하여 사용:
# 1. 프론트엔드 클론
git clone https://github.com/vercel-labs/ai-sdk-preview-python-streaming
cd ai-sdk-preview-python-streaming
# 2. 백엔드만 수정
# 프론트엔드는 그대로 사용요약
경로
고정된 노드와 엣지
LLM이 동적으로 결정
도구
코드로 명시
Function Calling 사용
Web Search
별도 구현 필요
Tavily API (무료 1000건)
비용
OpenAI API만
OpenAI + Tavily 무료
프론트엔드
직접 구현
Vercel 샘플 활용
참고 자료
강사 정보
- 작성자: 정구봉 
- LinkedIn: https://www.linkedin.com/in/gb-jeong/ 
- 이메일: bong@dio.so 
강의 자료
- 강의 자료: https://goobong.gitbook.io/fastcampus 
- Github: https://github.com/Koomook/fastcampus-ai-agent-vibecoding 
- FastCampus 강의 주소: https://fastcampus.co.kr/biz_online_vibeagent 
Last updated