AI 문서 어시스턴트를 위한 RAG 대체 가상 파일시스템 구축
(mintlify.com)- 기존 RAG 기반 검색의 한계를 극복하기 위해, 문서를 파일과 디렉터리로 구성한 가상 파일시스템 구조로 전환
- 실제 파일 복제 없이 Chroma 데이터베이스를 기반으로
grep,cat,ls,find명령을 수행할 수 있는 ChromaFs를 구현 - 이 방식으로 세션 생성 시간이 46초에서 100밀리초로 단축, 추가 연산 비용은 0달러 수준으로 감소
- 접근 제어는 파일 경로 메타데이터의 RBAC 필터링으로 처리되어, 별도 컨테이너나 사용자 그룹 관리가 불필요
- 결과적으로 Mintlify 문서 어시스턴트는 즉시 응답, 저비용, 무상태 구조를 갖춘 대규모 서비스로 운영 가능
RAG의 한계를 넘어선 가상 파일시스템 접근
- 기존 RAG 기반 문서 검색은 쿼리와 일치하는 텍스트 조각만 반환해, 여러 페이지에 걸친 답변이나 정확한 구문 검색이 어려웠음
- 이를 해결하기 위해 문서 구조를 파일시스템처럼 탐색 가능한 형태로 전환, 각 문서 페이지를 파일로, 섹션을 디렉터리로 매핑함
- 에이전트는
grep,cat,ls,find명령을 통해 문서를 직접 탐색할 수 있어, 개발자가 코드베이스를 다루듯 문서를 검색할 수 있는 구조로 설계됨
컨테이너 병목 문제
- 일반적인 접근은 에이전트에 실제 파일시스템을 제공하기 위해 격리된 샌드박스 환경을 생성하고 저장소를 복제하는 방식
- 그러나 프런트엔드 어시스턴트에서는 세션 생성 지연이 심각하게 나타나며, p90 세션 생성 시간은 약 46초에 달함
- 월 85만 회 대화 기준, 최소 구성(1 vCPU, 2GiB RAM, 5분 세션 유지)에서도 연간 7만 달러 이상 인프라 비용이 발생
- 이러한 병목을 제거하기 위해 즉시 반응하고 저비용으로 동작하는 가상 파일시스템이 필요했음
가상 셸 구현 — ChromaFs
- 실제 파일시스템 대신 가상의 파일시스템 환상(illusion) 만 제공
- 기존 문서 데이터는 이미 Chroma 데이터베이스에 색인되어 있었기 때문에, 이를 기반으로 ChromaFs를 구축
- ChromaFs는 UNIX 명령을 가로채어 Chroma 쿼리로 변환함
- 결과적으로 세션 생성 시간이 46초에서 100밀리초로 단축, 추가 연산 비용은 0달러 수준으로 감소
| Metric | Sandbox | ChromaFs |
|---|---|---|
| P90 Boot Time | ~46초 | ~100ms |
| Marginal Compute Cost | ~$0.0137/대화 | ~$0 |
| Search Mechanism | 디스크 스캔 | DB 메타데이터 쿼리 |
| Infrastructure | Daytona 등 외부 샌드박스 | 기존 DB 재활용 |
-
just-bash (Vercel Labs) 기반으로 구현되어,
grep,cat,ls,find,cd명령을 지원 - just-bash의
IFileSystem인터페이스를 활용해, 파이프 처리 및 플래그 로직은 그대로 유지하면서 파일 접근 호출을 Chroma 쿼리로 변환
디렉터리 트리 부트스트래핑
- ChromaFs는 실행 전 어떤 파일이 존재하는지 알아야 하므로, 전체 파일 트리를 압축된 JSON(
__path_tree__) 형태로 Chroma 컬렉션에 저장 - 서버 초기화 시 이를 가져와 두 가지 메모리 구조로 복원
- 파일 경로의
Set<string> - 디렉터리별 자식 목록의
Map<string, string[]>
- 파일 경로의
- 이후
ls,cd,find명령은 네트워크 호출 없이 로컬 메모리에서 즉시 처리, 동일 사이트의 후속 세션은 캐시된 트리를 재사용
접근 제어
- 경로 트리에는
isPublic및groups필드가 포함되어 있으며, 사용자 세션 토큰을 기준으로 접근 가능한 파일만 남김 - 접근 권한이 없는 파일은 트리에서 완전히 제거되어, 에이전트가 해당 경로를 인식하지 못함
- 기존 샌드박스에서는 이를 위해 리눅스 사용자 그룹,
chmod, 컨테이너 분리 등을 관리해야 했으나, ChromaFs에서는 간단한 필터링 로직만으로 RBAC 구현
| Path | Access | Visible |
|---|---|---|
| /auth/oauth.mdx | public | ✓ |
| /auth/api-keys.mdx | public | ✓ |
| /internal/billing.mdx | admin, billing | ✗ |
| /api-reference/users.mdx | public | ✓ |
| /api-reference/payments.mdx | billing | ✗ |
문서 조각 재조립
- Chroma에 저장된 문서는 임베딩을 위해 여러 조각으로 분할되어 있음
-
cat /auth/oauth.mdx실행 시, 동일한page슬러그를 가진 모든 조각을 가져와chunk_index순서로 정렬 후 병합 - 결과는 캐시되어, 반복된
grep워크플로에서도 DB 재조회가 발생하지 않음 - 대형 OpenAPI 스펙 등은 지연 로딩 포인터(lazy file pointer) 로 등록되어, 접근 시에만 S3에서 가져옴
- 모든 쓰기 연산은
EROFS(읽기 전용 파일시스템) 오류를 반환해, 세션 상태가 없는(stateless) 안전한 구조 유지
Grep 최적화
-
grep -r명령은 단순 네트워크 스캔 시 매우 느리므로, 두 단계 필터링 구조로 최적화- 1단계: Chroma 쿼리(
$contains,$regex)를 이용해 후보 파일을 선별 - 2단계: Redis 캐시에 미리 가져온 후,
just-bash에서 메모리 내 정밀 필터링 수행
- 1단계: Chroma 쿼리(
- 이를 통해 대규모 재귀 검색도 밀리초 단위로 완료 가능
결론
- ChromaFs는 하루 3만 건 이상, 수십만 명의 사용자가 이용하는 Mintlify 문서 어시스턴트를 구동
- 샌드박스를 대체함으로써 즉시 세션 생성, 0에 가까운 추가 비용, 내장 RBAC, 무상태 구조를 달성
- Mintlify의 모든 문서 사이트에서 직접 사용 가능 (mintlify.com/docs)
Hacker News 의견들
-
파일 시스템 기반 검색을 다시 주목하는 이유는 임베딩 기반이 아닌 의미 검색의 형태를 재발견하고 있기 때문임
도서관 사서가 주제별로 책을 선반에 정리하듯, 파일을 도메인별로 구성하는 방식이 더 해석 가능함
오래전부터 존재하던 검색 방식이지만, 이제야 다시 그 가치를 깨닫고 있음
관련 블로그 글- 전통적인 도서관학이 정보 구조의 깊은 패턴을 이미 포착했음
Pixar의 Ralph Wrecks The Internet에서도 이 개념을 잘 표현했음
참고 트윗1, 참고 트윗2 - 400개 이상의 Python 파일이 있는 코드베이스에서 작업 중인데, 임베딩 기반 RAG는 단어가 비슷한 엉뚱한 코드 조각을 자주 가져왔음
대신 에이전트가 디렉터리 트리를 직접 탐색하도록 하니 30초 만에 모듈 구조를 이해하고 정확한 파일을 요청하기 시작했음
디렉터리 계층 자체가 이미 사람이 만든 지식 그래프였음을 잊고 있었음 - LLM 검색 시스템을 만들다 보니 결국 역색인(concordance) 을 다시 발명하게 되었음
이는 Google의 inverted index와 동일한 개념으로, 사실 완전히 새로운 것은 아님 - 누군가 RAG는 반드시 벡터 검색을 써야 한다고 가정했고, 모두가 그 흐름을 따라간 것 같음
- AI 어시스턴트는 결국 LLM이 자동완성하는 가상의 등장인물이므로, 인간의 언어적 상호작용처럼 해석 가능한 메커니즘이 더 유리함
- 전통적인 도서관학이 정보 구조의 깊은 패턴을 이미 포착했음
-
RAG가 나에게는 직접 내용을 읽을 방법을 주지 않았음
그래서 이제는 Markdown 기반 정적 페이지로 지식을 통합하고, 수정 후 JSON 파일을 빌드해 에이전트가 이 소스를 질의하도록 함
설명 링크 -
파일 시스템 검색이 RAG보다 낫다는 주장은 혼란스러움
grep 같은 키워드 검색은 오래된 방식이고, RAG는 벡터 검색을 사용함
하지만 데이터베이스에서는 콘텐츠를 계층, 태그, 임의의 구조로 인덱싱할 수 있음
검색은 키워드, 벡터, tf-idf, BM25 등 다양한 조합이 가능함
파일 시스템으로 돌아가는 건 60년대 수준의 기술로 회귀하는 느낌임- 맞는 말이지만, 실제로 에이전트가 파일 기반으로 작업할 때 성능이 더 좋음
CLI 기반 코딩 에이전트는 파일 접근 시 훨씬 똑똑하게 행동함 - 나는 데이터베이스 기반의 agentic search로 좋은 결과를 얻었음
핵심은 에이전트가 다양한 ad-hoc 쿼리를 직접 실행할 수 있다는 점임
임베딩과 전체 텍스트 검색을 모두 지원하는 DB에서 에이전트가 자유롭게 질의하면 충분히 agentic함 - 사실 대부분의 파일 시스템도 내부적으로는 데이터베이스 구조를 사용함
파일 시스템을 DB처럼 쓰는 건 새로울 게 없음 - 기사에서 말한 접근법이 결국 이거 아닌가 싶음
- 여러 데이터 소스에서 에이전트가 직접 탐색하도록 하는 게 더 낫다고 생각함
- 맞는 말이지만, 실제로 에이전트가 파일 기반으로 작업할 때 성능이 더 좋음
-
월 85만 건의 대화로 연간 7만 달러 이상이 든다는 계산이 이상하게 들림
CPU와 메모리를 어디에 그렇게 쓰는지 궁금했는데, Vercel Labs의 just-bash 기반 ChromaFs 때문이었음- 각 에이전트에 격리된 컨테이너를 주면, 아무 일도 안 해도 메모리가 계속 점유되어 비용이 커짐
-
CLI 애플리케이션의 부흥기를 즐기고 있음
FUSE로 Mac의 실제 파일 시스템을 미러링하는 가상 파일 시스템을 만들어, 에이전트를 해당 트리 안에만 제한함
각 리포마다 장기 실행 에이전트를 두고, 권한은 가상 파일 시스템으로 제어함
프로젝트 bashguard -
우리는 가상 파일 시스템(VFS) 과 RAG를 모두 사용함
RAG의 핵심은 데이터 품질로, 문서를 의미 단위로 나누고 메타데이터와 링크를 생성함
voyage contextual embedding으로 각 청크를 문서와 함께 임베딩함
검색 시 에이전트는 링크를 따라가거나 원문을 분석할 수 있음
reranking 품질이 성능에 큰 영향을 줌- 우리의 VFS는 Postgres 기반이며, 파일/디렉터리 형태로 투영됨
grep, bm25, jq, 미리보기 도구 등을 지원하고, Pydantic AI 위에서 동작함
- 우리의 VFS는 Postgres 기반이며, 파일/디렉터리 형태로 투영됨
-
POSIX 셸을 TypeScript로 에뮬레이션해 계층 검색을 하는 건 과도한 설계처럼 보임
매번 ls나 grep을 실행할 때마다 추론 사이클이 늘어나 지연(latency) 이 커짐- 청크 위에 FUSE를 올리는 방식이면 셸 에뮬레이션이 필요 없을 것 같음
-
기술 스택은 잘 모르지만, 왜 굳이 가짜 셸을 만들었는지 궁금했음
FUSE 솔루션이 더 자연스러워 보임- 실제로 FUSE 어댑터를 고려했지만 속도가 너무 느림
POSIX 완전 호환이 필요 없었고, 읽기 전용 문서 탐색만 하면 되었음
따라서 bash 명령 일부만 지원하는 방식이 더 간단했음
- 실제로 FUSE 어댑터를 고려했지만 속도가 너무 느림
-
문서를 파일 시스템 도구로 접근 가능하게 만드는 맥락에서, Vercel의 AI SDK가 흥미로움
npm 패키지 루트에 .mdx 문서를 포함해, 에이전트가 먼저 로컬 문서에서 grep하도록 유도함
SKILL.md 예시 -
Mintlify 같은 스타트업에는 좋은 접근이지만, 복잡한 조직에서는 실용성이 떨어질 수 있음
구조가 비계층적이거나 문서가 뒤섞인 환경에서는 RAG가 더 유용함- 여기서는 코드 검색이라는 명확한 유즈케이스가 있으므로 단순함
RAG는 만능이 아니며, Claude 코드 팀도 같은 결론에 도달했음 - OCR 기술이 충분히 발전했기 때문에, 문서가 OCR 가능하다면 이 접근법도 일반화 가능함
- 복잡한 문서 조직 위에 VFS를 덧씌우면 결국 인덱서의 변형일 뿐이며, 접근 제어가 없으면 보안 문제가 생김
- 여기서는 코드 검색이라는 명확한 유즈케이스가 있으므로 단순함