LangChain 독학 가이드 4 - LCEL 체인 만들기

learning by Seven Fingers Studio 15분
LangChainLCELChainPythonAI

이전 글에서 프롬프트 템플릿을 배웠죠? 근데 템플릿만 있으면 뭐해요, 실제로 AI한테 보내서 답변을 받아야죠. 오늘은 프롬프트 → 모델 → 출력을 하나로 연결하는 **LCEL(LangChain Expression Language)**을 배워볼 거예요.

LCEL이 처음엔 좀 낯설 수 있는데, 알고 보면 진짜 직관적이에요. 리눅스 터미널에서 | (파이프) 쓰듯이 컴포넌트들을 연결하는 거거든요.

LCEL이 뭔가요?

LCEL은 LangChain의 컴포넌트들을 체인처럼 연결하는 문법이에요. 핵심은 **파이프 연산자 |**입니다.

프롬프트 | 모델 | 출력파서

데이터가 왼쪽에서 오른쪽으로 흘러가는 거예요:

  1. 프롬프트에 변수를 넣으면
  2. 모델이 답변을 생성하고
  3. 출력 파서가 결과를 정리해줌

첫 번째 체인 만들기

가장 기본적인 체인부터 만들어볼게요:

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

load_dotenv()

# 1. 프롬프트 템플릿
prompt = ChatPromptTemplate.from_template(
    "{topic}에 대해 한 문장으로 설명해줘."
)

# 2. 모델
model = ChatOpenAI(model="gpt-3.5-turbo")

# 3. 출력 파서
output_parser = StrOutputParser()

# 체인 연결!
chain = prompt | model | output_parser

# 실행
result = chain.invoke({"topic": "인공지능"})
print(result)

실행 결과:

인공지능은 인간의 학습, 추론, 인식 능력을 컴퓨터로 구현하여 스스로 문제를 해결하는 기술입니다.

prompt | model | output_parser 이 한 줄이 핵심이에요! 세 개의 컴포넌트가 파이프로 연결된 거죠.

invoke, batch, stream

체인을 실행하는 방법이 세 가지 있어요:

invoke - 하나씩 실행

# 하나의 입력 처리
result = chain.invoke({"topic": "블록체인"})
print(result)

실행 결과:

블록체인은 분산 네트워크에서 거래 정보를 암호화하여 체인 형태로 연결해 저장하는 기술입니다.

batch - 여러 개 한번에

# 여러 입력을 한번에 처리
results = chain.batch([
    {"topic": "클라우드"},
    {"topic": "메타버스"},
    {"topic": "양자컴퓨터"}
])

for r in results:
    print(f"- {r}")

실행 결과:

- 클라우드는 인터넷을 통해 서버, 저장소, 데이터베이스 등의 컴퓨팅 자원을 제공하는 서비스입니다.
- 메타버스는 현실과 가상이 융합된 3차원 디지털 공간에서 사회·경제 활동이 이루어지는 세계입니다.
- 양자컴퓨터는 양자역학 원리를 활용해 기존 컴퓨터보다 복잡한 연산을 빠르게 처리하는 차세대 컴퓨터입니다.

stream - 실시간 출력

ChatGPT처럼 글자가 하나씩 나오게 하고 싶다면:

# 스트리밍 출력
for chunk in chain.stream({"topic": "머신러닝"}):
    print(chunk, end="", flush=True)

실행 결과:

머신러닝은... (글자가 하나씩 출력됨)

RunnablePassthrough - 입력 그대로 전달

가끔 입력값을 그대로 다음 단계로 전달해야 할 때가 있어요. 그때 RunnablePassthrough를 써요:

from langchain_core.runnables import RunnablePassthrough

# 원본 질문과 답변을 함께 출력하고 싶을 때
prompt = ChatPromptTemplate.from_template(
    "질문: {question}\n\n위 질문에 대해 답변해주세요."
)

chain = (
    {"question": RunnablePassthrough()}
    | prompt
    | model
    | output_parser
)

result = chain.invoke("파이썬이 뭐야?")
print(result)

실행 결과:

파이썬은 1991년 귀도 반 로섬이 개발한 프로그래밍 언어로, 읽기 쉽고 배우기 쉬운 문법이 특징입니다. 데이터 분석, 웹 개발, 인공지능 등 다양한 분야에서 널리 사용됩니다.

