이메일 50,000통을 밀리초 만에 검색하기: MailVault 로컬 인덱스의 작동 방식
MailVault에 단어를 입력하면 키를 누르는 순간 가장 최근 일치 결과가 화면에 나타납니다. 메일함이 정말 커도 그렇게 되는지 확인하려고 메시지 50,000개짜리 볼트를 만들어 검색 시간을 쟀습니다. 가장 느린 쿼리가 14밀리초였습니다.
이 글에서는 실제 측정값, 무엇을 측정했고 무엇을 측정하지 않았는지, 그리고 그 뒤에 있는 기술, 곧 볼트 안에 들어 있는 작고 평범한 SQL 데이터베이스를 소개합니다.
테스트
실제 메일과 같은 형태, 곧 멀티파트 HTML과 일반 텍스트 구성으로 각각 약 3.3 KB인 메시지 50,000개를 만들었습니다. 메시지는 세 폴더(받은편지함, 보관함, 보낸편지함)에 대략 3분의 1씩 나누고, 알려진 단어를 알려진 비율로 심어 두었습니다. "invoice"는 메시지의 5%, "budget"은 8%, "meeting"은 6%이며, 영어가 아닌 검색을 확인하기 위해 일본어와 악센트가 있는 단어도 넣었습니다. 모든 메시지는 릴리스 빌드에서 MailVault의 실제 MIME 파서와 실제 인덱스 코드를 거쳤습니다.
테스트 기기는 16 GB 메모리의 Apple M4 Mac mini였습니다. 놀고 있던 기기가 아니어서, 테스트 중에도 다른 빌드가 돌아가고 있었으므로 이 시간은 바쁜 컴퓨터에서 나오는 값이라고 보시면 됩니다. 각 쿼리는 여섯 번씩 실행했고, 세 번은 수정본의 임시 빌드에서, 세 번은 병합된 코드에서 실행했습니다. 아래 수치는 그 실행들의 범위이며, 각 시간에는 검색과 목록에 표시되는 결과 행을 만드는 시간이 모두 포함됩니다.
결과
50,000 messages · Apple M4 · warm cache · 6 runs each
query matches rows shown time
invoice ~2,500 500 7.1 – 7.5 ms
budget meeting 246 246 13.4 – 14.1 ms
update 4999 15 15 13.5 – 14.0 ms
会議 (Japanese) 1,529 500 4.3 – 4.6 ms
last 7 days, no words 1,008 500 1.0 ms
first index build 11 s (10.9 – 11.9 s)
index size on disk 225 MB
status check 5 ms
표에서 눈여겨볼 점은 두 가지입니다. 첫째, 시간은 일치하는 개수와 관계가 없습니다. 15건이 나온 쿼리가 2,500건이 나온 쿼리보다 오래 걸렸는데, 시간을 좌우하는 것은 되돌아오는 메일의 양이 아니라 쿼리의 형태(두 단어 구문이 한 단어보다 일이 많습니다)이기 때문입니다. 둘째, 목록은 가장 최근 일치 결과를 최대 500개까지만 보여 주고, 더 있으면 그렇다고 알려 주므로, 일치하는 메시지가 아무리 많아도 결과를 그리는 작업에는 상한이 있습니다.

한 번만 드는 비용은 인덱스를 만드는 일입니다. 메시지 50,000개에 약 11초, 초당 대략 4,000개꼴이고 디스크는 225 MB를 씁니다. 이 작업은 백그라운드에서 진행되어 그동안에도 MailVault를 계속 쓸 수 있고, 그 뒤로는 새 메시지와 바뀐 메시지만 인덱싱합니다.

