게스트하우스 검색 시스템 설계 - Workaway

chaean·2025년 6월 20일

Workaway

목록 보기
7/11

1. 개요

게스트하우스 예약 시스템을 개발하면서, 여기어때, 야놀자와 같은 서비스의 검색 기능을 참고해 사용자 친화적인 검색 기능을 구현하고자 했습니다.


2. 검색 기능 기획

사용자가 검색어를 입력한 뒤 숙소를 탐색할 수 있도록 아래 요소를 기준으로 검색 기능을 기획했습니다.

  • 검색어 (ex: 공덕역, 서울특별시, 랜드마크, 숙소명 등)
  • 체크인 날짜
  • 체크아웃 날짜
  • 인원 수

검색어에 대한 데이터는 MongoDB에 행정구역, 관광지 등의 데이터를 수집하여 위도, 경도와 함께 저장해두었습니다


✅ 추천 기준 설계

일반적인 숙소 플랫폼은 아래와 같은 정렬 기준을 제공합니다:

  1. 추천 순
  2. 평점 높은 순
  3. 리뷰 많은 순
  4. 낮은 가격 순
  5. 높은 가격 순
  6. 거리 순

이 중 추천 순은 단순 정렬이 아닌 점수화 기반의 계산을 필요로 합니다.

이 중 ‘추천 순’은 다음과 같은 가중치를 기반으로 점수화했습니다

항목가중치
거리 유사도40%
평점35%
리뷰 수25%
좋아요 수10%

모두 정규화된 값으로 계산하여 공정성을 유지하고, 리뷰 수와 좋아요 수는 상한 개수를 정하여 규모에 영향을 줄였습니다.

검색어와 게스트하우스 이름의 유사도를 Levenshtein 알고리즘을 통해 구현하려 했으나, SQL만을 이용하여 구현하기에는 페이징 처리에 어려움이 있었고,
이를 해결하기 위해 Elasticsearch를 도입하는 방법도 존재하였지만, 현재 Workway와 같이 작은 서비스에서 도입하기에는 너무 무거운 기술이라고 생각되어 이름에 대한 유사도는 제외하기로 결정했습니다.


QueryDSL로 추천 점수 계산

NumberExpression<Double> recommendScore = Expressions.numberTemplate(
    Double.class,
    "(" +
        "(GREATEST(0, 1 - cast(ST_Distance_Sphere(point({0}, {1}), point({2}, {3})) as double) / 10000) * 0.3) + " +
        "(IFNULL(avg({4}), 0) / 5 * 0.3) + " +
        "(LEAST(COUNT(DISTINCT {5}), 100) / 100 * 0.2) + " +
        "(LEAST(COUNT(DISTINCT {6}), 100) / 100 * 0.2)" +
    ")",
    게스트하우스lng, 게스트하우스lat,
    키워드lng, 키워드lat,
    리뷰점수,
    리뷰,
    좋아요
);

데이터에 대한 페이징 처리가 필요했기때문에, SQL레벨에서 점수 계산을 해야했고,
거리를 계산하는 MySQL의 ST_Distance_Sphere 함수를 통해 해결할 수 있었습니다.


마무리

추천 정렬은 단순 조건문보다 훨씬 복잡하지만,
사용자 경험에 가장 큰 차별점을 만드는 요소이기도 합니다.

QueryDSL의 Expressions.numberTemplate()를 통해 유연하게 구현할 수 있었고,
DB 부하와 비즈니스 정확도 사이의 균형을 잡는 것이 핵심이었습니다.

profile
백엔드 개발자

0개의 댓글