Zola는 빠르고 가벼운 정적 사이트 생성기입니다. 서버 없이 Client-side 검색 기능을 구현하려면 적합한 JavaScript 라이브러리가 필요합니다. Zola는 Search 기능을 위해 Fuse와 Elasticlunr 기반의 index format 생성을 지원하여 쉽게 검색을 구현할 수 있습니다.
둘 다 가볍고 의존성 없이 동작하지만, 한글 지원과 사용 편의성에서 차이가 있습니다. 이 글에서는 두 라이브러리의 기능, 성능, 한글 지원, 그리고 왜 제가 Fuse.js를 선택했는지 이야기해 보겠습니다.
What is Fuse.js and Elasticlunr.js?
Zola에서 검색 기능을 추가하려면 Client-side JavaScript 라이브러리가 필요합니다. Fuse.js와 Elasticlunr.js는 각각 Fuzzy Search와 Full-Text Search에 강점을 가진 인기 있는 옵션입니다.
라이브러리 | 특징 | 장점/단점 |
---|---|---|
Fuse.js | Fuzzy Search에 특화된 라이브러리 | 장점: 오타나 부분 일치에 강력하며, 설정이 간단해 빠르게 구현 가능 단점: 복잡한 검색 기능은 지원하지 않음 |
Elasticlunr.js | Full-text Search를 지원 | 장점: Boolean 쿼리, TF/IDF 랭킹 등 고급 기능 제공 단점: 한글 검색 시 추가 설정 필요 |
Why Compare These Two?
블로그나 문서의 검색 기능은 간단하면서도 다국어를 잘 지원해야 합니다. 두 라이브러리 모두 의존성 없이 동작하고, Zola의 Tera 템플릿과 JavaScript로 쉽게 통합 가능하다는 점에서 매력적이었습니다. 하지만 저에겐 한글 검색 성능과 설정의 편의성, 그리고 Zola의 심플한 철학에 얼마나 잘 맞는지가 선택의 핵심이었습니다.
Fuse.js: Simple and Powerful Fuzzy Search
- 기능: 배열이나 객체 목록에서
title
,content
같은 키를 지정해 간단히 인덱싱합니다. 검색 임계값(threshold)이나 가중치(weight)로 유연한 쿼리 조정이 가능합니다. - 한글 지원: 별도 플러그인 없이 한글 Fuzzy Search가 자연스럽게 작동합니다. 예를 들어, "한글"로 검색하면 "한글 검색", "한글서치" 같은 결과도 잘 찾아냅니다.
- 성능: 소규모~중규모 데이터셋(수백~수천 개 문서)에서 빠르고 가볍게 동작합니다.
e.g.
const fuse = new Fuse(list, { keys: ['title', 'content'], threshold: 0.4 });
const results = fuse.search('한글');
Elasticlunr.js: Advanced Search Option
- 기능: 필드별 인덱싱, 스톱 워드 커스터마이징, Boolean 쿼리, TF/IDF 랭킹을 지원합니다. 필드별 부스팅(예:
title:검색
)으로 정밀한 검색이 가능합니다. - 한글 지원: 기본 설정은 영어 중심이라 한글 검색 성능이 떨어집니다.
lunr-languages
플러그인을 추가해야 한글 토큰화가 제대로 작동합니다. - 성능: 대규모 데이터셋에서도 빠르지만, 브라우저 메모리 한계가 있고 설정이 상대적으로 복잡합니다.
e.g.
const index = elasticlunr();
index.addField('title');
index.addDoc(doc);
const results = index.search('한글', { fields: { title: { boost: 2 } } });
How to Integrate with Zola?
Zola는 Tera 템플릿과 JavaScript로 검색 UI를 쉽게 구성할 수 있습니다. config.toml
설정에 따라 빌드 시 JSON 포맷의 index 파일이 생성되고, 이를 JavaScript에서 로드하여 검색 기능을 추가하면 됩니다.
Fuse
index_format
을 fuse_javascript
또는 fuse_json
으로 설정하면 빌드 시 search_index.en.json
과 같이 Fuse.js가 사용할 수 있는 포맷의 index 파일이 생성됩니다.
# config.toml
[search]
index_format = "fuse_javascript" # or "fuse_json"
Elasticlunr
Fuse와 동일하게 elasticlunr_javascript
또는 elasticlunr_json
으로 설정하면 Elasticlunr 포맷의 index 파일이 생성됩니다.
# config.toml
[search]
index_format = "elasticlunr_javascript" # or "elasticlunr_json"
My Case
저는 아래와 같이 title
에 가중치를 더 주고, body
와 tags
를 검색 대상에 포함했습니다. threshold
값을 조절하여 검색 민감도를 설정할 수 있습니다.
var options = {
keys: [
{ name: "title", weight: 2 },
{ name: "body", weight: 1 },
{ name: "tags", weight: 1 },
],
includeScore: true,
ignoreLocation: true,
threshold: 0.4, // Adjust as needed for search sensitivity
};
var currentTerm = "";
var documents = Object.values(window.searchIndex.documentStore.docs);
var fuse = new Fuse(documents, options);
// https://github.com/hahwul/goyo/blob/main/static/goyo.js
Why I Chose Fuse.js
초기에는 Zola가 한글 index를 직접 지원하지 않아 영어 검색만 가능한 Elasticlunr를 사용하고 있었습니다. 하지만 올해 5월(2025.05)에 제가 보낸 PR이 머지되면서 공식적으로 한글 index 지원이 가능해졌고, 최근 릴리즈에 포함되었습니다.
그래서 다시 검색 라이브러리를 고민하게 되었고, 결과적으로 Zola의 심플한 철학과 잘 어울리는 Fuse.js로 마음이 기울었습니다. Fuse.js 커뮤니티가 훨씬 활발하다는 점도 매력적이었습니다. 또한, lunr-language
가 한글을 지원하긴 하지만 Elasticlunr.js에 통합하는 과정에서 손이 많이 가는 반면, Fuse.js는 별도 설정 없이 바로 사용할 수 있어 편리했습니다.
Conclusion
Zola에서 검색 기능을 구현한다면, Fuse.js를 간단하고 빠른 솔루션으로 추천합니다. 특히 한글 검색에서 별도 설정 없이 유연한 Fuzzy Search를 제공해 소규모~중규모 사이트에 최적입니다. Elasticlunr.js는 고급 검색 기능이 필요한 곳에서 유용하겠지만 그래도 대부분의 상황에선 Fuse가 투자 대비 효과가 좋다고 생각합니다.
두 라이브러리 모두 훌륭하지만, 제 경험상 Fuse.js가 Zola의 간결함과 더 잘 맞았습니다. 여러분들도 블로그나 문서 페이지를 운영하신다면 여러 검색 기능을 비교해보고 더 나은 검색을 만들어가길 바랄게요.