9월16일(금)

Win Cha·2026년 9월 21일

RAG

챗봇 능력의 단선 파이프라인(Single-line / Linear Pipeline)의 한계

사용자 발화 입력부터 최종 응답 출력까지의 처리 과정이 분기나 피드백 루프 없이 단 하나의 직렬 경로(일방통행)로만 순차 실행되는 구조를 뜻합니다.

[사용자 입력] ──> [입력 전처리/의도 파악] ──> [지식 검색/로직 수행] ──> [응답 생성] ──> [최종 출력]

핵심 특징

  • 직렬 순차 실행: 앞 단계의 결과가 그대로 다음 단계의 입력이 되며, 역방향 재시도나 다중 에이전트 간 협업 없이 한 방향으로 흐릅니다.
  • 낮은 제어 복잡도: 조건에 따른 동적 분기(Dynamic Branching)나 자기 반성(Self-reflection), 도구 재호출 루프가 없어 구조가 단순하고 응답 지연(Latency)이 짧습니다.

주요 한계점

  • 오류 전파(Error Propagation): 앞선 단계(예: 의도 분류 실패, 잘못된 RAG 검색 문서 반환)에서 오차가 발생하면 뒤 단계에서 이를 자가 교정하지 못하고 그대로 환각이나 오답으로 이어집니다.
  • 복합 추론 한계: "날씨를 조회한 뒤 그 결과에 맞춰 옷차림을 추천하고 캘린더에 일정을 잡는" 식의 다단계 의존 작업이나 예외 상황 대응(루프·백트래킹) 처리가 어렵습니다.

발전된 파이프라인 형태와의 비교

구분단선 파이프라인 (Linear Chain)순환·분기형 에이전트 파이프라인 (Graph/Loop)
흐름 구조일방통행 직렬 연결 (A → B → C)조건부 분기(Router), 순환 루프(Graph DAG)
오류 처리실패 시 시스템 에러 또는 오답 출력자가 평가(Reflection) 후 재검색·재작성 루프 수행
도구 활용정해진 순서대로 1회 호출결과에 따라 필요한 도구를 자율적으로 반복 호출
구현 예시단순 LangChain SequentialChainLangGraph, LangSmith, AutoGen, Multi-Agent 시스템

위 단선 파이프라인으로는 해결하기 위한 방법으로는?

  • LangChain, LangGraph

랭체인(LangChain)은?

거대 언어 모델(LLM)을 단독 텍스트 생성기에 머무르게 하지 않고, 외부 데이터베이스, API, 계산 도구 등과 연결해 실무형 애플리케이션(RAG 시스템, 자율 에이전트 등)으로 조립·구축할 수 있도록 돕는 오픈소스 오케스트레이션 프레임워크입니다.

[입력 프롬프트] ──> [LCEL 체인 파이프라인] ──> [벡터 DB / 도구 연동] ──> [LLM 추론] ──> [구조화된 출력]

핵심 구성 요소

  • 프롬프트 템플릿 (Prompt Templates): 동적 변수 주입 및 역할(System, Human, AI) 설정을 표준화하여 모델에 전달할 프롬프트를 모듈화합니다.
  • 모델 연결 추상화, I/O (Model I/O): OpenAI, Anthropic, 오픈소스 로컬 LLM(Ollama, vLLM 등)의 다양한 인터페이스를 통일된 표준 호출 방식으로 추상화합니다.
  • 검색 엔진 연동 (Retrieval / RAG): 텍스트 로더(Document Loaders), 청크 분할기(Text Splitters), 임베딩 모델, 벡터 데이터베이스(Chroma, Pinecone, pgvector 등)를 유기적으로 연결해 외부 지식 검색을 자동화합니다.
  • 메모리 (Memory): 대화형 인터페이스에서 이전 대화 이력을 요약하거나 버퍼 형태로 저장해 문맥 연속성을 유지합니다.
  • 에이전트 및 도구 (Agents & Tools): LLM이 사용자의 질문을 분석해 웹 검색, 계산기, SQL 쿼리 실행 등 필요한 외부 도구를 스스로 판단하고 호출(Tool Calling)하게 만듭니다.
  • LCEL (LangChain Expression Language): 유닉스 파이프(|) 문법을 사용해 구성 요소들을 직관적으로 엮고, 비동기(async) 처리, 스트리밍, 병렬 실행을 기본 지원하는 선언적 파이프라인 문법입니다.

