Projects로 돌아가기

PROJECT CASE STUDY

02

로디 복지 상담 에이전트 · RAG 2 · 사람이 만들던 RAG를 Agent와 함께 만들기

Agent가 법령 문서의 chunk와 관계 후보를 만들고, 사람이 승인한 판단을 memory로 돌려보내는 RAG construction pipeline을 구축했습니다.

복지 상담 안내 캐릭터 로디RODY WELFARE AGENT · RAG 01로디 복지 상담 에이전트 · RAG 1법령 근거와 유사 사례를 함께 사용하고 RAG를 독립 서비스로 분리한 이유부터 읽기

구축은 누가 하는가

이 고민을 시작할 무렵에는 Obsidian을 MCP나 graph database에 연결하고, 문서를 넣을 때마다 node가 생기는 장면을 보여주는 Agentic RAG 데모가 주목받고 있었습니다. 개인의 note를 graph로 바꾸는 시각적 경험은 인상적이었지만, 실제 조직의 문서를 운영 가능한 RAG로 만드는 일은 여전히 별개의 구축 프로젝트처럼 다뤄지고 있었습니다.

AI Expo에서 여러 database·RAG solution 팀에 “문서를 올리면 지식 기반으로 만들어주는 SaaS 형태가 있습니까?”라고 물었을 때 돌아온 답은 먼저 문서 규모를 보고 견적을 산정해야 한다는 것이었습니다. 문서 수와 형태를 확인하고, 사람이 정제하고 chunking·embedding·연결 작업을 해야 비용과 기간을 계산할 수 있다는 의미로 받아들였습니다.

그 설명이 틀렸다고 생각하지는 않았습니다. 조직의 데이터는 같은 개념을 서로 다른 이름으로 부르거나, 문서마다 구조와 품질이 다르고, 관계를 판단할 ontology조차 없는 경우가 많습니다. 다만 법률과 조례처럼 문서의 위계와 연결 기준이 비교적 명확한 영역이라면, construction work의 더 많은 부분을 Agent에게 위임할 수 있지 않을까라는 질문이 남았습니다.

관계가 지식이 되는 순간

당시 제가 떠올린 연구자는 중앙대학교 문헌정보학과의 김학래 교수였습니다. 김학래 교수는 온톨로지와 지식그래프를 통해 흩어진 데이터를 색인하고 연결해 AI가 맥락을 읽을 수 있는 지식으로 바꾸는 문제를 연구해 왔습니다. 관련 인터뷰에서도 온톨로지와 지식그래프를 Agentic AI를 실제 조직에 적용하기 위한 기반으로 설명합니다.

이 관점에서 보면 RAG construction의 비용은 embedding API 비용만으로 설명되지 않습니다. 문서의 개념과 관계를 어떻게 통일할지, 어떤 연결을 graph fact로 인정할지, 이후 들어오는 문서를 같은 policy로 처리할지를 정하는 일이 함께 필요합니다.

저희가 자동화하려고 한 것도 이 판단을 없애는 일이 아니었습니다. Agent가 반복적인 문서 분석과 관계 후보 생성을 맡고, 사람은 후보가 실제로 맞는지 approve 또는 deny하며, 그 판단 기록이 다음 construction에 다시 사용되는 framework를 만드는 일이었습니다.

반복은 Agent에게

문서를 업로드하면 먼저 Chunking Agent가 원문을 의미 단위로 나눕니다. 만들어진 chunk마다 worker가 기존 graph와 관련 문서를 탐색하고, 연결할 수 있는 node와 relationship candidate를 제안합니다. Agent가 저장하는 것은 확정된 관계가 아니라 사람이 검토할 후보입니다.

검토자는 후보의 원문 근거와 rationale을 보고 approve 또는 deny합니다. 두 결정에는 note를 남길 수 있고, review log와 note는 graph에 저장됩니다. 다음 construction run에서는 이 기록을 memory context로 제공해 과거에 어떤 관계를 승인했고 어떤 기준으로 거절했는지를 참고하도록 했습니다.

