// post
독서지수 서비스에 RAG를 얹으려면 — FastAPI + LangChain 설계 노트
2026년 8월 4일
독서 활동 기반 서비스에 RAG를 붙이며 FastAPI, LangChain, 데이터 저장 구조를 어떻게 나눴는지 정리한 설계 회고입니다.
RAG를 제품에 붙이는 일은 검색 정확도를 높이는 작업이기도 하지만, 그보다 먼저 "무엇을 근거로 답하게 할 것인가"를 정하는 설계 작업에 가깝다. 독서 활동을 다루는 서비스에서는 사용자가 남긴 기록, 문서 원문, 분석 결과가 서로 다른 성격을 가진다. 이 셋을 한 바구니에 넣으면 검색은 쉬워 보여도, 실제로는 어떤 문장이 어디서 왔는지 추적하기 어려워진다. 그래서 처음부터 데이터의 출처를 분리하고, 질문이 들어왔을 때 어떤 순서로 조합할지 명시적으로 설계하는 데 시간을 많이 썼다.
FastAPI를 선택한 이유는 API 경계를 작게 나누기 쉬웠기 때문이다. 업로드, 전처리, 임베딩 생성, 질의, 결과 저장을 각각 분리하니 실패 지점을 찾기 쉬워졌고, 이후 일부 단계만 다시 돌리는 것도 편해졌다. LangChain은 빠르게 실험할 수 있다는 장점이 있었지만, 체인이 길어질수록 내부 동작이 가려질 수 있어 각 단계의 입력과 출력 로그를 남기는 쪽으로 사용했다. 중요한 것은 프레임워크가 아니라, 검색 결과가 왜 선택됐는지 사람도 설명할 수 있는 구조였다.
저장소 설계도 의외로 중요했다. 원문 텍스트, 조각으로 나눈 문단, 임베딩 메타데이터, 사용자 세션 결과를 분리해 두니 프롬프트를 수정해도 다시 써야 하는 범위를 줄일 수 있었다. 프론트엔드에서는 답변 하나만 보여주는 대신, 참고한 문서 단서와 질문 히스토리를 함께 보여주는 방식이 더 신뢰를 줬다. 결국 RAG 품질은 모델 한 번 호출로 결정되지 않고, 검색과 저장, 추적, 화면 설명이 한 세트로 맞물릴 때 비로소 좋아진다.
이번 작업에서 가장 크게 배운 점은 AI 기능도 결국 운영 가능한 소프트웨어여야 한다는 사실이다. 데모 단계에서는 화려한 답변이 눈에 띄지만, 실제 서비스에서는 실패했을 때 어떻게 다시 시도하고, 근거를 어떻게 보여주며, 비용과 응답 속도를 어떻게 통제할지가 더 중요하다. 다음에 비슷한 구조를 만든다면 체인 자체보다 평가 로그와 회귀 케이스를 더 일찍 준비할 생각이다.