파이썬 기본 파이프라인 예시 (LCEL)

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

# 1. 프롬프트 정의
prompt = ChatPromptTemplate.from_template("{topic}에 대해 핵심만 3줄로 요약해 줘.")

# 2. 모델 설정
model = ChatOpenAI(model="gpt-4o-mini", temperature=0)

# 3. 체인 결합 (LCEL)
chain = prompt | model | StrOutputParser()

# 4. 실행
response = chain.invoke({"topic": "Docker"})
print(response)

도입 장단점

구분장점단점 및 고려사항
개발 생산성수백 가지 서드파티 도구·DB 연동 어댑터가 완비되어 프로토타입 구축 속도가 매우 빠름과도한 추상화 레이어로 인해 세부 내부 로직 디버깅 및 트러블슈팅 난도가 높음
확장성LCEL 기반의 스트리밍, 비동기 호출, 병렬 처리 기본 내장라이브러리 업데이트 및 패키지 구조 개편이 잦아 버전 의존성 관리가 까다로움

추상화(Abstraction)란?

복잡한 내부 세부 구현 사항(네트워크 통신, 파싱, API 규격 등)을 감추고, 개발자가 공통의 단순한 인터페이스(메서드 규격)만 다루도록 만드는 객체지향 프로그래밍(OOP) 및 소프트웨어 설계 핵심 기법입니다.

자동차가 내연기관 엔진인지 전기 모터인지 상관없이 운전자는 엑셀과 브레이크 페달이라는 동일한 인터페이스로 조작하듯, LangChain은 모델이나 DB 종류가 달라도 동일한 함수 규격으로 통제할 수 있게 만듭니다.

LangChain의 주요 4대 추상화 계층

  • 모델 호출 추상화 (BaseChatModel):
  • OpenAI, Anthropic, Ollama, HuggingFace 등 공급자마다 파라미터명과 요청/응답 JSON 포맷이 완전히 다릅니다.
  • LangChain은 이를 감추고 모든 모델을 .invoke(), .stream(), .batch()라는 동일한 메서드로 호출하도록 감싸(Wrapper), 코드 수정 없이 모델 객체만 교체할 수 있게 합니다.
  • 입력 데이터 표준화 (PromptTemplate):
  • 각 LLM마다 요구하는 역할 체계(System, User, Assistant)와 메시지 직렬화 방식을 표준화하여 변수 매핑({variable}) 하나로 통합 관리합니다.
  • 출력 파싱 추상화 (BaseOutputParser):
  • 모델이 반환하는 원시 응답(Text/JSON)을 Python 문자열, 딕셔너리, 또는 Pydantic 데이터 클래스 객체로 자동 검증·변환합니다.
  • 저장소 및 검색 추상화 (VectorStore, Retriever):
  • pgvector, Chroma, Pinecone, FAISS 등 서로 다른 DB의 임베딩 저장 및 유사도 쿼리 문법을 감추고 .as_retriever()를 통해 일관된 get_relevant_documents() 인터페이스로 조회합니다.

코드 비교: 원시 API vs LangChain 추상화 (LCEL)

1. 원시 API 직접 구현 시 (추상화 없음)

# OpenAI API 기준 (모델을 바꾸려면 엔드포인트와 응답 처리 코드를 전부 뜯어고쳐야 함)
import openai

client = openai.OpenAI()
raw_res = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "RAG 설명해줘"}],
)
text = raw_res.choices[0].message.content

2. LangChain 추상화 적용 시 (LCEL)

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
# from langchain_anthropic import ChatAnthropic # 모델 교체 시 이 줄만 변경

prompt = ChatPromptTemplate.from_template("{topic}에 대해 설명해 줘.")
model = ChatOpenAI(model="gpt-4o")  # 추상 인터페이스 구현체
parser = StrOutputParser()

# 파이프라인 결합
chain = prompt | model | parser
result = chain.invoke({"topic": "RAG"})

