안녕하세요. LINE VOOM 서비스의 추천 시스템을 개발하는 ML 엔지니어 이창현, 백진우입니다. 저희는 LINE VOOM의 실시간 추천 시스템을 위한 대규모 벡터 데이터베이스 도입 프로젝트를 진행했습니다. 이번 글에서는 그 도입 과정을 자세히 소개하고자 합니다.
LINE VOOM이란
먼저 저희가 개발하고 있는 서비스, LINE VOOM을 소개하겠습니다. LINE VOOM은 LINE 앱 내에서 서비스하는 비디오 콘텐츠 중심의 소셜 네트워크 서비스입니다. 현재 일본과 대만, 태국 등에서 서비스하고 있습니다.
LINE VOOM에서는 누구나 콘텐츠 크리에이터가 되어 콘텐츠를 업로드할 수 있으며, 사용자는 다양한 콘텐츠를 탐색하고 소비할 수 있습니다. For you 탭에서는 사용자가 흥미를 느낄 만한 동영상을 연속적으로 시청할 수 있고, Following 탭에서는 팔로우한 크리에이터의 콘텐츠를 모아볼 수 있습니다.
이 글에서는 주로 For you 탭에서 제공하는 추천 프로세스를 다룰 예정입니다. For you 탭은 사용자에게 개인화한 콘텐츠 추천 결과를 제공하는 탭입니다. 사용자의 콘텐츠 피드백, 예를 들어 이전에 시청 혹은 클릭했거나 '좋아요'를 누른 등의 피드백을 토대로 사용자가 선호할 만한 콘텐츠를 추출해 제공합니다.
기존 추천 시스템의 문제점
이전에 사용하던 추천 시스템의 전체 작동 흐름은 다음과 같습니다.
- 포스트 작성: 사용자가 비디오 포스트를 작성합니다.
- 포스트 임베딩 생성: 작성된 포스트에 대한 임베딩을 생성합니다.
- 포스트 임베딩 저장: 생성된 임베딩을 벡터 데이터베이스에 저장합니다.
- 유사한 포스트 검색(ANN(approximate nearest neighbor)): 유사성 검색을 통해 해당 포스트와 유사한 포스트들을 찾습니다.
- 추천 포스트 요청 및 가져오기: 사용자에게 추천된 포스트들을 제공합니다.
이 과정을 통해 사용자는 자신의 관심사에 맞는 다양한 콘텐츠를 쉽게 접할 수 있었는데요. 한 가지 문제가 있었습니다.
문제점: 즉시성 부족
기존 추천 시스템은 포스트 임베딩을 생성해 저장한 후 추천 후보군을 추출해서 인메모리 데이터베이스에 저장하는 과정을 모두 일 단위 오프라인 배치 작업으로 처리했습니다. 이 때문에 추천 후보군을 업데이트하는 데 최대 하루가 걸린다는 한계가 있었고, 이 한계는 사용자 경험에 다음과 같은 문제를 초래했습니다.
- 크리에이터 A가 새해를 맞아 'Happy New Year'라는 내용의 영상을 게시했을 때 이 영상이 사용자들에게 즉시 추천되지 않습니다.
- 크리에이터 B가 월드컵 경기 중 골을 넣은 장면을 담은 영상을 게시했지만 이 영상 역시 사용자들에게 즉시 추천되지 않습니다.
이와 같이 신선한 콘텐츠를 바로 볼 수 없다는 '즉시성 부족' 문제는 사용자 경험을 저하했습니다. 이를 해결하기 위해 시스템을 개선할 필요가 있었고, 실시간 추천 시스템을 구현하는 프로젝트를 시작했습니다.
이 프로젝트의 목표는 사용자가 게시한 포스트를 즉각 추천 후보군에 반영해 더 신선한 포스트를 사용자에게 추천하는 것이었습니다. 이를 위해서 기존 시스템의 많은 부분을 변경했는데요. 일 단위로 후보군 풀(포스트 풀)을 생성하던 방식을 모델 기반의 실시간 후보군 생성 방식으로 변경했고, 벡터 검색 방식을 오프라인 연산에서 온라인 연산으로 전환했습니다.
그중 이 글에서는 벡터 검색 구조의 변경에 중점을 두고 설명하려고 합니다.
새로운 실시간 추천 시스템의 구조와 벡터 DB가 필요했던 이유
새로 개발한 실시간 추천 시스템의 전체적인 작동 흐름은 다음과 같습니다.
위와 같이 실시간 추천을 구현하기 위해 이전 추천 시스템에서 오프라인으로 수행하던 작업들을 온라인으로 전환해야 했는데요. 이를 위해 두 가지 작업이 필요했습니다. 첫 번째로 포스트 임베딩을 저장해 두는 공간을 오프라인 저장소에서 온라인 저장소로 교체해야 했습니다. 두 번째로 이전에는 유사성 검색을 통해 추천 가능한 모든 포스트를 오프라인에서 미리 찾아 그 결과를 온라인 저장소에 저장하는 방식으로 진행했는데요. 이제는 중간 저장 과정 없이 즉시 유사성 검색을 수행해야 했습니다.
저희는 온라인 저장소와 실시간 유사성 검색, 이 두 가지 기능을 구현하려면 벡터 DB를 도입해야 한다고 판단했고, 여러 벡터 DB 플랫폼을 탐색하기 시작했습니다.
지금까지의 과정을 요약해 보겠습니다.
- 기존 추천 시스템은 오프라인 저장소와 배치 처리를 통해 유사성 검색을 수행했으며, 이로 인해 즉시성이 떨어지는 문제가 있었습니다.
- 기존 추천 시스템의 주요 문제는 포스트 생성 후 추천 후보군에 포함되기까지 최대 하루가 소요된다는 점이었으며, 이 때문에 사용자들에게 즉시 포스트를 제공하지 못하고 있었습니다.
- 기존 시스템의 문제를 해결하기 위해 오프라인 작업을 모두 온라인으로 전환하기로 결정했고, 이를 위해서는 포스트 임베딩을 온라인 저장소에 저장하고, 중간 과정 없이 실시간으로 유사성 검색을 수행하는 시스템으로 개선해야 했습니다.
- 온라인 저장소와 유사성 검색을 실시간으로 처리하려면 벡터 DB를 도입할 필요가 있었습니다.
벡터 DB 선정 기준과 Milvus를 선택한 이유
최근 벡터 DB 생태계가 발전하면서 다양한 선택지가 생겼는데요. 저희는 그중에서 적합한 플랫폼을 선정하기 위해 다음과 같은 몇 가지 기준을 세웠습니다.
- 벡터 전용 DB여야 한다.
- 오픈소스여야 한다.
- 온프레미스 환경에 직접 구축할 수 있어야 한다.
- 실시간 추천을 위해 높은 부하에서도 안정적으로 작동하며 지연 시간이 낮아야 한다.
이러한 기준을 두고 탐색했을 때, 적절한 프레임워크는 Milvus와 Qdrant가 있었습니다. 이제 두 프레임워크를 비교해 보겠습니다.
기준 | Milvus | Qdrant |
---|---|---|
성능(QPS(query per second), 지연 시간)(참고) | 2406 req/s, 1ms | 326 req/s, 4ms |
스토리지/컴퓨팅 분리 | O | X |
스트림과 배치 지원 | O | X |
GitHub 별 개수(커뮤니티 규모 및 활성도 간접 측정) | 35.9K stars | 24.6K stars |
지원하는 인메모리 인덱스 유형 개수 | 10(참고) | 1(HNSW만 지원) |
Milvus는 성능 면에서 Qdrant에 비해 우수했고, 스토리지와 컴퓨팅을 분리해 안정성 또한 더 높았습니다. 또한 다양한 인덱스 알고리즘을 지원하고 있어서 여러 실험을 통해 저희 시나리오에 맞게 성능을 최적화할 수 있는 가능성이 크다고 판단했습니다. 스트림과 배치 작업이 분리되어 있어 온라인 INSERT와 오프라인 벌크 INSERT 기능을 지원하기 때문에 향후 임베딩 업데이트에 대응하는 기능도 구현할 수 있을 것으로 판단했으며, 더불어 활발한 커뮤니티 덕분에 문제 발생 시 정보를 쉽게 얻을 수 있다는 장점도 있었습니다.
위와 같은 이유로 저희는 Milvus를 채택하기로 결정했습니다.
Milvus 소개
Milvus는 수십억 개 이상의 대규모 벡터 데이터에 대한 유사도 검색을 전제로 설계됐기 때문에 아래와 같이 구조가 복잡합니다. 대규모 벡터 데이터에 대한 유사도 검색이 목적이었기에 클러스터 버전으로는 공개된 사용 사례가 많지 않았고, 이에 따라 성능과 안정성이 어떠할지는 불확실한 요소로 남아 있었습니다.
저희는 이 불확실성을 해소하고 Milvus를 성공적으로 도입하기 위해 성능과 안정성을 철저히 검증해야 했고, 이를 위해 카오스 테스트와 성능 테스트를 진행했습니다.
먼저 카오스 테스트에서는 시스템이 얼마나 안정적으로 작동하는지 확인하고, 만약 시스템이 불안정하게 작동하는 상황이 있다면 이를 어떤 방법으로 안정화할 수 있는지에 중점을 두고 테스트를 진행했습니다.
다음으로 성능 테스트에서는 ANN 벤치마크에서 확인할 수 있는 벡터 검색 성능이 저희 환경에서도 재현되는지, 한정된 자원으로 처리량을 어떻게 최대화하고 응답 시간을 최소화할 수 있는지 등에 중점을 두고 테스트를 진행했습니다.
그럼 각 테스트 방법과 결과를 하나씩 살펴보겠습니다.