국가법령정보 공동활용 API 기반의 법령·행정규칙·판례를 인덱싱하고, hybrid retrieval + multi-chain document review + 안전 배포 파이프라인으로 모델 환각(hallucination)과 도메인 편향을 줄이는 데 집중한 시스템. 백엔드부터 인프라까지 전 영역을 단독으로 설계·구현.
클라이언트 → API 게이트웨이 → RAG 코어 → 저장소·외부 API. 데이터 수집·인덱싱은 운영 트래픽과 분리된 배치 잡으로 운용해, 학습/임베딩이 응답 지연에 영향을 주지 않게 함.
법령·판례는 도메인 어휘가 무겁고 인용·근거가 핵심이라 범용 LLM만으로는 환각·근거 불일치가 잦음. 동시에 신뢰성을 위해 인용 검증 가능한 컨텍스트가 필요.
세 단계 분리:
서비스 분리로 호출 hop이 늘어나 latency가 약간 증가. 대신 각 단계가 독립 캐시·재시도·관측 가능 — 장애 격리와 점진 개선이 쉬워짐.
검색 품질·답변 품질·배포 안전을 각각 따로 측정·개선할 수 있는 구조. 한 영역의 회귀가 다른 영역으로 번지지 않음.
법령 조문 정확도("제N조"는 정규식이 가장 강하다)와 의도 유사도(벡터 검색)를 따로 다루지 않고 하나의 파이프라인에 묶음. 코퍼스 분포 편향 보정까지 마지막 단계로 포함.
(1) 벡터 검색만으로는 "제15조의2" 같은 식별 표현을 못 잡음. (2) lexical-only는 paraphrase에 약함. (3) 인덱스의 대부분이 법령(statute)이라 행정규칙·자율규약이 top-k에서 항상 밀림.
LLM 호출이 retrieval 안에 들어가 비용·지연 증가. 대신 잘못된 청크가 LLM에 흘러들어가 답을 망치는 비용이 훨씬 크다고 판단 — 검색 단계에서 끊는 게 낫다.
소수 코퍼스(행정규칙·자율규약)가 항상 컨텍스트에 포함되어, 다층 규범이 필요한 질문에서 답변 정합성 향상. 식별 표현이 들어간 질문은 exact가 안정적으로 잡아주므로 vector 가중을 무리하게 올리지 않아도 됨.
계약서·약관 검토는 단일 프롬프트 한 번으로 처리하면 길이·관점이 한쪽으로 쏠림. 관점을 분해해 병렬 호출하고, 마지막에 병합·정규화하는 방식으로 빠르고 균형 잡힌 결과를 만든다.
장문 문서에 대한 단일 프롬프트 검토는 (1) 컨텍스트 토큰 한계로 누락이 생기고, (2) "리스크/목적/제도" 중 한 관점만 부각되며, (3) 사용자가 기다리는 동안 응답 지연이 길어짐.
LLM 호출 수가 늘어 비용 증가. 다만 병렬 실행으로 wall-clock은 단일 호출과 비슷하게 유지. 병합 단계 복잡도가 증가하지만, 그 대가로 결과가 사용자 검토 가능한 형태로 일관됨.
검토 누락이 줄어들고, 각 관점이 항상 보장됨. 추가로 다중 파일 검토는 별도 오케스트레이터로 분기해 확장.
RAG 시스템에서 가장 위험한 변경은 인덱스 갱신. 임베딩 모델·청킹 정책·코퍼스 추가가 동시에 일어나면 한 번의 잘못된 배포가 답변 품질을 크게 떨어뜨림. 그래서 롤백 가능한 단계 배포를 인프라 수준에서 강제.
(1) 인덱스 빌드 실패가 운영 트래픽을 멈추면 안 됨. (2) 임베딩이 일부 깨졌어도 200이 떨어지면 알아채기 어려움. (3) 환경변수 변경이 트래픽에 잘못 반영되는 흔한 함정.
배포 단계가 길어져 turnaround가 늘어남. 대신 잘못된 인덱스가 사용자에게 노출되는 사고가 구조적으로 차단됨 — RAG에서는 이 쪽이 비교 불가하게 중요.
인덱스를 자주, 부담 없이 갱신할 수 있게 됨. 새로운 코퍼스 추가나 청킹 정책 실험이 운영 리스크 없이 가능.
RAG는 "검색 + LLM"이라는 단순한 슬로건과 달리, 운영 가능한 검색 품질을 만드는 게 본질이라는 걸 체감. 도메인 특성과 인프라 제약 사이에서 트레이드오프를 결정하는 일이 많았다.
한 가지 검색 방식이 모든 질문 타입을 잘 풀어주지 않는다. 식별 표현·자연어·도메인 어휘는 서로 다른 검색기를 요구한다. 하나의 검색 서비스에 묶되 내부에서 분기하는 게 운영하기 좋다.
코퍼스 분포가 비대칭이면 score-only top-k가 항상 다수 코퍼스를 뽑는다. "코퍼스별 최소 보장" 같은 단순한 후처리가 가장 효과적이었다.
단일 호출의 한계를 피하려면 관점을 분해하고, 마지막에 병합 + 안전망 통합 호출을 둔다. wall-clock은 비슷하면서도 누락이 크게 줄어든다.
코드만 바꾸는 게 아니라 인덱스가 바뀐다. 백업·검증·트래픽 분리가 없으면 한 번의 실수가 답변 품질 회귀로 이어진다. CI/CD를 RAG에 맞게 다시 설계할 필요가 있었다.
인용이 실제 청크에 존재하는지, top-k 분포가 어떤지, 어떤 질문에서 fallback이 발동하는지 —지표를 코드에 박아두는 것이 막연한 "프롬프트 튜닝"보다 빨랐다.
LLM 출력은 매번 미묘하게 다른 모양으로 나온다. 응답 후처리에서 강한 스키마와 폴백을 두는 게, 프롬프트만 다듬는 것보다 안정적인 클라이언트 경험을 만든다.