추상화의 실무적 장단점

구분장점단점 및 주의점
개발 생산성코드 몇 줄로 LLM + 벡터 DB + 도구를 연결해 빠른 RAG/에이전트 프로토타입 구현 가능세부 레이어가 여러 겹 감싸져 있어 API 에러나 성능 병목 발생 시 디버깅이 어려움
코드 이식성모델(OpenAI ↔ 로컬 vLLM)이나 벡터 DB를 교체할 때 비즈니스 로직 수정 최소화LangChain 고유 문법(LCEL, 체인 클래스)을 별도로 익혀야 하며 프레임워크 락인 발생

LangGraph는 ?

거대 언어 모델(LLM)을 이용해 순환(Loop)과 조건부 분기(Branching)가 포함된 복잡한 에이전트 워크플로우를 구축하기 위해 LangChain 팀이 개발한 그래프 기반 오케스트레이션 라이브러리입니다.

기존 LangChain의 체인(LCEL)이 앞선 단계에서 다음 단계로만 흐르는 단선형(DAG, 비순환 방향 그래프) 방식이었다면, LangGraph는 상태를 유지하며 실패 시 이전 단계로 되돌아가거나 재시도하는 순환형 상태 머신(Cyclic State Machine)을 지원합니다.

       ┌────────────────────────┐
       │   사용자 입력 / 시작    │
       └───────────┬────────────┘
                   ▼
         ┌───────────────────┐
    ┌───>│  에이전트 노드     │<───┐
    │    │ (추론 및 도구 판단)│    │
    │    └─────────┬─────────┘    │
    │              │             │
    │      [조건부 엣지 분기]      │
    │         /         \        │
    │   (도구 필요)   (완료)       │
    │       /             \      │
    │      ▼               ▼     │
    │ ┌─────────┐     ┌─────────┐  │
    └─┤ 도구 실행│     │최종 출력│  │
      └─────────┘     └─────────┘  │
           └──────────-------─────┘
             (자가 교정 / 재검색 루프)

핵심 아키텍처 요소

  • 상태 (State):
  • 그래프 전역에서 공유되는 중앙 데이터 저장소(주로 TypedDict나 Pydantic 모델)입니다.
  • 노드가 실행될 때마다 상태가 덮어씌워지거나 누적(Reducer 패턴, 예: 대화 기록 추가)되면서 문맥이 유지됩니다.
  • 노드 (Nodes):
  • 실제 로직을 수행하는 Python 함수 또는 Runnable 객체입니다.
  • 현재 상태(State)를 입력받아 작업을 수행(LLM 추론, 도구 호출, DB 쿼리 등)한 후, 갱신된 상태 딕셔너리를 반환합니다.
  • 엣지 (Edges):
  • 노드와 노드 사이의 이동 경로를 정의합니다.
  • 일반 엣지 (Normal Edges): A 노드가 끝나면 무조건 B 노드로 이동합니다.
  • 조건부 엣지 (Conditional Edges): LLM의 판단 결과나 상태 값에 따라 라우팅할 다음 노드를 동적으로 결정합니다 (예: "검색 결과가 부실하면 재검색 노드로, 충분하면 작성 노드로 이동").
  • 체크포인터 (Checkpointer / 영속성):
  • 그래프의 각 실행 단계(Step) 상태를 데이터베이스(Memory, SQLite, PostgreSQL 등)에 스냅샷으로 자동 저장합니다.
  • 사람이 중간에 개입해 승인하거나 수정하는 Human-in-the-loop(HITL) 기능과 작업 되감기(Time-travel)를 가능하게 합니다.

LangChain (LCEL) vs LangGraph 비교

비교 항목LangChain (LCEL)LangGraph
흐름 구조단선 직렬 / 비순환 (DAG)순환 허용 그래프 (Cyclic Graph)
상태 관리입력과 출력이 파이프를 통해 전달공유 상태(State) 기반 중앙 집중식 관리
오류 복구실패 시 중단되거나 단순 Fallback반성(Reflection) 노드를 통한 자가 수정 루프
적합한 작업정형화된 RAG 파이프라인, 단순 질의응답멀티 에이전트 협업, 코드 디버깅 반복, 복합 업무 자동화

