신규 검색 서비스 전환기
안녕하세요. 29CM 검색스쿼드 이하윤입니다. 검색스쿼드는 29CM 서비스의 검색플랫폼을 개발하여 사용자가 원하는 결과를 안정적으로 제공하기 위해 최선을 다하고 있습니다. 사용자에게 양질의
medium.com
역시 다양한 카테고리의 상품이 있는 만큼 검색 서비스도 잘할 것 같아서 검색해보니까 아니나 다를까
내가 원하는 정보가 쏙쏙 있었다. 그래서 위 블로그를 많이 참고했다.
일단 나는 ElasticSearch Cloud를 활용했다. -> https://www.elastic.co/kr/elasticsearch
Elasticsearch: 공식 분산형 검색 및 분석 엔진 | Elastic
Elasticsearch는 속도, 수평적 확장성, 신뢰성 및 용이한 관리를 위해 설계된 앞서가는 분산형 RESTful 오픈 소스 검색 및 분석 엔진입니다. 무료로 시작하세요....
www.elastic.co
근데 적용하기 전에 로그 저장용으로 ElasticSearch 엔진이 탑재된 AWS의 OpenSearch를 사용중이라서 이걸 쓰는게 좋을 것 같아서
Spring Boot랑 연동하다가 진짜 삽질 많이 했다..
일단 내가 내린 결론은, 현재의 내 상황에서 AWS의 OpenSearch는 거의 사용 안하는게 좋을 것 같다. 검색엔진이니까 얘도 연동은되는데 Spring Boot의 CrudRepository를 상속받은 ElasticSearchRepository가 사용이 안된다. 분명 모든 블로그나 GPT도 예제를 주는데 아무리해도 먹통이였다.
원인은 AWS OpenSearch와 Elasticsearch 클라우드는 기본적으로 같은 루씬(Lucene) 기반의 검색 엔진을 사용하지만, AWS의 오픈서치는 Elasticsearch 7.10 버전 이후 Elastic과의 라이선스 문제로 인해 독자적인 개발을 진행해서 아예 다른 엔진 됐다고 볼 수 있다..
그래서 여튼 AWS는 손절하고.. 인덱스 매핑부터 시작했다.
1. 인덱스 매핑
/PUT 상품_날짜
{
"settings": {
"analysis": {
"tokenizer": {
"nori_tokenizer": {
"type": "nori_tokenizer",
"decompound_mode": "mixed"
}
},
"analyzer": {
"korean": {
"type": "custom",
"tokenizer": "nori_tokenizer"
}
}
}
},
"mappings": {
"properties": {
"상품명": {
텍스트타입, 키워드타입
},
"브랜드명": {
텍스트타입, 키워드타입
},
"카테고리": {
nested타입
},
"검색키워드": {
텍스트타입, 키워드타입
},
"모델명": {
텍스트타입, 키워드타입
},
"updatedAt": {
"type": "date",
"format": "strict_date_optional_time||yyyy-MM-dd'T'HH:mm:ss||epoch_millis"
},
"id": {
"type": "long"
},
"_class": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"visibleYn": {
"type": "boolean"
},
"status": {
"type": "keyword"
}
}
}
}
이런식으로 엘라스틱에서 기본적으로 제공하는 nori 분석기 적용하고 중간에 몇군데는 생략했지만 토크나이저도 상품명, 키워드, 카테고리, 브랜드 등등 한글이 들어가는 필드에는 모조리 넣어줬다.
2. 검색 테스트
뭐 기본적으로 잘 됐다. 한국어도 음절 어절 알아서 잘 나눠서 검색해주고 가중치를 준만큼 거의 의도된 대로 동작했다.
근데 하나 짜치는 상황이 발생했는데..
한글자씩 검색해봤는데 상품명에 일치하는 않는 친구가 나왔다(?)
테스트 환경에서 매칭된 단어와 그에대한 점수를 하이라이팅 옵션을 줘서 검색을 테스트하는데도.. 진짜 이상했다..
'어'를 검색했더니 '어묵', '스페어' 등 잘 하이라이팅 돼서 나왔다.
근데 문자열이 좀 짧은 (짧을수록 가중치 높음) '다져주는'에 하이라이팅 된 최종 점수가 좀 높게 상위에 랭크되게 검색이 됐다.
뭔가 싶어서 좀 찾아보니까 '다져주는'이라는 단어는 파생어라서 '다지' '어' '주' '는' 으로 인덱싱이 돼서 '어'에 검색된거여서 좀 많이 놀랐다.
확실히 형태소 분석기가 수많은 전문가들, 개발자들이 만든거니까 성능 최고다라고 느끼긴했지만 팀 내에서는 이걸 납득을 할까 싶어서
파생어는 점수를 좀 낮추는 방향으로 제안을 드리긴했다.
확실히 형태소 분석기가 수많은 전문가들, 개발자들이 만든거니까 성능 최고다라고 느끼긴했지만 팀 내에서는 이걸 납득을 할까 싶어서파생어는 점수를 좀 낮추는 방향으로 제안을 드리긴했다. 검색 의도를 고려했을 때, 파생어가 불필요하게 높은 점수를 받는 것은 문제가 될 여지가 있다. 왜냐면 절대적인 상품수가 그리 많지 않아서..?
그래서 팀 내에서 파생어에 대한 점수를 낮추는 방향을 제안했다. 좀 빡셀 것 같긴한데.. 뭐 재밌을 것 같다. 멀티 필드 만들어서 파생어 끊고 약간 각이 나온다. (사망 플래그 온..)근데 사실, 한 글자 또는 이상한 검색어를 입력했을 때, 대부분의 사용자는 검색어를 잘못 입력해서 엉뚱한 결과가 나왔다고 생각할 가능성이 높지만 나의 생각으로는 이런 방식은 구글, 네이버 같은 상품군에만 타겟팅 돼 있는게 아닌 모든 데이터가 다 나오는 대형 검색 엔진에서는 유효한거고 규모가 작은 커머스(절대적인 상품이 적음)에서는 조금 더 엄격한 검색 기준이 필요로 할수도 있다고 지금은 생각이 들어서이다.
-> 파생어 문제가 맞긴한데 멀티필드로 해결할 필요 없고 그냥 필터링으로 해결하면 끝.. 그리고 필드 타입 수정도 무중단으로 가능해서 운영환경에서 알맞게 취사선택하면 될듯하다 ㅎㅎ
암튼 많은걸 배운 요즘이였고 다음번엔 어떻게 의사결정이 어떻게 됐는지에 따라서 기술적으로 어떻게 해결했는지 작성하는게 목표다~~
댓글