RunnableParallel - 병렬 실행

여러 작업을 동시에 처리하고 싶을 때 사용해요:

from langchain_core.runnables import RunnableParallel

# 장점과 단점을 동시에 분석
pros_prompt = ChatPromptTemplate.from_template(
    "{topic}의 장점 3가지를 간단히 말해줘."
)
cons_prompt = ChatPromptTemplate.from_template(
    "{topic}의 단점 3가지를 간단히 말해줘."
)

pros_chain = pros_prompt | model | output_parser
cons_chain = cons_prompt | model | output_parser

# 병렬 실행
parallel_chain = RunnableParallel(
    pros=pros_chain,
    cons=cons_chain
)

result = parallel_chain.invoke({"topic": "재택근무"})
print("=== 장점 ===")
print(result["pros"])
print("\n=== 단점 ===")
print(result["cons"])

실행 결과:

=== 장점 ===
1. 출퇴근 시간 절약으로 개인 시간 확보
2. 유연한 근무 환경으로 집중력 향상
3. 사무실 유지 비용 절감
=== 단점 ===
1. 팀원 간 소통 부족 가능성
2. 업무와 일상의 경계 모호
3. 자기 관리 능력 필요

장점과 단점 분석이 동시에 실행돼서 시간이 절약돼요!

체인 안에 체인 넣기

체인은 중첩해서 사용할 수도 있어요:

# 첫 번째 체인: 주제 추출
extract_prompt = ChatPromptTemplate.from_template(
    "다음 문장에서 핵심 주제를 한 단어로 추출해줘: {text}"
)
extract_chain = extract_prompt | model | output_parser

# 두 번째 체인: 주제 설명
explain_prompt = ChatPromptTemplate.from_template(
    "{topic}에 대해 초등학생도 이해할 수 있게 설명해줘."
)
explain_chain = explain_prompt | model | output_parser

# 체인 연결
full_chain = (
    {"topic": extract_chain}
    | explain_prompt
    | model
    | output_parser
)

result = full_chain.invoke({
    "text": "요즘 ChatGPT 때문에 AI가 화제야"
})
print(result)

실행 결과:

AI는 '인공지능'의 줄임말이에요. 컴퓨터가 사람처럼 생각하고 배울 수 있게 만든 기술이에요. 마치 로봇 친구가 스스로 공부해서 똑똑해지는 것처럼요!

첫 번째 체인에서 “AI”라는 주제를 추출하고, 두 번째 체인에서 그걸 설명하는 거예요.

실전 예시: 번역 체인

실제로 쓸만한 번역 체인을 만들어볼게요:

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

translate_prompt = ChatPromptTemplate.from_messages([
    ("system", "당신은 전문 번역가입니다. 자연스럽고 정확하게 번역해주세요."),
    ("human", "다음 텍스트를 {target_lang}로 번역해주세요:\n\n{text}")
])

model = ChatOpenAI(model="gpt-3.5-turbo")
parser = StrOutputParser()

translate_chain = translate_prompt | model | parser

# 한국어 → 영어
result = translate_chain.invoke({
    "target_lang": "영어",
    "text": "오늘 날씨가 정말 좋네요. 산책하기 딱 좋은 날이에요."
})
print(result)

실행 결과:

The weather is really nice today. It's a perfect day for a walk.

정리

오늘 배운 LCEL 핵심:

  • 파이프 연산자 |: 컴포넌트를 연결
  • invoke: 하나의 입력 처리
  • batch: 여러 입력 한번에 처리
  • stream: 실시간 스트리밍 출력
  • RunnablePassthrough: 입력값 그대로 전달
  • RunnableParallel: 여러 체인 병렬 실행

LCEL은 LangChain의 핵심 문법이에요. 이걸 알아야 RAG, Agent 같은 복잡한 기능도 만들 수 있습니다. 다음 글에서는 다양한 LLM(GPT, Claude, Gemini 등)을 연결하는 방법을 알아볼게요!


다음 글 보기

← 이전 글
LangChain 독학 가이드 3 - 프롬프트 템플릿
다음 글 →
LangChain 독학 가이드 5 - 다양한 LLM 연결하기
← 블로그 목록으로