✅ 1단계. SQL 기반 LIKE 검색 → Elasticsearch 도입
📌 기존 방식
SELECT * FROM board WHERE title LIKE '%농구%'
❌ 문제점
- 성능 저하: 대량 데이터에서 Full Scan
- 오탈자/띄어쓰기 미지원:
농구
는 검색되지만농규
,농 구
는 미검색
- 정확도 부족: 텍스트 일치 외 유연한 검색 불가능
🎯 개선 목표
- 빠르고 정확한 검색
- 한글 형태소 분석 및 오타 보정
- 관심사/성별/나이 등 사용자 필터링 지원
✅ 2단계. Elasticsearch 기본 검색 적용
✅ 매핑 및 데이터 색인
게시글 데이터를 Elasticsearch에 전송하여 색인합니다.
@Document(indexName = "boards")
public class BoardDocument {
private String title;
private String content;
private List<String> tags;
...
}
✅ match / multi_match 기반 검색 쿼리
{
"multi_match": {
"query": "농구",
"fields": ["title", "content", "tags"]
}
}
✅ 서비스 구현
SearchHits<BoardDocument> hits = elasticsearchRestTemplate.search(query, BoardDocument.class);
Pageable
기반으로 페이징 처리
- 검색어가 포함된
title
,content
,tags
필드 중심 조회
✅ 3단계. 사용자 필터링 조건 적용
🎯 사용자별 검색 조건 예시
- 성별 제한:
GenderType.MALE
,FEMALE
- 나이 제한:
minAge
,maxAge
- 모집 상태:
confirmed == false
✅ 구현 전략
- 도메인 필터링 + 검색 후 후처리
- 또는 ES bool filter 쿼리 적용 (성능 최적화 시)
if (board.getMinAge() > userAge || board.getGender() != userGender) {
// 필터링
}
또는 ES 내부에서 처리:
"bool": {
"must": { "multi_match": ... },
"filter": [
{ "term": { "gender": "MALE" }},
{ "range": { "minAge": { "lte": 26 }}}
]
}
✅ 4단계. 형태소 분석기 기반 Korean Analyzer 적용
📌 문제
- 한글은 조사, 어미, 띄어쓰기 등이 많아 정확한 검색이 어렵다.
- 예:
농구 좋아해요
→농
,구
,좋아
,하다
등 분리 필요
✅ 해결: Nori 형태소 분석기 적용
🔧 인덱스 생성 시 Custom Analyzer 설정
PUT /boards_korean
{
"settings": {
"analysis": {
"analyzer": {
"korean_analyzer": {
"type": "custom",
"tokenizer": "nori_tokenizer"
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "korean_analyzer"
}
}
}
}
Elasticsearch 7.x 이상부터 Nori는 기본 탑재
✅ 5단계. N-gram 기반 부분 검색 적용
🎯 목적
- 부분어 검색 (
농
,농구
,농규
) 지원
- 오타나 단어 일부만 입력해도 검색되도록
✅ ngram 분석기 적용 예시
"analysis": {
"tokenizer": {
"ngram_tokenizer": {
"type": "nGram",
"min_gram": 2,
"max_gram": 3,
"token_chars": ["letter", "digit"]
}
},
"analyzer": {
"ngram_analyzer": {
"type": "custom",
"tokenizer": "ngram_tokenizer"
}
}
}
✅ 다중 analyzer 검색 쿼리
{
"multi_match": {
"query": "농규",
"fields": ["title.korean", "title.ngram"]
}
}
✅ 6단계. Fuzziness 적용 (오탈자 보정 기능)
🎯 목적
농규
,놈구
등 오타도 검색되도록
- Levenshtein 편집 거리 기반 자동 보정
✅ 쿼리 예시
{
"multi_match": {
"query": "농규",
"fields": ["title.korean", "title.ngram"],
"fuzziness": "AUTO"
}
}
"AUTO"
또는"1"
,"2"
등 수치 지정 가능
AUTO
는 단어 길이에 따라 거리 자동 조절
🔄 전체 고도화 흐름 정리
plaintext
복사편집
SQL LIKE 검색
↓
Elasticsearch 기본 검색 (match/multi_match)
↓
도메인 기반 필터링 (나이/성별/모집 여부)
↓
형태소 분석기 적용 (nori)
↓
n-gram 분석기 적용 (부분어 대응)
↓
Fuzziness 적용 (오탈자 대응)
🧠 마무리하며
검색은 단순한 기능이지만, 사용자 만족도와 서비스 완성도를 크게 좌우하는 핵심 요소입니다.
이번 프로젝트에서는 단순 키워드 조회를 넘어, 다음과 같은 점을 직접 구현하며 실전 역량을 키웠습니다:
- 검색 정확도 향상을 위한 분석기 튜닝
- 오탈자 대응을 위한 fuzzy search
- 사용자 조건 기반 필터링
- 성능과 유연성을 고려한 다단계 쿼리 구성