[WHY 시리즈 2] E.002 — 상점 검색 결과 개선 (1)

Mijeong (Rachel)
5 min readJul 7, 2020

‘코드와 서비스 만들기를 좋아하는 소프트웨어 엔지니어’로 일하고 있다. 엔지니어는 문제를 해결하는 사람이다. 꾸준히 문제를 발견하고 해결하는 엔지니어가 되기 위해 이 글을 작성하고자 한다. 발견한 문제와 해결책을 WHY 시리즈 글로 공유하고자 한다. 꾸준히 공유하고 꾸준히 피드백 받기를 바란다.

올해는 WHY 시리즈 글쓰기에 참 게으르다. 다른 종류의 글을 쓰기도 하고 일에 더 몰입해서 지내기도 하고 핑계를 대자면 다양하다. 겨우 마음을 다잡고 글을 쓰려고 보니 밀려있는 주제가 가득하다. 지금 이야기하려는 주제도 벌써 약 6개월 전의 변화이다. 그 사이 참 많은 일과 사람의 변화가 있었다.

우리가 만들고 있는 서비스에서 사용자는 키워드를 입력하여 원하는 상점 목록을 결과로 얻을 수 있다. 사용자로부터 원하는 상점이 잘 검색되지 않는다는 피드백을 받았고, 현상과 문제를 파악하기 시작했다. 현상은 간단했다. 특정 키워드 입력 시, 키워드와 관련 없어 보이는 상점이 상위에 노출됐다. 예를 들면, 베트남 전통 간식인 Chè를 키워드로 검색하면 Kitchen, Chewy와 같은 단어가 이름에 포함된 상점이 상위에 노출된 것이다.

이 현상에 대한 원인은 명확했고, 우리 서비스의 기존 전제는 다음과 같다.

  • MongoDB 사용 중이며 $geoNear aggregation을 통해 거리 filter와 거리 계산을 수행
  • 별도 검색 엔진을 도입하지 않음

위의 전제를 기반으로, 원인은 3가지로 요약할 수 있었다.

  • 키워드를 slugify 후, 단순 부분 검색
  • $geoNear 사용으로 인해, MongoDB의 text search 사용 못 함
  • 검색 결과의 순서를 결정하는 로직에서 거리만 고려함

Why?

1. $geoNear 사용 제거

우리는 MongoDB aggregation을 사용 중이며, aggregation 시 1개의 index만 사용할 수 있다. 앞서 말한 것처럼 $geoNear(2dsphere index)를 이미 사용 중이기 때문에 MongoDB의 text index를 이용한 text search를 활용할 수가 없었다. 우리는 $geoNear를 제거하고 text search를 사용하기로 결정했다.

  • Why? MongoDB의 text search 장점을 활용하기로 했다. 하나의 Collection에서 string field에 대해 text index를 적용할 수 있다. 단일 field에 대해 index를 적용할 수도 있고, 여러 개의 field에 대해 compound index를 적용할 수도 있다. compound index 적용 시, 각 필드에 대해 가중치를 적용할 수 있다는 장점도 있다. 현재는 상점 이름만 검색 대상으로 적용하고 있지만, compound index를 활용하여 음식 이름 수준의 검색도 함께 제공할 계획이다.

Note: MongoDB $geoNear

Note: MongoDB Text Indexes

  • Why? $geoNear aggregation 대신 find()를 사용하여 쿼리하기로 결정했다. $geoNear를 사용하는 이유 중 하나는 배달 위치를 기준으로 우리 서비스에서 제공하는 거리 범위 내에 존재하는 상점을 보여주기 위함이었다. 상점 위치에 대한 위도, 경도 정보를 보유하고 있기 때문에 거리 범위를 명시적으로 지정하여 쿼리가 가능했다. 다만, 이 방식으로 변화할 때 x, y축 평면 기준으로 검색하게 되기 때문에 중심점에서 멀어질수록 2dsphere를 사용하던 기존 검색 결과와 오차가 발생할 수 있다는 위험 요소는 존재했다. 하지만 사용자가 키워드 검색을 통해 원하는 상점 결과를 얻는 행위는 검색 결과 상위 xx 개에서 결정되기 때문에 큰 위험요소가 아니라고 판단했다.

Note: mongoDB 2dsphere Indexes

Note: mongoDB 2d indexes

2. text score 적용

앞에서 언급한 것 처럼 기존에는 오직 거리만을 기준으로 가까운 상점이 검색 결과의 상위에 노출되었다. MongoDB의 text search를 사용하면서 얻을 수 있는 text score도 검색 결과의 순서를 결정하는 계산 로직에 포함시키기로 했다.

  • Why? 키워드로 상점을 검색하는 사용자에게는 키워드 자체가 의도가 될 수 있고, 가까운 거리 만큼 (혹은 그보다 더) 키워드와 관련 있는 상점이 상위에 노출되는 것이 중요하다고 판단했다. 이를 위해 검색 결과로 반환된 document의 score를 반환받고 검색 결과의 순서를 결정하는 계산 로직에 포함했다. MongoDB는 $text 연산자 사용 시 기본적으로 score를 반환하지 않기 때문에 {$meta: “textScore”}를 명시적으로 지정해줘야 한다.

Note: MongoDB Text Score

이러한 기술적 변화를 기반으로 상위 키워드 대상 성능 및 사용성 관점에서 테스트를 수행했고, 적합하다고 판단되어 릴리즈를 완료했다.

해당 검색 결과의 개선이 키워드 검색을 통한 Conversion Rate에 영향을 미치지는 못했다. 당연한 말이지만 기술적 기반을 계속 다져나가면서 핵심 지표를 꾸준히 추적하고 근본적인 해결책에 가까워져야 한다.

조만간 다양한 수준에서의 검색 개선 이야기도, 또 별도의 검색 엔진 도입에 관한 이야기도 할 수 있는 날이 올 것 같다.

나는 말만 많을 뿐 실제 모든 액션을 멋지게 수행해주는 백엔드 챕터 멤버들.png

--

--