Write access도 모든 Agent에게 열지 않았습니다. read_document_tool, write_chunk_tool, write_relationship_candidate_tool과 edge materialization은 RAG 내부 construction surface에만 둡니다. 사용자와 대화하는 Main Agent에는 외부 MCP의 read-only 도구만 제공합니다.

문서에서 지식까지

자동화하려는 대상은 단순한 파일 업로드가 아니었습니다. 원문을 추적할 수 있는 문서로 등록하고, 의미 단위의 chunk를 만들고, embedding을 저장하고, 기존 법령 graph와 연결할 관계 후보를 제안하는 과정까지 하나의 construction flow로 묶었습니다.

다만 LLM이 제안한 관계를 자동으로 사실로 확정하지는 않았습니다. 문서 처리 과정은 자동화하되, 법령 사이의 의미 관계가 실제 graph edge가 되는 마지막 결정에는 사람의 검토를 남겼습니다.

DOCUMENT CONSTRUCTION FLOW

public text document
  → deterministic document registration
  → source-faithful chunking agent
  → embedding dispatch and storage
  → graph relationship candidate agent
  → pending human review
  → approved edge materialization
  → read-only MCP tools
등록한 문서와 ingestion 상태, chunk 및 관계 후보 수를 보여주는 Documents 화면
등록된 문서마다 construction stage, 생성된 chunk와 검토할 relationship candidate 수를 함께 확인합니다.원본 크기로 보기

원문을 고정하다

문서 등록은 Agent에게 맡기지 않았습니다. DocumentRegistry가 파일 형식을 확인하고, 정규화한 원문의 SHA-256 content_hash와 원문 전체, 파일명과 source metadata를 저장합니다. 이후 단계는 이때 만들어진 document_id를 기준으로 같은 문서를 읽습니다.

이 경계를 둔 이유는 provenance 때문입니다. Chunk와 관계 후보가 그럴듯하더라도 어느 원문에서 만들어졌는지 다시 확인할 수 없다면 법령 근거로 사용하기 어렵습니다. 생성 모델이 내용을 해석하기 전에 문서 identity와 원문을 먼저 고정했습니다.

요약보다 추적 가능성

LLM이 문서를 매끄럽게 요약하면 검색용 문장처럼 보일 수 있지만, 조건과 예외가 사라지거나 원문의 위치를 다시 찾기 어려워질 수 있습니다. 법령 데이터에서는 읽기 좋은 요약보다 근거를 되짚을 수 있는 chunk가 더 중요했습니다.

ChunkingAgent는 문서의 의미 경계를 판단하지만 chunk 본문은 원문에서 그대로 복사하도록 제한했습니다. 각 chunk에는 start_unique_stringend_unique_string을 두고, 해당 문자열이 원문에 정확히 한 번 등장하는지 도구로 확인합니다. Marker가 중복되면 범위를 넓혀 다시 검사합니다.

Chunk의 본문과 함께 사람이 빠르게 확인할 수 있는 이름, 설명, tag, summary와 경계 선택 이유도 저장합니다. 생성된 chunk는 write_chunk_tool을 통해 원본 Document와 연결됩니다.

검색하고, 연결하다

Embedding은 기존 Chunk node에 저장합니다

EmbeddingDispatchNodeService는 chunk text로 embedding을 만들고 기존 Chunk node에 vector와 embedding model을 기록합니다. 일부 chunk가 실패하면 같은 graph node 안에서 누락된 chunk를 한 번 더 시도하며, 모든 upstream chunk의 embedding이 확인되기 전에는 관계 후보 생성 단계로 넘어가지 않습니다.

Agent는 확정 관계가 아니라 검토 후보를 만듭니다

GraphCandidateAgent는 각 chunk의 text와 현재 Memgraph의 schema·주변 관계를 읽고, 법령과 조례, 시행 규정 사이에 연결할 수 있는 relationship candidate를 제안합니다. Candidate에는 양쪽 node, 관계 방향과 유형, evidence text와 rationale을 남깁니다.

