서버

[BUCL 프로젝트] Full Text Search를 활용한 검색 엔진 성능 개선

창민이 개발일지 2024. 5. 22. 20:26

 

기존 방식

  • 검색 페이지(/search)에 들어가 상품 이름(”productName”)를 검색시, %LIKE% 사용해 productName과 겹치는 상품 리스트를 클라이언트에게 전달
@Query(
"SELECT p FROM Product p " +
"WHERE p.name LIKE %:productName% " +
"AND p.deletedAt IS NULL " +
"AND p.isExposed = true " +
"AND p.productStatus = com.freeder.buclserver.domain.product.vo.ProductStatus.ACTIVE " +
"ORDER BY p.productPriority DESC")
Page<Product> findProductsBySearchByConditions(
    @Param("productName") String productName,
    Pageable pageable
);

문제점

1. 띄어쓰기 오타에 대해서 해당 상품을 검색하지 못하는 문제

원인 분석

%LIKE% 검색의 경우 문자열이 정확히 일치해야 하기 때문에, “유모 차”와 “유모차”를 다른 단어로 인식합니다.

 

2. 상품 검색시 상품 리스트를 가져오는 데 오래 걸리는 문제

  • 가짜 상품 데이터 1,000개로 테스트를 진행했습니다.
  • 개발자 도구의 네트워크를 확인해본 개발 상품 리스트를 가져오는 데, 걸리는 시간은 평균 500ms로 유저 사용했을 때 사용성이 좋지 않는 문제가 있습니다.
    • 1,000개 상품에 대해서 대략 500ms 속도 → 상품이 10,000, 100,000 일 경우 매우 늘려지는 문제

 

[문제 접근]

  1. Elastic Search를 사용하는 경우
  2. Full Text Search를 사용하는 경우

1. Elastic Search를 사용하는 경우

역색인

Elastic Search은 오픈소스 검색 엔진 서비스로 DB 인덱스에 대해서 n-gram한 키워드를 기준으로 역색인으로 검색하기에 매우 빠르게 해당 데이터에 대해 검색할 수 있습니다.

 

문제점

  • Elasticsearch의 경우 오픈소스이기에 AWS 처럼 사용 비용이 발생

  • 스탠더드 경우라도 달에 95 달러의 비용이 발생하기에 현실적으로 사용하기 어려웠습니다.

뭘 하든 돈 많은 게 짱입니다

 

2. Full Text Search를 사용하는 경우

  • 여러 데이터베이스에 내장된 기능으로 Elasticsearch 처럼 인덱스를 기준으로 역색인화해 데이터를 빠르게 검색할 수 있는 기능입니다.
  • 내장 기능이기 때문에, 따로 비용이 발생하지 않습니다.

결론

  • 저는 Freeder는 비용 문제로 최종적으로 Elasticsearch 대신 Full Text Search를 사용하기로 했습니디.

Full Text Index 종류 선택

  1. Built In Parser를 사용하는 경우
  2. N gram를 사용하는 경우

1. Built-In Parser를 사용하는 경우

  • Built-In Parser는 정관사나 부정관사 등을 제외한 stop word(구분자)를 기준으로 키워드를 추출합니다.

문제점

  • 구분자(띄어쓰기 등)를 기준으로 토크나이징하기 때문에 “유모”, “모차”의 단어는 단어는 검색되지 않습니다.

2. N-gram Parser를 사용하는 경우

  • N-gram Parser는 단어를 n크기로 문자열을 토큰화 해서 키워드를 추출합니다.
유모차 브랜드
ex) N:2 => "유모", "모차", "차 ", " 브", "브랜", "랜드"

위 방식을 사용하면 Built-in의 문제를 해결할 수 있지만 데이터의 개수가 많아지면 stop word에 비해 인덱스가 매우 커지는 문제가 있습니다.

 

결론

  • 유저의 사용성의 중요성과 현재 상품의 개수가 대략 30개이기 때문에 인덱스의 크기가 매우 커지지 않기 때문에 최종적으로 n-gram parser 방식을 사용하기로 했습니다.
  • 저희는 n의 크기를 2로 설정 했습니다.

[결과]

띄어쓰기 오타에 대해서 해당 상품 검색 가능

  • 기존 %LIKE% 검색과 달리 “유 모차” 같은 띄어쓰기 오타에 대해서도 검색할 수 있습니다.

검색 API 성능 향상

  • 542ms -> 66ms
  • 풀텍스트 인덱스 검색 방식을 사용해서 기존 %LIKE% 검색 알고리즘 대비 약 87.8%의 성능 향상

FullText Index 사용에 따른 검색 성능 향상

  • 사용툴: nGrinder
  • 가상유저: 20명, 테스트 시간: 30초

  • 풀텍스트 인덱스 검색 방식을 사용해서 기존 %LIKE% 검색 알고리즘 대비 약 86.3%(MRT) 속도 향상 및 TPS가 기존 대비 2.4배 이상(35.6 → 86.4) 증가 시켰습니다.

BUCL(버클)

  • 버클은 제가 창업 대학(코코네스쿨)에서 진행한 창업 프로젝트입니다. 창업을 하면서 간접적으로 회사 생활을 경험을 해본거 같아요. 취업하려는 분들도 취업 전에 한번 쯤 창업 활동 해보면 좋을 까 생각하네요. 개발자 뿐만 아니라 기획자, 디자이너, PM 다양한 사람들도 대화해볼 경우가 많이 생깁니다.