검색 랭킹 흐름 만들기: 검색은 처음 인디요

Hy Lee
당근 테크 블로그
8 min readMar 13, 2022

안녕하세요! 당근마켓 검색 시스템을 개발하고있는 Hy(하이) 에요

검색은 사용자에게는 매우 쉬운 활동이지만, 그 한번의 검색으로 사용자를 만족시키기 위해 시스템에서는 다양한 프로세스를 거쳐요. 오늘은 그 한번의 검색의 랭킹을 만들기 위해 어떠한 것들을 하는지, 또 어떠한 고민을 했는지, 데이터의 흐름관점에서 이야기 해볼게요.

들어가기 전에 어떠한 검색모델을 통해 랭킹을 개선하고 있는지 궁금하다면, 저희팀 모델 개발자 Aiden의 카테고리 잘 활용해보기: 중고거래 검색 개선을 참고 해주세요!

검색 랭킹 파이프라인 기술 스택

검색 랭킹의 Pipeline은 위와 같은 기술 스택을 사용하고 있고, 크게 4가지의 단계가 있어요.

  1. 검색 문서 분류
  2. 검색 문서 색인
  3. 검색 랭킹 모델 생성
  4. 검색 랭킹 서빙과 실험
중고거래 검색 랭킹이 만들어 지는 과정 요약

각 단계를 저렇게 나눈 이유는 각 단계안에서

  • 비슷한 모듈 끼리 공통화 할 수 있을것 같은 단위
  • 단계와 단계사이에 약한 의존과 멱등을 가져가서 시스템 안정성을 지킬 수 있는 단위

이 두가지를 생각해서 나누었어요! 그럼 이제 각 단계별로 이야기 해볼게요.

1. 검색 문서 분류

이 단계에서는 문서가 어떤 종류의 문서인지 분류하는 일을 주로해요. 예를들어 “아직 멀쩡한 아이폰 11Pro를 팔아요” 같은 글을 사용자가 작성한다면 해당 글은 핸드폰을 파는 문서 라는 것을 검색엔진이 알 수 있게 해주는 단계 에요.

모델에 대한 자세한 것은 나중에 저희팀 모델 개발자 Aiden이 알려주시리라 믿고 넘어 갈게요.

해당 단계에서는 문서를 분류 하기 위한 학습 모델파이프라인, 학습 모델을 실시간으로 예측하는 Inference API 그리고 많은 문서들을 예측하는 대용량 예측 파이프라인 작업이 있어요.

Airflow On Kubernetes 환경을 통해 모델을 학습해요.

  • 모델 학습, 예측 등의 코드들이 Airflow에 의존성없이 개발 할 수 있는 환경을 만들기 위해 K8S를 활용했어요.
  • GPU환경이 필요할때와 필요 없을때를 고려할 수 있어요.
  • (초반 구축때 많은 도움을 주신 SRE팀 Frank에게 무궁한 감사를 드려요!)

S3에 모델을 저장하고, Central Dogma를 통해서 버저닝을 해요.

  • AWS 에는 저장소로써 매우 훌륭하고 저렴한 S3가 있어요. 이곳에 모델과 학습 데이터, 중간데이터 등을 저장하고 있어요. HDFS를 운영하지 않아도 되어서 너무 편해요!
  • Version이 바뀌었을때 쉽게 여러 서버에 전파를 해야할 필요가 있었기 때문에 Coordinator 시스템이 필요했어요. 그 때 마침 사내에서 운영하고 있는 Central Dogma가 있어서 이것을 활용 했어요.

Go 언어로 배포된 model을 실시간으로 Inference하고 있어요

  • Model Serving 오픈소스를 고려했지만, 당근마켓 검색 알고리즘에서 다양한 라이브러리를 쓰고 있고, ML 라이브러리가 대부분 C++을 쓰고 있기 때문에 Go로 Wrapping해서 Inference할 수 있는 서버를 개발 했어요.

Spark을 통해 대용량 문서를 예측을 해요

  • 모델이 변경 될때 마다, 수억건의 서비스 문서들을 예측해야 하기 때문에 Spark같은 분산시스템을 활용 하고 있어요.
  • Spark의 Executor/Core/Partition 사이즈를 Data의사이즈에 맞게 여러 조합으로 Benchmark를 돌리고 튜닝 해서, 몇시간 걸리던 수억건의 데이터를 수십분 내로 줄일 수 있었어요!
모델 학습 예측 배포 파이프라인

아래는 모델이 변경 되었을때, 모델을 배포하고 대용량 문서들을 예측하는 과정이에요. 예측한 데이터는 다음 단계에서 이야기할 전체색인 과정에서 사용하기위해 DB에 적재하고 있어요.

모델 배포 파이프라인

2. 검색 문서 색인

검색이 되어야할 문서를 검색엔진에 색인 하는 단계 에요. 이곳에 색인이 되어야 실제 사용자들이 검색을 했을때 문서를 볼 수 있어요.

