가상 파일시스템으로 AI 어시스턴트 비용·속도 최적화하기
RAG(검색 증강 생성) 기반 AI 어시스턴트는 분명 강력하지만, 문서 탐색에서는 뚜렷한 한계를 보여요. 쿼리와 유사한 텍스트 청크만 반환하는 방식은 답변이 여러 페이지에 걸쳐 있거나 정확한 구문 매칭이 필요한 경우 제대로 작동하지 않아요. Mintlify 팀은 에이전트가 코드베이스를 탐색하듯 문서를 직접 탐색할 수 있는 구조가 필요하다고 판단했어요. 그 결과물이 바로 가상 파일시스템(Virtual Filesystem) — ChromaFs예요. 이 글에서는 ChromaFs의 설계 배경, 핵심 구조, 그리고 성능·비용 트레이드오프를 개발자 시각에서 깊이 있게 살펴볼게요.
실제 샌드박스가 실패하는 이유
에이전트에게 실제 파일시스템을 주는 건 직관적인 해결책이에요. 격리된 샌드박스를 스핀업하고 저장소를 클론하면 되니까요. Mintlify도 비동기 백그라운드 에이전트에는 실제로 이 방식을 사용해요. 그런데 사용자가 로딩 스피너를 바라보는 프론트엔드 어시스턴트 시나리오에서는 이야기가 완전히 달라져요.
레이턴시 문제
GitHub 클론을 포함한 세션 생성의 p90 레이턴시가 약 46초에 달했어요. 사용자 입장에서 46초는 곧장 이탈로 이어지는 숫자예요. 아무리 답변 품질이 좋아도, 기다림 자체가 UX를 망가뜨려요.
비용 문제
정적 문서 읽기를 위해 전용 마이크로-VM을 띄우는 건 인프라 비용이 상당해요. Daytona의 퍼-세컨드 샌드박스 가격(vCPU당 $0.0504/h, GiB RAM당 $0.0162/h)을 기준으로, 월 850,000건의 대화에 최소 설정(1 vCPU, 2 GiB RAM, 5분 세션)을 적용하면 연간 $70,000 이상이 나와요. 세션 시간이 늘어나면 이 수치는 두 배로 뛰죠.
| 항목 | 실제 샌드박스 | ChromaFs |
|---|---|---|
| 세션 생성 시간 | ~46초 | ~수백 ms |
| 대화당 추가 비용 | ~$0.0137 | ~$0 |
| 인프라 | 신규 VM 필요 | 기존 DB 재사용 |
핵심 인사이트는 이거예요. 에이전트는 실제 파일시스템이 필요한 게 아니라, 파일시스템처럼 동작하는 인터페이스가 필요할 뿐이에요.
ChromaFs: 가상 파일시스템의 설계
가상 파일시스템 ChromaFs는 UNIX 명령어를 가로채 기존 Chroma 데이터베이스에 대한 쿼리로 변환해요. 문서는 이미 검색 기능을 위해 Chroma에 청크로 저장되어 있었기 때문에, 별도 인프라 없이 그 위에 파일시스템 추상화를 얹은 거예요.
구현의 핵심은 Vercel Labs의 just-bash예요 — bash를 TypeScript로 재구현한 프로젝트로, 플러그어블 FileSystemInterface를 노출해요. 파싱, 파이핑, 플래그 처리는 just-bash가 담당하고, ChromaFs는 모든 파일시스템 호출을 Chroma 쿼리로 번역하는 역할만 맡아요.
디렉토리 트리 초기화
ChromaFs는 에이전트가 명령을 실행하기 전에 전체 파일 트리를 미리 알아야 해요. 이를 위해 gzip 압축된 JSON 문서(__path_tree__)를 Chroma 컬렉션 내에 저장해요.
{
"api-reference/endpoints/users": ["get-users", "post-user"],
"guides": ["quickstart", "authentication"]
}
초기화 시 서버는 이 문서를 가져와 두 가지 인메모리 구조로 파싱해요:
- 디렉토리 → 자식 목록을 매핑하는
Map<string, string[]> - 빠른 존재 확인을 위한
Set<string>
ls, cd 같은 명령은 네트워크 호출 없이 로컬 메모리에서 즉시 해결돼요. 트리는 캐시되므로 같은 사이트의 후속 세션은 Chroma fetch를 건너뛰어요.
접근 제어(RBAC) 구현
ChromaFs는 사용자 세션 토큰을 기반으로 파일 트리를 빌드하기 전에 슬러그를 프루닝(pruning)해요. 접근 권한이 없는 파일은 트리에서 완전히 제외되므로, 에이전트는 그 경로의 존재 자체를 인식할 수 없어요.
실제 샌드박스에서 이 수준의 per-user 접근 제어를 구현하려면 Linux 사용자 그룹 관리, chown/chmod 권한 설정, 또는 고객 티어별 격리된 컨테이너 이미지가 필요해요. ChromaFs에서는 __path_tree__ 빌드 전 몇 줄의 필터링으로 끝나요.
// 세션 토큰 기반 경로 필터링 예시
const allowedPaths = await pruneBySessionToken(rawPaths, sessionToken);
const tree = buildTree(allowedPaths);
grep 최적화와 읽기 전용 보장
cat, ls 같은 명령은 가상화가 단순하지만, grep은 완전히 달라요. 네트워크를 통해 모든 파일을 순차적으로 스캔하면 치명적으로 느려지거든요.
grep의 가상화 전략
ChromaFs는 grep을 가로채 플래그를 파싱하고 Chroma 의미론적 쿼리로 변환해요. 어떤 파일이 히트를 포함하는지 식별한 뒤 해당 청크를 Redis 캐시에 저장하고, grep 명령은 매칭된 파일만 대상으로 재작성되어 just-bash의 인메모리 실행으로 넘어가요.
# 에이전트가 실행하는 명령
grep -r "Authorization" /api-reference/
# ChromaFs 내부 동작
# 1. Chroma 쿼리: "Authorization" 포함 청크 식별
# 2. 매칭 파일 목록 → Redis 캐시에 저장
# 3. just-bash에 재작성된 명령 전달 (인메모리 실행)
결과적으로 대규모 재귀 grep 쿼리도 밀리초 단위로 완료돼요. 반복 읽기도 Redis 캐시 덕분에 Chroma를 두 번 찌르지 않아요.
읽기 전용 보장과 스테이트리스 아키텍처
모든 쓰기 작업은 EROFS(Read-Only File System) 에러를 던져요. 에이전트는 자유롭게 탐색하지만 문서를 변경할 수 없어요. 덕분에 시스템은 완전히 스테이트리스(stateless)가 되고, 세션 정리가 필요 없으며, 한 에이전트가 다른 에이전트의 뷰를 오염시킬 위험도 사라져요.
또한 모든 파일이 Chroma에 존재할 필요도 없어요. 고객 S3 버킷에 저장된 대용량 OpenAPI 스펙처럼 lazy 파일 포인터를 등록해두면, 에이전트가 cat을 실행할 때 비로소 컨텐츠를 가져와요.
마무리
가상 파일시스템 ChromaFs는 실제 샌드박스 없이도 에이전트가 문서를 코드베이스처럼 탐색할 수 있게 해줘요. 세션 생성 시간은 46초에서 수백 밀리초로 단축됐고, 기존 Chroma 인프라를 재사용하므로 대화당 추가 비용은 사실상 제로예요. RAG의 한계를 파일시스템 추상화로 극복하는 이 접근법은, 문서 어시스턴트를 넘어 다양한 에이전트 워크플로우에 응용할 수 있는 강력한 패턴이에요.