간단한 구현 예시 (상태 기반 루프 구조)

from typing import Annotated, TypedDict
from langgraph.graph import END, StateGraph
from langgraph.graph.message import add_messages


# 1. 전역 상태 정의
class AgentState(TypedDict):
    messages: Annotated[list, add_messages]


# 2. 노드 함수 정의
def call_model(state: AgentState):
    # LLM 호출 로직 (생략)
    return {"messages": ["모델의 응답 또는 도구 요청"]}


def run_tool(state: AgentState):
    # 외부 도구 실행 로직 (생략)
    return {"messages": ["도구 실행 결과"]}


# 3. 라우팅 조건 함수
def should_continue(state: AgentState):
    last_message = state["messages"][-1]
    if "도구 요청" in str(last_message):
        return "tools"
    return END


# 4. 그래프 빌드 및 엣지 연결
workflow = StateGraph(AgentState)
workflow.add_node("agent", call_model)
workflow.add_node("tools", run_tool)

workflow.set_entry_point("agent")
workflow.add_conditional_edges(
    "agent", should_continue, {"tools": "tools", END: END}
)
workflow.add_edge("tools", "agent")  # 도구 결과를 들고 다시 에이전트로 순환(Loop)

app = workflow.compile()

LangGraph는 단선 파이프라인의 가장 큰 한계였던 "오류 전파 및 자가 교정 불가" 문제를 해결하여, 상용 수준의 자율 에이전트와 정교한 RAG(Self-RAG, Corrective RAG)를 구현할 때 사실상의 표준 프레임워크로 활용됩니다.


LangGraph의 노드(Node)와 엣지(Edge)의 자세한 설명은?

그래프 아키텍처 기반으로 에이전트의 '행동'과 '흐름 제어'를 정의하는 두 핵심 구성 요소입니다.

노드가 무엇을 할 것인가(작업 단위)를 정의한다면, 엣지는 다음에 어디로 갈 것인가(이동 경로 및 분기)를 결정합니다.

1. 노드 (Nodes): 작업을 수행하는 독립된 실행 단위

노드는 그래프의 상태(State)를 입력받아 특정 작업을 처리한 뒤, 변경된 상태를 반환하는 Python 함수 또는 Runnable 객체입니다.

  • 동작 방식:
  1. 현재 공유 상태(State)를 전달받습니다.
  2. 로직(LLM 추론, 도구 호출, DB 쿼리, 데이터 전처리 등)을 수행합니다.
  3. 전체 상태 중 갱신할 키-값 쌍(Dictionary)만 반환하여 상태를 업데이트합니다.
  • 주요 유형:
  • 에이전트 노드: 프롬프트와 LLM을 실행하여 다음 작업이나 도구 호출 여부를 결정합니다.
  • 도구 노드 (ToolNode): 모델이 요청한 외부 함수(검색, 계산기, API 호출 등)를 실제로 실행합니다.
  • 반성/평가 노드: 생성된 답변의 정확도를 채점하거나 검색 문서의 적합성을 평가합니다.

2. 엣지 (Edges): 노드 간의 이동 경로 및 제어 흐름

엣지는 한 노드의 실행이 끝난 후 다음에 실행할 노드를 연결하는 통로입니다. LangGraph는 단순 직렬 이동뿐만 아니라 조건부 분기와 순환(Loop)을 엣지로 제어합니다.

  • 일반 엣지 (Normal Edge):
  • 조건 없이 항상 고정된 다음 노드로 이동합니다 (A -> B).
  • workflow.add_edge("node_a", "node_b") 형태로 등록합니다.
  • 조건부 엣지 (Conditional Edge):
  • 이전 노드의 결과(상태 값)를 라우팅 함수로 평가하여, 반환값에 따라 분기할 다음 노드를 동적으로 결정합니다.
  • workflow.add_conditional_edges("agent", should_continue, {"tools": "tools", "end": END})
  • 예: "도구 호출이 필요하면 tools 노드로, 작업이 완료되었으면 END 노드로 이동".
  • 진입점 및 종료 엣지 (Entry Point & END):
  • 그래프 실행 시 가장 먼저 시작할 시작 노드(START / set_entry_point)와 최종 작업을 마치는 종료 노드(END)를 지정합니다.

