1,600개 이상의 사이버 보안 (Cybersecurity) 기사를 대상으로 검색 엔진을 구축하며 실제로 배운 것들
요약
1,600개 이상의 사이버 보안 기사를 대상으로 Meilisearch를 활용해 고성능 검색 엔진을 구축한 경험담입니다. 단순 키워드 매칭의 한계를 극복하기 위해 기술 스택 선정부터 데이터 품질 관리까지의 실무적인 과정을 다룹니다.
핵심 포인트
- Meilisearch를 활용해 오타 처리 및 50ms 미만의 빠른 검색 구현
- 검색 품질은 도구보다 메타데이터와 콘텐츠 품질에 좌우됨
- 발췌문(Excerpt) 품질 강제 및 카테고리 필터링을 통한 검색 정밀도 향상
1년 전 저에게는 문제가 하나 있었습니다. Go 백엔드 (Backend)에 1,600개 이상의 사이버 보안 (Cybersecurity) 기사들이 흩어져 있었는데, 검색창은 쓸모없는 결과만 내놓고 있었습니다. 표준적인 MySQL LIKE '%keyword%' 방식은 창피한 수준이었습니다. "pentest Active Directory"라고 검색하면, 한쪽에는 "pentest"라는 단어가 있고 다른 쪽 어딘가에 "Directory"라는 단어가 포함된 기사들이 검색되었습니다. 전혀 관련 없는 콘텐츠가 검색 결과 상위에 노출되었습니다. 그래서 저는 처음부터 다시 구축했습니다. 실제로 일어난 일들에 대한 솔직한 버전입니다.
제가 선택한 스택 (및 그 이유)
제 백엔드 (Backend)는 Go Fiber입니다. 저는 다음과 같은 요건을 충족하는 것이 필요했습니다:
- 오타 처리 (사용자는 "kerberoasting"이 아니라 "kerberosting"이라고 검색함)
- 50ms 미만의 결과 반환
- 셀프 호스팅 가능 (소규모 사이트를 위해 SaaS 의존성 없음)
- 괜찮은 Go 클라이언트 보유
저는 Meilisearch를 선택했습니다. 모든 사용 사례에 기술적으로 최고이기 때문이 아니라, 위의 모든 요건을 충족하면서 설정하는 데 20분밖에 걸리지 않았기 때문입니다.
// 시작 시 기사 인덱스 동기화
func SyncMeilisearch ( client * meilisearch . Client , articles [] Article ) error {
index := client . Index ( "articles" )
docs := make ([] map [ string ] interface {}, len ( articles ))
for i , a := range articles {
docs [ i ] = map [ string ] interface {
"id" : a . ID ,
"title" : a . Title ,
"slug" : a . Slug ,
"excerpt" : a . Excerpt ,
"category" : a . Category ,
"tags" : a . Tags ,
"published_at" : a . PublishedAt ,
}
}
_ , err := index . AddDocuments ( docs )
return err
}
인덱스는 시작 시 자동으로 동기화되며 CRUD 훅 (Hooks)을 통해 업데이트됩니다. 따라서 기사가 생성, 업데이트 또는 삭제될 때마다 Meilisearch는 동기화된 상태를 유지합니다.
저를 놀라게 한 것: 콘텐츠 문제
첫 일주일이 지난 후, 저는 고통스러운 깨달음을 얻었습니다. 검색 품질은 도구의 문제가 아니라 대부분 콘텐츠의 문제라는 점이었습니다. Meilisearch는 제 역할을 다하고 있었습니다. 하지만 제 기사들은 메타데이터 (Metadata)가 일관되지 않았습니다. 어떤 기사는 풍부한 발췌문 (Excerpt)이 있었지만, 어떤 기사는 전혀 없었습니다. 태그 (Tags)는 느슨하게 적용되어 있었습니다. 카테고리 (Category) 할당도 때때로 잘못되었습니다.
가장 큰 차이를 만들어낸, 제가 수정한 세 가지 사항:
1.
쓰기 시점에 발췌문 (Excerpt) 품질 강제하기: 적절한 발췌문(최소 길이 준수, 상투적인 문구 제외)이 없는 기사는 거부하는 검증 로직을 추가했습니다. 이를 구현하는 것은 지루한 작업이며 아무도 하고 싶어 하지 않습니다. 하지만 그럼에도 불구하고 반드시 해야 합니다.
-
키워드 검색보다 카테고리 필터링이 효과적임: 특정 도메인에 특화된 코퍼스 (Corpus)의 경우, 사용자가 카테고리 (뉴스 / 가이드 / 분석 / 체크리스트)별로 사전 필터링을 할 수 있게 하면 검색 공간이 극적으로 줄어듭니다. 관련성 순위 (Relevance ranking)가 완벽하지 않더라도 정밀도 (Precision)가 올라갑니다.
GET /api/search?q=kerberoasting&cat=guide&limit=10 -
폴백 (Fallback)의 중요성: Meilisearch가 다운될 때가 있습니다. 드물지만 발생합니다. 저는 자동으로 작동하는 MySQL LIKE 폴백을 추가했습니다:
`results, err := SearchMeilisearch(query, filters)
if err != nil || len(results) == 0 {
results, err = SearchMySQL(query, filters) // fallback
}
솔직한 수치
| 지표 (Metric) | 이전 (Before) | 이후 (After) | 평균 (Avg) |
|---|---|---|---|
| 검색 지연 시간 (search latency) | 340ms (MySQL LIKE) | 28ms (Meilisearch) | |
| 오타 허용 (Typo tolerance) | 없음 (None) | 1~2글자 오류 처리 가능 | |
| 다중 단어 쿼리 (Multi-word queries) | 미흡 (Poor) | 양호 (Good) | |
| 인덱스 크기 (Index size) | 해당 없음 (N/A) | ~12MB | |
| 설정 시간 (Setup time) | — | 총 ~2시간 |
1,600개 이상의 기사를 위한 12MB 인덱스는 강조할 만한 가치가 있습니다. Meilisearch는 매우 가볍습니다.
다르게 했을 일들
1. 발췌문(excerpts)뿐만 아니라 전체 콘텐츠를 인덱싱할 것
저는 제목, 슬러그(slugs), 발췌문, 태그는 인덱싱했지만, 기사 본문 전체는 인덱싱하지 않았습니다. 이는 기사 내용 깊숙이 등장하는 기술 용어를 검색했을 때 아무것도 반환되지 않음을 의미합니다. 이 부분을 점진적으로 수정하고 있습니다.
2. 첫날부터 유의어(synonyms)를 추가할 것
Meilisearch에는 유의어 API가 있습니다. 사이버 보안(cybersecurity) 용어에 대한 유의어 목록을 즉시 구축했어야 했습니다:
{ "AD" : [ "Active Directory" ], "pentest" : [ "penetration test" , "intrusion test" ], "MFA" : [ "multi-factor authentication" , "2FA" ] }
저는 명백한 쿼리 누락을 발견한 후에야 뒤늦게 이를 추가했습니다.
3. 모든 검색 실패를 기록할 것
제가 가진 가장 가치 있는 데이터셋은 결과가 0개로 반환된 검색 목록입니다. 이는 어떤 콘텐츠가 부족한지, 어떤 유의어를 추가해야 하는지를 정확히 알려줍니다. 저는 이를 search_misses 테이블에 기록하기 시작했는데, 처음부터 그렇게 했어야 했습니다.
요약 (The takeaway)
콘텐츠 중심의 사이트를 구축하면서 막대한 인프라 투자 없이 좋은 검색 기능을 원한다면:
- Meilisearch는 진정으로 훌륭하고 정말 쉽습니다.
- 콘텐츠의 품질은 언제나 알고리즘의 영리함보다 우선합니다.
- 도메인 특화 검색(domain-specific retrieval)의 경우, 쿼리가 대화형이거나 개방형이 아니라면 벡터 임베딩(vector embeddings)이 필요하지 않습니다.
- 결과가 0개인 검색을 기록하세요. 이는 비용이 들지 않는 제품 조사 방법입니다.
카테고리/난이도/유형 필터, 페이지네이션(pagination), 그리고 Meilisearch/MySQL 폴백(fallback) 기능이 포함된 전체 검색 엔드포인트는 Go 언어로 약 80줄 정도입니다. 도움이 된다면 기꺼이 공유하겠습니다.
저는 사이버 보안 컨설팅 회사인 AYI NEDJIMI Consultants를 운영하고 있습니다. 코퍼스(corpus)는 침투 테스트(pentesting), Active Directory, 클라우드 보안 및 컴플라이언스(compliance)를 다루며, 17개의 무료 보안 강화 체크리스트(PDF + Excel)를 포함하고 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기