외부 웹 검색은 관계 판단에 필요한 배경을 보강할 수 있지만, 검색 결과만으로 graph node나 edge를 만들 수는 없습니다. Candidate의 endpoint는 Memgraph에서 실제로 확인한 node여야 하고, 근거는 현재 chunk와 연결되어야 합니다.

문서별 Staged, Chunked, Graph built, Review 단계를 보여주는 Graph Jobs 화면
Graph Jobs에서는 각 문서가 Staged, Chunked, Graph built, Review 가운데 어느 단계에 있는지 추적합니다.원본 크기로 보기
선택한 문서 job의 실행 stream과 graph step을 보여주는 Diagnostics Studio 화면
개별 job을 열면 Agent 실행 stream과 queue 상태, 완료된 graph step을 같은 진단 화면에서 확인할 수 있습니다.원본 크기로 보기

승인 전에는 사실이 아니다

LLM이 높은 confidence를 반환하더라도 잘못된 법령 위계나 적용 범위가 graph에 고정될 수 있습니다. 그래서 DocumentConstructionGraph는 관계 후보를 만든 뒤 pending_review 상태에서 종료합니다.

검토자는 후보의 evidence와 rationale을 읽고 yes 또는 no를 선택합니다. 승인된 후보만 ActualEdgeMaterializationNodeService를 거쳐 실제 semantic edge가 됩니다. 거절된 후보는 상태와 reviewer note를 남기며, review 기록은 이후 판단 기준을 정리하는 memory update에 사용됩니다.

사람의 응답을 기다리는 동안 하나의 LangGraph 실행을 계속 유지하지도 않습니다. 문서 construction과 candidate review를 서로 다른 graph execution으로 분리해 pending 상태를 저장하고, 검토 action이 들어왔을 때 별도 review graph를 실행합니다.

문서별 pending relationship candidate를 묶어 보여주는 Review Queue 화면
Review Queue는 문서별 relationship candidate를 하나의 검토 작업으로 묶고 pending·finished 상태를 분리합니다.원본 크기로 보기
Source와 target chunk, 관계 추출 근거와 reviewer note를 함께 검토하는 candidate review 화면
Candidate를 열면 양쪽 chunk와 LLM의 관계 추출 근거를 비교하고, reviewer note를 남긴 뒤 관계를 승인하거나 거절할 수 있습니다.원본 크기로 보기

구축 비용을 다시 계산하다

내부 비교에서는 데이터 수집과 문서 확인을 담당하던 작업자에게 같은 종류의 RAG construction을 수작업으로 진행해 달라고 요청했습니다. 당시 들은 작업량은 약 4~5시간에 문서 3~4개였고, 비교 기준으로는 대략 문서 하나에 한 시간 정도가 필요했습니다.

같은 범주의 비교 문서를 Agent-assisted pipeline으로 처리했을 때는 문서 하나가 약 10분 이내에 candidate review 단계까지 도달했습니다. OpenRouter에 기록된 실제 사용 비용과 당시 최저시급을 기준으로 문서당 비용을 비교하면, 사람의 검토 시간을 포함하더라도 약 10분의 1 수준까지 줄어드는 구간을 확인했습니다.

비교 항목수작업Agent-assisted construction
처리 시간약 4~5시간에 문서 3~4개비교 문서 기준 문서당 약 10분 이내
비용 기준작업 시간에 당시 최저시급을 적용OpenRouter 사용액과 사람의 review 시간을 합산
문서당 비용약 한 시간의 인건비내부 비교 구간에서 약 10분의 1 수준
품질 확인사람이 chunk와 관계를 직접 구성Chunk와 후보를 Agent가 만들고 사람이 approve/deny

Chunk 단위의 품질과 승인된 connection에서는 눈에 띄는 차이를 발견하지 못했습니다. Agent 결과를 그대로 확정한 것이 아니라 사람이 같은 기준으로 후보를 검토했기 때문에, 반복 작업의 속도를 줄이면서 최종 판단 layer는 유지할 수 있었습니다.

읽기 전용 경계

RAG 내부의 construction Agent는 chunk와 relationship candidate를 쓰는 도구가 필요합니다. 하지만 사용자와 대화하는 Main Agent가 문서나 graph 관계를 수정할 이유는 없습니다. 그래서 외부 MCP surface에는 다음 read-only 도구만 등록했습니다.

