🌏 인트로
LLM 기반 서비스를 만들 때 가장 핫한 기술 중 하나는 RAG 입니다.
그런데 실제로 구현해보면 모델을 불러서 돌리는 것보다, 파이프라인을 어떻게 연결할지, 메모리를 어디에 둘지, 프롬프트 변형은 어떤 조건에서 할지 같은 구성 문제가 훨씬 어렵습니다.
LangChain과 LangGraph는 이런 복잡한 LLM 워크플로우를 안정적으로 만들기 위해 등장한 도구입니다.
✅ 사전지식: RAG(Retrieval-Augmented Generation)
RAG(Retrieval-Augmented Generation)는 모델이 답을 생성하기 전에, 외부 지식 저장소에서 관련 문서를 검색해 함께 넣어주는 방식입니다.
LLM은 기본적으로 학습 시점까지의 정보만 알고 있어 최신 데이터나 사내 데이터는 알 수 없기 때문에, RAG는 모델이 모르는 것을 아는 것처럼 보이게 하는 핵심 기술입니다. LLM이 가진 추론 능력 위에 검색 기반의 지식 보강 레이어를 붙인 구조입니다

문제는 검색 → 전처리 → 프롬프트 → 후처리 → 메모리 관리 전체가 직접 짜기엔 꽤 복잡하다는 점입니다.
LLM모델이 좋은 응답을 하게 만드는 것에는 크게 Fine Tuning과 RAG가 있습니다. 모델 자체를 튜닝하는 것은 GPU 자원이 기본적으로 많이 필요하기 때문에 비용이 많이 들기도 하고, 이후에 업데이트에 추가적으로 계속 대응하면서 모델을 학습시킨다는 것이 대다수의 기업에는 한계가 있기 때문에 비교적 간편하고 비용이 저렴한 RAG 방식이 자주 사용됩니다. 과거에는 RAG 방식을 사용해 관련 문서의 내용을 추가한 프롬프트가 길어지면 긴 컨텍스트를 인지하지 못하는 문제가 종종 발생했는데, 현대(2025년)의 LLM은 이런 문제가 거의 개선되었기 때문에 RAG 방식이 더 큰 장점을 가지게 되었습니다.
🌏 AI Agent
✅ 역할
AI Agent는 단순히 모델을 호출하는 것이 아니라, 사용자의 요청을 해석하고 적절한 작업 흐름(Flow)을 설계·실행하는 ‘조정자(Orchestrator)’ 역할을 합니다.
어떤 도구(Vector DB, API, 모델 등)를 언제 호출할지 결정하고 흐름을 구성하고 중간 결과를 바탕으로 다음 행동을 선택하고 필요하면 프롬프트를 재구성하고 실패 상황에서는 다른 경로로 우회하거나 재시도하고 전체 컨텍스트를 유지하면서 상태를 관리해야 합니다.
대충 생각해도 좀 복잡한 것 같은데, RAG나 LLM 기능을 직접 만들다보면 다음과 같은 문제가 흔히 발생합니다.
✅ 문제 상황
- 검색, 모델 호출, 문서 파싱, 후처리 모두를 직접 연결해야 함
- 조금만 플로우가 복잡해져도 if-else가 난무하는 문제가 발생함니다
- 상태 저장·컨텍스트 관리가 어려움
- 대화형 시스템일수록 어떤 정보를 기억해야 하는지가 점점 꼬임
- 병렬 처리 / 재시도 / 분기 로직을 안정적으로 작성하기 까다로움
- 외부 API가 실패하면 어디서 다시 처리해야 하는지 직접 구현해야 함
- 파이프라인을 변경할 때마다 전체 코드를 뜯어고쳐야 함
검색 → 요약 → 답변구조에서검색 → 필터링 → 정형화 → 요약 → 답변으로 바꾸고 싶으면 거의 다시 만들다시피 해야 함
✅ 예시를 통한 감정이입(?)
AI Agent를 직접 구성해본 적이 없는 분이라면 위의 상황이 잘 와닿지 않겠는데요
한번 예시를 통해 감정이입(?)해 보겠습니다
우리 회사는 클라이언트 매뉴얼(PDF/문서)을 업로드하면 AI가 고객이 묻는 질문에 자동으로 답변해주는 SaaS를 만들고 있습니다.
첫 버전은 이렇게 단순합니다.
사용자 질문 → 문서 검색 → LLM 호출 → 답변
초기 버전 코드는 대략 이런 느낌입니다.
query = user_input
docs = vector_db.search(query) # 문서내 검색
parsed = parse_docs(docs) # 살짝의 전처리
prompt = make_prompt(query, parsed) # LLM에 날릴 프롬프트 만들기 = 유저가 물어본거 + 정확한 자료
answer = llm(prompt) # llm 호출
cleaned = postprocess(answer) # 살짝의 후처리
return cleaned
여기까지는 괜찮아 보이지만, 클라이언트 요구가 이렇게 오기 시작합니다.
“검색된 문서가 3개 이상이면 요약해서 넣어주세요”
“문서가 없으면 FAQ API를 먼저 호출해주세요”
“답변이 너무 길면 다시 줄여주세요”
“할루시네이션 감지 후 재생성 해주세요”
“특정 키워드는 마스킹해주세요”
그러면 suddenly…
if docs:
if len(docs) > 3:
parsed = summarize(docs)
else:
parsed = parse(docs)
else:
faq = search_faq(query)
if faq:
parsed = faq
else:
parsed = "No data"
이런 지옥의 if-else가 생기기 시작합니다. (아직은 애교일수도,,?)
⇒ 검색, 모델 호출, 문서 파싱, 후처리 모두를 직접 연결해야 함
만약 클라이언트가 “대화형 모드로 만들어주세요”라고 요청하면?
사용자: 로깅 설정 어떻게 하나요?
AI: ~~ 설명 ~~
사용자: 그럼 Spring Boot 기준에서 어떻게 적용하죠?
이때 AI가 이전 질문의 문맥을 자연스럽게 이어가려면 이전 답변, 이전 검색 결과, 대화 히스토리, 요약된 컨텍스트 등을 계속 관리해야 합니다.
이걸 전부 개발자가 직접 저장하고 재조립해야 하는데, 대화가 5~10턴만 넘어가면 컨텍스트가 꼬여버립니다.
⇒ 상태 저장·컨텍스트 관리가 어려움
벡터 DB나 LLM API는 종종 실패합니다. (Timeout, Rate limit, Empty response, 500 오류)
이때 “어디서 다시 호출해야 하는지” 로직을 직접 구현해야 합니다. (= 외부 API 실패 시 흐름 제어를 전부 직접 관리해야 함)
1) 먼저 벡터 DB 검색 시도
- 실패하면 캐시 검색
- 그것도 실패하면 웹 검색
- 결과가 없으면 default 답변
2) LLM 호출 후 응답이 이상하면
- 프롬프트 재구성
- retry(3)
- fallback 모델로 전환
이걸 다 직접 처리하면 비즈니스 로직이 아니라 오류 처리 코드가 60%가 됩니다.
⇒ 병렬 처리 / 재시도 / 분기 로직을 안정적으로 작성하기 까다로움
마지막으로 우리가 처음 만든 구조가 이거였다고 합시다.
검색 → 요약 → 답변
그런데 클라이언트가 이렇게 요청합니다.
“검색 결과가 너무 많아서 답변이 부정확하니 먼저 필터링 → 정형화 → 그걸 요약해서 넣어주세요.”
그러면 파이프라인이 이렇게 변경됩니다.
검색 → 필터링 → 정형화 → 요약 → 답변
초기 설계가 단계 3개를 가정하고 만들어져 있기 때문에 새로운 단계가 끼면 모든 코드의 흐름 제어 부분을 다 수정해야 합니다.
결과적으로 전체 재개발에 가까운 작업이 발생합니다. (근데 실제 운영 환경에서는 파이프라인 수시로 바뀜)
⇒ 파이프라인을 변경할 때마다 전체 코드를 뜯어고쳐야 함