1 ms와 7 ms는 어떻게 느껴질까
밀리초는 감이 잘 오지 않으니 자를 하나 놓아 봅시다. 60 Hz 화면은 16.7 ms마다 다시 그려지는데, 여기서 가장 느린 검색도 화면이 한 번 다시 그려지는 시간 안에 끝났습니다. 사용성 연구는 1993년부터 같은 세 가지 한계를 써 왔습니다. 0.1초 미만이면 즉각적으로 느껴지고, 1초까지는 생각의 흐름이 끊기지 않으며, 10초가 되면 주의가 떠나갑니다. 14밀리초는 "즉각" 한계의 약 7분의 1입니다. 1 ms인 날짜 필터는 그 한계보다 백 배 빠릅니다.
서버 메일, 보관, 백업까지 한 번에 검색

MailVault는 세 종류의 메일을 나란히 둡니다. 서버에서 동기화한 메시지, 사용자가 보관한 메시지, 백업에서 복원한 메시지입니다. 모두 같은 볼트 안의 파일이 되므로 같은 인덱스에 들어갑니다. 이번 테스트에서도 메일은 받은편지함, 보관함, 보낸편지함에 나뉘어 있었고, 쿼리 하나로 전부를 훑었습니다. 메시지가 어디에서 왔는지는 찾는 속도에 영향을 주지 않습니다.
서버에만 있고 내려받은 적 없는 메일은 볼트에 없으므로 로컬 인덱스는 그 존재를 알 수 없습니다. 그래서 MailVault는 서버에도 물어보며, 서버가 답하는 동안 인덱싱된 로컬 결과가 먼저 나타납니다. 이 구간은 사용 중인 제공업체에 달려 있어서 숫자를 공개하지 않습니다. Premium에서는 서버 편지함 하나 대신 최대 다섯 개를 한꺼번에 검색할 수 있습니다.
외부 백업 드라이브는 두 번째의 차가운 사본입니다. 검색은 작업용 볼트에서 이루어지며, 백업 드라이브에도 사본이 있는 결과에는 표시가 붙습니다.
기술: 아주 빠르고 아주 단순한 SQL 데이터베이스
검색 서버도, 클라우드 서비스도 없습니다. 인덱스는 볼트 안에 있는 SQLite 파일 하나이며, SQLite는 아마 세계에서 가장 널리 배포된 데이터베이스일 것입니다. MailVault는 SQLite의 전문 검색 엔진인 FTS5를 trigram 토크나이저와 함께 사용합니다. 모든 단어가 세 글자씩 겹치는 조각으로 저장됩니다. 그래서 "voic"을 입력하면 "invoice"를 찾을 수 있고, 와일드카드도 정확한 단어 규칙도 필요 없습니다. 악센트는 무시되므로 "reunion"으로 "Réunion"도 찾을 수 있습니다. 단어 사이에 띄어쓰기를 쓰지 않는 일본어와 중국어는 이를 위해 만든 두 번째 테이블을 거칩니다.
속도는 세 가지 평범한 결정에서 나옵니다.
- 검색은 메시지 파일을 열지 않습니다. 목록에 필요한 모든 정보(보낸 사람, 제목, 날짜, 폴더, 플래그)가 인덱스 행에 저장되어 있습니다. 메시지 50,000개 테스트에서 결과를 만드는 동안 메일 파서는 한 번도 호출되지 않았습니다.
- 파일 하나, 프로세스 하나. 인덱스는 MailVault의 백그라운드 헬퍼가 소유하며, 한 번 열어 둔 채 계속 유지됩니다. 따로 시작할 것도, 네트워크로 보낼 것도 없습니다.
- 기준은 언제나 사용자의 디스크입니다. 인덱스는 파생 데이터입니다. 혹시 손상되더라도 MailVault가 저장된 메시지로 다시 만들며, 메시지 자체는 건드리지 않습니다.
오프라인에서도 작동하며, 어떤 것도 컴퓨터 밖으로 나가지 않습니다.
첨부 파일과 이미지 (Premium)
무료 검색은 보낸 사람, 제목, 메시지 본문을 다룹니다. Premium은 같은 인덱스, 같은 검색창에서 첨부 파일 안의 텍스트까지 더합니다.
- 첨부 파일 텍스트. PDF, Word, Excel, PowerPoint 파일을 읽어 그 안의 텍스트를 인덱싱하므로, 계약 번호로 검색하면 그 번호가 들어 있는 PDF가 첨부된 메시지를 찾을 수 있습니다.
- macOS의 이미지와 스캔 텍스트. MailVault는 Mac의 Apple Vision 프레임워크로 사진, 스크린샷, 스캔한 페이지 속 텍스트를 인식해 인덱싱합니다. 인식은 기기 안에서 이루어집니다. Windows와 Linux에는 이 단계가 없습니다.
첨부 파일 안에만 있는 검색 결과에는 클립 표시가 붙으므로, 본문에는 별다른 내용이 없는 메일이 왜 나왔는지 알 수 있습니다. 이번 테스트에서는 첨부 파일 추출 시간을 재지 않았습니다. 사용자의 파일에 따라 달라지며, 검색할 때가 아니라 첨부 파일마다 한 번씩 백그라운드에서 실행되기 때문입니다.
다른 클라이언트는 자기 검색을 어떻게 설명하나
다른 메일 앱은 벤치마크하지 않았고, 아래 앱 중 메시지 50,000개에서의 검색 시간을 공개한 곳도 없으므로, 이것은 스톱워치가 아니라 설계를 비교한 것입니다.
- Apple Mail: Apple의 안내 기준으로 Spotlight의 첫 인덱싱은 데이터 양에 따라 몇 시간, 심지어 며칠이 걸릴 수 있고, Mail에는 인덱싱이 아직 끝나지 않았다는 알림이 표시될 수 있습니다.
- Outlook for Windows는 Windows Search 인덱스를 사용하며, Microsoft의 안내 기준으로 인덱싱이 끝날 때까지 결과가 불완전할 수 있고, 로컬에 캐시된 메일만 인덱싱되며, 검색 결과가 너무 많으면 오래된 항목이 숨겨질 수 있습니다.
- Thunderbird는 자체 데이터베이스에 전역 인덱스를 둡니다. 버그 트래커에는 대용량 메일함에서 인덱싱이 느려진다는 오래된 보고가 이어지고 있으며, 한 사용자는 메시지 36,000개에 며칠이 걸렸다고 적었습니다. 이는 오래된 하드웨어에서의 사용자 보고라서 우리 테스트와 직접 비교할 수 없습니다.
우리의 설계 선택은 흔한 방식과 반대입니다. 사용자가 저장한 사본을 직접 인덱싱하고, 그것을 작은 파일 하나에 두고, 쿼리 경로를 짧게 유지해서 답이 밀리초 단위로 나오게 합니다.
이 테스트가 보여 주지 않는 것
메일함은 합성 데이터입니다. 실제 메일은 더 크고 지저분하므로 본문이 긴 경우 인덱스는 더 커집니다. 다만 쿼리는 여전히 파일이 아니라 인덱스를 훑습니다. 시간은 웜 캐시 기준이며, 재시작 후 첫 검색은 디스크에서 더 많이 읽습니다. 테스트는 제목, 보낸 사람, 본문을 다루었고 첨부 파일 텍스트는 다루지 않았으며, 기기 한 대에서 실행했습니다.
측정은 직접 되풀이해 볼 수 있습니다. 벤치마크는 MailVault 소스 트리에 있는 무시 처리된 Rust 테스트 search_index_bench_50k_real_parser이며, 위의 모든 숫자를 출력합니다.
6년 전의 이메일을 밀리초 만에 찾으십시오.
MailVault는 보관함 옆에 비공개 검색 인덱스를 두므로 메시지 50,000개도 500개만큼 쉽게 검색됩니다. 무료로 사용할 수 있습니다. 첨부 파일과 이미지 검색은 Premium에 포함됩니다.
출처: Apple Support, Spotlight 인덱싱; Microsoft Support, Outlook 검색 문제; Mozilla Bugzilla 585429. 벤치마크는 2026년 9월 21일에 측정했습니다.