노드와 엣지의 상호작용 구조

요소역할입력 및 출력코드 상의 형태
State (상태)노드 간 데이터를 주고받는 전역 버퍼스키마 정의 (TypedDict, Pydantic)class AgentState(TypedDict): ...
Node (노드)상태를 소비하고 갱신하는 실행 주체State 입력 ➔ dict 반환def run_agent(state): return {...}
Edge (엣지)제어권(실행 순서) 전달 및 조건부 분기이전 노드 ➔ 라우팅 판단 ➔ 다음 노드workflow.add_edge() / add_conditional_edges()
# 노드 등록
workflow.add_node("llm_reasoning", call_llm)  # 노드 1
workflow.add_node("execute_tools", run_tools)  # 노드 2

# 엣지 연결 (순환 구조 형성)
workflow.set_entry_point("llm_reasoning")

# 조건부 엣지: 결과에 따라 tools로 가거나 종료(END)
workflow.add_conditional_edges(
    "llm_reasoning", decide_next_step, {"tools": "execute_tools", "done": END}
)

# 일반 엣지: 도구 실행 후 다시 LLM 판단 노드로 복귀 (Loop)
workflow.add_edge("execute_tools", "llm_reasoning")

LangSmith는?

LangChain 생태계에서 개발한 LLMOps(대형 언어 모델 운영) 전용 모니터링, 디버깅, 테스팅 및 평가 플랫폼입니다.

LangChain이나 LangGraph 같은 복잡한 프레임워크는 내부가 여러 추상화 계층으로 감싸져 있어 "블랙박스"처럼 동작하기 쉬운데, LangSmith는 각 단계의 입출력, 지연 시간, 토큰 비용 등을 투명하게 시각화하여 상용화 수준으로 끌어올리는 관측성(Observability) 도구입니다.

[사용자 요청] ──> [LangChain / LangGraph 실행] ──> [최종 응답]
                         │
                         ▼ (자동 추적 전송)
               ┌───────────────────────┐
               │       LangSmith     │
               │ • 각 단계 입출력 로깅  │
               │ • 지연 시간 / 토큰 추적│
               │ • 데이터셋 기반 평가   │
               └───────────────────────┘

핵심 4대 기능

  • 추적 및 디버깅 (Tracing & Debugging):
  • 체인이나 에이전트가 실행될 때 거치는 모든 내부 단계(프롬프트 조립, 임베딩 생성, 벡터 DB 검색 결과, LLM 원시 응답, 도구 호출 파라미터)를 트리 구조로 시각화합니다.
  • 어디서 환각이 발생했는지, 어떤 도구가 잘못된 인자를 받았는지 즉시 식별할 수 있습니다.
  • 비용 및 지연 시간 모니터링 (Metrics & Monitoring):
  • 호출별 총 소요 시간(Latency), 사용된 프롬프트/완성 토큰 수, 달러 환산 비용을 자동으로 계산하여 병목 지점과 과도한 과금 요인을 추적합니다.
  • 평가 및 데이터셋 관리 (Evaluation & Datasets):
  • 실패했던 실제 사용자 입출력 로그를 클릭 한 번으로 테스트 데이터셋으로 저장할 수 있습니다.
  • 프롬프트나 모델을 바꿨을 때 품질이 개선되었는지 LLM-as-a-Judge나 휴리스틱 기준으로 자동 벤치마크 테스트를 수행합니다.
  • 프롬프트 허브 및 플레이그라운드 (Prompt Engineering):
  • 웹 콘솔에서 프롬프트를 직접 수정하고 다양한 LLM에 바로 실행해보며 최적의 템플릿 버전을 관리(Versioning)할 수 있습니다.

적용 방식 (코드 수정 최소화)

LangSmith는 별도의 복잡한 로깅 코드를 삽입할 필요 없이, 환경 변수 설정만으로 기존 LangChain/LangGraph 파이프라인과 자동 연동됩니다.