🌏 LangChain
✅ 개념
LangChain은 LLM을 중심으로 한 앱을 쉽게 구성할 수 있도록 만든 모듈식 프레임워크입니다. (RAG나 Agent 기능 만들 때 반복되는 구성 요소들을 표준 라이브러리로 정리해둔 느낌입니다.)
프롬프트 템플릿, 메모리 관리, 벡터스토어, 모델 호출, 체이닝(Chain) 등 LLM 기능을 구성하는 모든 요소를 표준화된 인터페이스로 제공합니다.
LLM 파이프라인을 레고처럼 조립할 수 있게 해줍니다!
최근 LangChain은 Chain보다 LCEL 기반으로 흐름을 구성합니다.
✅ 기능
- 프롬프트 템플릿 관리
- 벡터스토어 연동 및 RAG 구성
- Tool 호출 구조 정의(검색, DB조회 등)
- 에이전트(Agent) 기반 워크플로우 구성
- 대화 메모리 관리(Chat History)
✅ LCEL(LangChain Expression Language)
예전에는 Chain을 상속해서 만들고, 함수 여러 개 연결하는 방식이었지만, 요즘 LangChain은 LCEL이라는 표현식 기반으로 파이프라인을 구성하는 방식을 사용합니다.
파이프라인을 함수 합성하듯 깔끔하게 만들 수 있다는 장점이 있습니다.
chain = retriever | format_docs | prompt | llm
그냥 | 로 연결하면 바로 파이프라인이 됩니다. (매우 편하쥬?)
🌏 LangGraph
✅ 개념