문서를 색인 할때는 문서의 제목, 내용, 그외 문서에대한 정보들 그리고 검색랭킹을 위해서 문서 분류단계에서 만든 분류 정보들을 함께 색인 해요.

당근의 검색은 전체 색인 단계와 실시간 색인 단계가 있어요.

전체색인

  • 당근마켓 검색의 전체색인은 매일 모든 데이터를 Migration하고 있어요.
  • 분류 단계에서 Spark로 예측한 값을 가져와서 색인 해요.
  • 전체 색인 단계에서 생긴 증분데이터 들은 실시간 Go Inference API를 통해서 예측해요.
  • 전체색인을 끝내면 랭킹 모델을 만들기 위해 전체문서의 Snapshot을 S3에 채워넣어요.
전체 색인과 실시간 색인 과정

실시간 색인

실시간 색인을 할때 아래와 같은 작업을해요.

  • 다른 팀들에서 발행한 Kafka 이벤트들을 검색팀에서 구독해서 색인 해요.
  • 실시간으로 분류모델을 통한 Bulk예측이 필요했어요.
  • 검색엔진의 부하를 줄 이기 위해 Bulk로 색인 해야 했어요.

이 같은 작업을 하기위해서는 잠시 동안 구독중인 데이터의 State를 가지고 있을 수 있는 TimeWindow 같은 기능을 제공하는 라이브러리가 필요했어요. 그렇지만, Go에는 아직 레퍼런스가 많은 Streaming 라이브러리가 없어서 직접 만들었어요.

직접 만든 Go Streaming library

KafkaStreams를 많이 참고했어요. 저희는 라이브러리가 필요했고, KafkaStreams는 Flink, SparkStreaming과 다르게 라이브러리 형태의 Streaming 오픈소스이기 때문에 참고하기가 좋다고 생각했어요. 그리고 Event 기반의 처리를 하기 때문에 Microbatch보다 리소스가 적게 들어가는 점 도 좋았고, 제가 이전에 기여활동을 했었던 프로젝트여서 이해도가 비교적 높은 편이었어요.

라이브러리를 만들고 실제로 데이터를 적재할 때, 타이트한 Tumbling window와 안전하지만 중복 트래픽이 많을 수 있는 Sliding window중에서 고민을 했어요. 그래서 Benchmark를 돌려 보았는데, Tumbling window도 누락이 전혀없어서 Tumbling window를 선택했어요!

tumbling vs sliding

State Store는 우선 In-Memory를 쓰고있어요. 당장은 이슈가 없지만, 서버가 Gracefull하게 죽지않거나 했을때 이슈가 있을수 있어요. 그래서 나중에는 K8S의 PV를 활용해서 RocksDB같은 Local DB로 바꿀예정이에요.(생각만 하고있답니다…..)

더 자세한건 나중에 기회가 된다면 조금 더 이야기 해볼게요.

3. 검색 랭킹 모델 생성

해당 단계는 사용자의 검색 질의에 따른 랭킹 가중치 모델을 만드는 단계 에요. Aiden이 작성해주신 카테고리 잘 활용해보기: 중고거래 검색 개선 같은 알고리즘이 들어가는 중요한 단계이기도 해요.

랭킹 모델 파이프라인
  • 이벤트로그와 수동대응한 기록들로 학습 데이터를 추출해요.
  • Airflow On Kubernetes 환경을 통해 모델을 학습, 예측을 해요.
  • 충분히 배포되어도 될 모델인지 체크를 하기도해요.
  • Redis에 예측한 데이터를 업로드해서 서빙을 준비해요.

질의 단계에서의 모델 예측 방식은 사용자 접점이기 때문에, 실시간으로 예측을 하기보다는 모델의 성능과 상관없이 안정적으로 빠른 성능을 내줄 수 있는 Redis에 미리 예측한 데이터를 넣는 방향을 선택했어요.

4. 검색 랭킹 모델 서빙과 실험

이제 마지막입니다! 이번에는 사용자가 검색을 했을때 사용자의 질의에 따른 랭킹 Score를 전달해주는 마지막 단계 에요.

  • 인터페이스는 비교적 TypeSafe한 protobuf 와 gRPC조합으로 서빙을 하고있어요.
  • 실험을 하기 위해 당근마켓의 실험플랫폼의 segment값을 이용해서 모델의 예측값을 선택해요.
  • CS대응을 위해 어드민에서 수동으로 score를 조절 할 수 있어요.

사실 검색은 처음이라서…

당근마켓을 시작으로 검색 시스템을 처음 개발하게 되었는데요. 새롭게 도전하는 문제들이 많았지만 좋은 동료들과 협업하면서 당근마켓만에 검색 시스템을 만들어 가고 있어요. 과정속에서 배우는게 많고 시스템이 점점 발전하고 있어서 보람을 느끼며 재미있게 개발하고 있어요!

사실 예상하신 그거 맞아요... 저와 같이 새로운 문제에 도전하고 당근마켓만에 검색팀을 만드실 분을 찾습니다!!

많은 지원 부탁드려요!

--

--