먼저, 테스트 과정과 결과는 블로그에 조금 더 자세히 정리해뒀습니다.

여기에는 핵심만 간단히 적어보겠습니다.
검색엔진이 왜 필요할까?
검색은 생각보다 단순하지 않습니다.
강남 스시
강남스시
강남에 있는 스시
오마카새
사람은 띄어쓰기도 틀리고 오타도 냅니다.
그래도 검색창은 알아서 비슷한 결과를 찾아줘야 하죠.
그래서 서비스에 검색을 넣다 보면 Elasticsearch나 OpenSearch 같은 전문 검색엔진을 보게 됩니다.
그런데 OpenSearch가 생각보다 무거웠습니다
한국어 검색도 가능하고 기능도 많습니다.
그런데 실제로 띄워보니 데이터가 거의 없는 상태에서도 메모리를 약 760MB 먹고 있었습니다.
JVM 기반이고 기능도 많으니 어느 정도는 당연합니다.
그래도 이름, 주소, 업종 정도를 검색하는 서비스에 이 정도가 필요한가 싶었습니다.
그래서 대안을 직접 비교해봤습니다.
OpenSearch vs Typesense vs PostgreSQL
OpenSearch
한국어 형태소 분석부터 복잡한 검색 튜닝까지 가능합니다. 강력하지만 상대적으로 무겁습니다.
Typesense
오타 허용, 자동완성, 필터, 지역 검색 등을 비교적 간단하게 사용할 수 있습니다.
PostgreSQL + pg_trgm
별도 검색 서버가 필요 없습니다. 부분 일치와 유사도 검색이 가능합니다.
한국어 데이터 5천 건으로 직접 돌려봤습니다
정상적인 검색어만 넣으면 의미가 없을 것 같아 실제 사용자가 입력할 법한 검색어를 만들었습니다.
강남스시하루 → 띄어쓰기 없음
오마카새 → 오타
강남에 있는 스시 하루 → 문장형 검색
성수카 → 입력 중인 검색어
이런 식으로 총 12개 검색어를 테스트했습니다.
결과가 꽤 의외였습니다
원하는 검색 결과가 1위로 나온 횟수를 비교했습니다.
| 검색 방식 | 1위 적중 |
|---|---|
| OpenSearch 기본 구성 | 2 / 12 |
| PostgreSQL + pg_trgm | 4 / 12 |
| Typesense | 10 / 12 |
| Typesense + 필드 보강 | 11 / 12 |
Typesense가 가장 잘 나왔습니다.
물론 이 결과만 보고 Typesense가 OpenSearch보다 좋은 검색엔진이라고 할 수는 없습니다.
OpenSearch에 Nori 같은 한국어 형태소 분석기를 붙이고 랭킹까지 제대로 튜닝하면 결과는 달라질 수 있습니다.
이번 비교는 어디까지나 복잡한 튜닝 없이 짧은 한국어 데이터를 검색하는 현재 조건에서의 결과입니다.
5만 건까지 늘려봤습니다
Typesense 데이터를 5만 건까지 늘려서 속도와 메모리도 확인했습니다.
| 항목 | 결과 |
|---|---|
| 검색 응답 p50 | 4.7ms |
| 검색 응답 p95 | 5.7ms |
| 메모리 | 약 208MB |
비교했던 OpenSearch는 데이터가 거의 없는 상태에서도 약 760MB를 사용하고 있었습니다.
짧은 한국어 이름이나 주소를 검색하는 지금 용도에는 Typesense 정도면 충분해 보였습니다.
결국 OpenSearch를 걷어냈습니다
구조는 오히려 단순해졌습니다.
기본 검색 → Typesense
Typesense 장애 → PostgreSQL + pg_trgm
원본 데이터는 PostgreSQL에 있으니 Typesense 인덱스가 날아가도 다시 만들면 됩니다.
이번에 다시 느낀 건 하나였습니다.
유명하고 강력한 기술이 항상 내 서비스에 가장 잘 맞는 기술은 아니었습니다.
문서만 계속 보는 것보다 내 데이터를 직접 넣고, 오타도 내보고, 띄어쓰기도 빼보고 돌려보는 게 훨씬 빨랐습니다.
가끔은 뭔가를 더 붙이는 것보다 필요 없는 걸 하나 걷어내는 게 더 좋은 최적화인 것 같습니다.
저도 몇 가지 사용해봤습니다만 기술 이해도가 높은 편은 아닙니다.
그런데 먼저 생각해볼 건,
검색 엔진이 왜 필요한가?
사용자의 요구사항은 무엇인가?
라고 생각합니다.
초기에는 키워드 검색으로도 충분할 수 있습니다.
검색이 필요한 사용자들은 한 번의 검색으로 원하는 결과가 정확히 나오기를 기대하기보다 여러 키워드로 바꿔가며 검색하기도 합니다.
오타까지 보정해야 하는지, 의미 기반 검색까지 필요한지도 결국 서비스와 사용자에 따라 다릅니다.
처음부터 모든 경우를 대비해 복잡하게 만들기보다 실제 사용자의 검색어와 검색 결과 데이터를 수집하고, 분석하면서 필요한 방향을 결정하는 게 낫다고 생각합니다.
그리고 실제로 의미 기반 검색이 필요하다는 판단이 들면 저라면
LLM으로 내용 요약 → Embedding → Vector Search
정도로 최대한 단순하고 확실하게 시작할 것 같습니다.