LangGraph는 LangChain의 상위 개념으로, LLM 기반 흐름을 그래프 형태로 정의하는 프레임워크입니다.
기존에는 파이프라인을 직접 코드로 연결했지만, LangGraph는 Node와 Edge로 RAG pipeline을 선언적으로 만듭니다.
LangGraph를 활용하면 여러 에이전트를 포함한 애플리케이션을 만들 수 있습니다.
- Node(노드): 파이프라인 안에서 하나의 단계
- 예: 검색하기, 필터링하기, 프롬프트 만들기, LLM 호출하기
- Edge(엣지): 각 단계를 어떤 순서로 이어줄지를 나타냄
- 예: 검색 → 필터링 → 프롬프트 → LLM 같은 흐름을 연결
즉, LangGraph는 내가 RAG를 어떻게 실행하고 싶은지 연결해두면 그 순서대로 동작하도록 자동으로 제어해주는 구조입니다.
✅ 기능
- 노드(Node) 단위로 기능 정의
- 분기/루프/병렬 등을 그래프 형태로 선언
- 오류 발생 시 재시도/롤백 같은 제어 가능
- 여러 모델/도구/상태를 상태머신처럼 관리
- 여러 턴을 거치는 에이전트 시스템을 안정적으로 구축
LangChain Agent는 단일 턴 위주, LangGraph Agent는 멀티스텝·지속형에 적합합니다.
복잡한 Agent 시스템을 만들 때는 대부분 LangGraph를 사용합니다.
🌏 결론
- LangChain: LLM 기능을 “부품처럼 조립”할 수 있게 해주는 프레임워크
- LangGraph: 그 조립된 기능들이 안정적으로 “흐름대로 실행”되도록 관리해주는 워크플로우 엔진
다음 포스팅에서는 랭체인, 랭그래프를 활용해 RAG 기반 희귀품종 무화과 챗봇을 개선해 보겠습니다

도움이 되었다면, 공감/댓글을 달아주면 깃짱에게 큰 힘이 됩니다!🌟
비밀댓글과 메일을 통해 오는 개인적인 질문은 받지 않고 있습니다. 꼭 공개댓글로 남겨주세요!
'AI > LLM' 카테고리의 다른 글
| [AI/LLM] MCP(Model Context Protocol): LLM이 곧바로 DB에서 최신 데이터도 읽고, 메일도 보내준다고? (2) | 2025.11.21 |
|---|---|
| [AI/LLM] LLM Fine-tuning 완벽 정리: LoRA부터 파인튜닝 vs RAG까지 (0) | 2025.10.21 |
| [AI/LLM] 거대한 LLM에서 가벼운 sLLM으로: LLM 경량화 필요성과 방법 (0) | 2025.10.20 |