# 환경 변수 설정만으로 자동 추적 활성화
export LANGCHAIN_TRACING_V2="true"
export LANGCHAIN_API_KEY="ls__your_api_key"
export LANGCHAIN_PROJECT="my-rag-service"

LangChain 생태계 3대 축 요약

도구주 역할비유
LangChain선형 파이프라인 및 도구·DB 추상화 조립기본 레고 블록 및 부품 결합기
LangGraph상태 기반 순환 루프 및 복합 멀티 에이전트 제어복잡한 궤도와 회로를 가진 기계 장치
LangSmith전 과정 모니터링, 디버깅, 품질 평가, 비용 추적종합 계측기 및 관제실 모니터

도전과제 - 내 PC에서 돌아가는 문서 챗봇

  1. 목표
    브라우저 localhost에서, 내가 고른 문서에 질문하면, 근거 조항과 함께 답하는 화면 만들기
    배포는 하지 않습니다
    ROOT 7강 코드를 참고하되, 코랩이 아닌 내 PC에서 돌아가야 합니다
    화면은 AI를 활용해서 만들어도 됩니다

2.규칙
API 키는 코드에 직접 쓰지 않는다 -> .env 파일에 저장
.env 파일은 절대 깃허브에 올리지 않는다
답변 생성은 API로 한다 (claude-haiku-4-5, gpt-4o-mini 같은 저렴한 모델)
막히면 체크포인트 번호와 함께 오픈채팅으로 질문

  1. 도전 1
    로컬 환경 구축
    아나콘다 프롬프트에서 새 conda 환경 만들기
    필요한 라이브러리 설치
    VS Code에서 .py 파일로 작업 환경 잡기
    .env 파일에 API 키 저장, python-dotenv로 불러오기
    터미널에서 LLM API 한 번 호출해보기
    체크포인트 1 : 내 PC 터미널에서 API 호출 성공

  2. 도전 2. 문서 하나 잡고 RAG 만들기
    문서를 하나 고른다
    예) 우리 학교 학사규정, 근로기준법, 주택임대차보호법, 관심 있는 회사 규정 등
    PDF가 다루기 편합니다
    텍스트 추출 -> 정제 -> 청킹
    내 문서에 맞는 청킹 기준을 직접 정해보세요 (조항 단위? 글자 수? 문단?)
    임베딩 후 Chroma에 저장
    PersistentClient 사용 -> 한 번 만든 임베딩은 디스크에 저장해두고 재사용
    질문 -> 검색 -> 답변 흐름 완성
    답변 끝에 근거(조항 번호, 페이지 등)가 나오도록
    문서에 없는 내용은 "문서에서 확인되지 않습니다"라고 답하도록
    체크포인트 2 : 터미널에서 질문하면 근거가 붙은 답이 나온다

  3. 도전 3. AI로 화면 입히기
    Streamlit으로 채팅 화면 만들기
    AI에게 도전 2 코드를 주고 화면을 붙여달라고 요청해보세요
    브라우저 localhost에서 질문하고 답변 받기
    화면이 느리거나 이상하면 왜 그런지 먼저 의심해보기
    힌트 : Streamlit은 버튼을 누를 때마다 무엇을 다시 실행할까?
    체크포인트 3 : 브라우저에서 질문하고 답과 근거를 본다

  4. 추가 과제
    대화 이력 유지 (ROOT 6강 멀티턴 활용)
    청킹 전략 2개를 화면에서 바꿔가며 결과 비교
    여러 문서를 넣고 문서별로 필터링해서 검색

  5. 비상구
    PC가 너무 느려서 임베딩이 안 끝나면
    -> 임베딩만 코랩 GPU에서 만들고, Chroma 저장 폴더를 zip으로 받아서 로컬에 풀어서 사용

  6. 제출 및 벨로그 업로드 - 오늘까지 아닙니다
    오픈채팅에 아래 내용 텍스트로 공유
    완성 화면 캡처 1장 (못 끝냈으면 도달한 체크포인트 번호)
    고른 문서와 청킹 기준
    제일 오래 막힌 곳 한 줄
    추석 이후 개인 프로젝트로 키운다면 뭘 해보고 싶은지 한 줄

0개의 댓글