이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
- LangChain과 LlamaIndex 같은 framework에서 백엔드 개발자가 배울 실전 패턴은 무엇인가?
- framework 추상화를 어디까지 믿고 어디부터 직접 경계를 잡아야 하는가?
- framework를 도입할 때 버전 변화와 lock-in을 어떻게 다루는가?
개요
2026-06-30 GitHub API로 확인한 기준에서 langchain-ai/langchain은 140k+ stars, run-llama/llama_index는 50k+ stars이고 둘 다 당일 업데이트가 있는 활발한 프로젝트다. 이 정도 생태계는 학습 가치가 크다.
다만 목표는 사용법을 외우는 것이 아니다. 백엔드 개발자가 framework에서 배울 것은 “LLM 앱을 어떤 관심사로 나누는가”다.
배울 패턴
LLM app framework는 보통 다음 관심사를 분리한다.
- model client
- prompt template
- output parser
- retriever
- document loader
- memory
- tool
- agent/workflow
- callback/tracing
- evaluation
이 분리는 백엔드 설계에도 그대로 유용하다. 다만 framework 객체를 API 계층까지 끌고 올라오면 애플리케이션 경계가 흐려진다.
백엔드 적용 기준
좋은 적용 방식:
- framework를 adapter 내부에 둔다.
- 도메인 서비스는 내부 DTO와 포트에 의존한다.
- prompt version과 model profile은 별도 관리한다.
- trace id를 framework callback과 연결한다.
- 핵심 chain은 integration test를 둔다.
나쁜 적용 방식:
- Controller에서 framework chain을 바로 실행한다.
- framework exception을 API 응답에 그대로 노출한다.
- prompt와 retriever 설정이 코드 곳곳에 흩어진다.
- token usage와 retrieval source를 기록하지 않는다.
코드로 이해하기
framework 사용부를 adapter로 숨기는 구조다.
class RagAnswerPort:
def answer(self, *, question: str, tenant_id: str) -> dict:
raise NotImplementedError
class LlamaIndexRagAdapter(RagAnswerPort):
def __init__(self, query_engine, usage_recorder):
self.query_engine = query_engine
self.usage_recorder = usage_recorder
def answer(self, *, question: str, tenant_id: str) -> dict:
response = self.query_engine.query(question)
source_ids = [
node.metadata["source_id"]
for node in response.source_nodes
]
self.usage_recorder.record(
feature="document_qa",
tenant_id=tenant_id,
source_ids=source_ids,
)
return {
"answer": str(response),
"source_ids": source_ids,
}프레임워크는 내부 구현이다. API 응답은 내부 계약으로 반환한다.
실전 팁
- framework 문서의 quickstart는 운영 기준이 아니다.
- framework callback을 내부 trace와 연결한다.
- framework 버전 업데이트는 retriever, parser, agent behavior를 바꿀 수 있으므로 eval을 돌린다.
- lock-in을 완전히 피하려 하기보다 핵심 경계만 포트로 감싼다.
위험 신호!
- framework 객체가 Controller 응답으로 직접 노출된다.
- chain 내부에서 어떤 prompt가 쓰이는지 모른다.
- retrieval source를 추적하지 않는다.
- framework upgrade 후 eval을 돌리지 않는다.
확인 질문
확인 질문
- LLM app framework를 백엔드에 도입할 때 가장 중요한 경계는 무엇인가?
- framework를 adapter 뒤에 두고 서비스 계층은 내부 계약에 의존하게 하는 것이다.
- framework 추상화가 디버깅을 어렵게 만드는 이유는 무엇인가?
- prompt, retrieval, tool, model 호출 흐름이 한 체인 안에 숨어 실패 원인을 보기 어려울 수 있기 때문이다.