RAG MCP PUBLIC TOOLS

memgraph.text_index_search
memgraph.vector_search
memgraph.graph_traverse
memgraph.read_query
memgraph.schema_read
도구Main Agent에 제공하는 기능제한
memgraph.text_index_search법령명, 정책명, 지역, 기관과 문서 제목으로 anchor node를 찾습니다.결과 수를 제한하며 index가 없으면 bounded property scan으로 fallback합니다.
memgraph.vector_search이미 숫자 embedding vector가 있을 때 vector index에서 가까운 node를 찾습니다.자연어 질문을 embedding으로 바꾸는 도구가 아니며 numeric vector가 없는 호출에는 사용하지 않습니다.
memgraph.graph_traverse찾은 node 주변의 chunk, document와 relationship을 multi-hop으로 확인합니다.max depth와 row 수를 제한해 전체 graph가 context로 확장되지 않게 합니다.
memgraph.read_query근거와 source field를 반환하는 read-only Cypher를 실행합니다.CREATE, MERGE, SET, DELETE를 포함한 write operation과 write procedure를 거부합니다.
memgraph.schema_read사용 가능한 label, relationship type, property와 index를 확인합니다.schema를 읽기만 하며 변경하지 않습니다.

도구 결과는 embedding vector와 지나치게 긴 text를 그대로 노출하지 않도록 sanitize합니다. Main Agent는 필요한 근거를 읽을 수 있지만 graph를 만드는 규칙과 승인 결과를 바꿀 수 없습니다.

만드는 권한, 쓰는 권한

구분Construction 내부Main Agent 외부
목적문서에서 검색 가능한 지식을 만듭니다.사용자 질문에 필요한 근거를 찾습니다.
읽기원문, chunk context, graph schema와 주변 관계를 읽습니다.공개된 text/vector search, traversal, schema와 read query를 사용합니다.
쓰기Chunk와 relationship candidate를 저장하고 승인된 edge를 materialize합니다.쓰기 권한을 제공하지 않습니다.
판단LLM이 chunk 경계와 관계 후보를 제안하고 사람이 edge를 승인합니다.저장된 지식을 조회할 뿐 construction 결과를 변경하지 않습니다.

이 권한 분리는 RAG를 독립 서비스로 만든 이유와 직접 연결됩니다. 내부 구현을 감추기 위한 분리가 아니라, 자동으로 지식을 구축하는 surface와 제품이 그 지식을 소비하는 surface를 서로 다른 계약으로 운영하기 위한 분리였습니다.

자동화 뒤의 검토

현재 pipeline은 text 계열 입력을 중심으로 동작합니다. PDF, OCR과 VLM을 거쳐야 하는 문서는 별도의 전처리 layer가 필요합니다. 신규 문서의 등록과 construction은 구현되어 있지만, 같은 source의 변경을 자동 감지해 version을 증가시키는 re-ingest와 원본 polling도 다음 운영 범위로 남아 있습니다.

관계 후보 생성은 LLM과 외부 provider에 의존하므로 latency, quota와 부분 실패가 발생할 수 있습니다. Chunk별 candidate generation은 가능한 결과를 보존하지만, 후보가 만들어졌다는 사실만으로 graph 품질이 보장되지는 않습니다. 사람이 검토한 edge와 원문 provenance를 유지하는 이유가 여기에 있습니다.

이 작업은 다섯 명이 함께 만든 팀 프로젝트입니다. 저는 팀장으로 전체 일정과 작업 방향을 정리하고, RAG service와 Main Agent 사이의 경계 및 파트 간 통합 흐름을 확인했습니다. RAG의 세부 데이터 구축과 구현 기여는 팀원별 책임을 구분해 소개합니다.

복지 상담 안내 캐릭터 로디RODY WELFARE AGENT · INTERFACE로디 복지 상담 에이전트 · 상담 인터페이스RAG와 외부 도구에서 찾은 근거를 상담 화면, 기관 지도, 체크리스트와 음성으로 연결한 다음 글