Uber의 서비스에서 검색은 단순히 원하는 정보를 찾는 기능이 아닙니다. Uber Eats에서 수많은 음식점과 메뉴 중 원하는 상품을 찾거나, Uber에서 목적지를 검색하고 적절한 드라이버를 연결하는 과정까지 검색과 랭킹 기술이 핵심 역할을 담당합니다.
문제는 Uber와 같은 대규모 서비스에서는 검색 대상과 데이터가 계속 변한다는 점입니다. 수많은 사용자가 동시에 검색하고, 드라이버의 위치가 실시간으로 바뀌며, 음식점과 메뉴 정보도 지속적으로 업데이트됩니다. 따라서 검색 플랫폼에는 높은 성능과 확장성뿐만 아니라 데이터의 최신성과 안정적인 운영까지 요구됩니다.
Uber의 검색 플랫폼은 이러한 요구에 맞춰 지속적으로 변화해왔습니다. 초기에는 Elasticsearch를 활용해 빠르게 규모를 확장했고, 실시간 검색에 대한 요구가 커지자 Lucene을 확장한 자체 검색 엔진 Sia를 구축했습니다. 그러나 자체 검색 플랫폼을 운영하면서 새로운 기술을 빠르게 적용하고 유지하는 데 또 다른 어려움이 나타났습니다.
이에 Uber는 2024년 Project Sunrise를 시작하고 검색 플랫폼 전략을 다시 설계했습니다. 핵심 방향은 모든 것을 직접 만드는 것이 아니라 오픈소스 생태계와 함께 발전하는 것이었습니다. 그 결과 Uber는 OpenSearch를 새로운 기반으로 선택하고, Sia와 LucenePlus에서 얻은 기술적 경험을 다시 오픈소스 생태계에 기여하는 방향으로 나아가고 있습니다.
이 글에서는 Uber의 검색 플랫폼이 왜 Elasticsearch에서 Sia로, 다시 OpenSearch 중심의 구조로 변화했는지 그 배경과 기술적 특징을 살펴봅니다.
Uber에서 검색이 중요한 이유
검색은 Uber의 핵심 사용자 경험과 직접 연결되어 있습니다.
Uber Eats를 생각해보면 사용자가 검색해야 하는 대상은 매우 많습니다. 전 세계적으로 100만 개가 넘는 음식점이 존재하며, 한 번의 사용자 세션에서도 수천 개에 달하는 음식점이나 메뉴가 검색 대상이 될 수 있습니다.
사용자가 원하는 결과를 찾기 위해서는 단순히 검색어가 일치하는지를 확인하는 것만으로는 부족합니다.
예를 들어 사용자는 다음과 같은 조건을 함께 고려할 수 있습니다.
- 어떤 종류의 음식인지
- 가격은 얼마인지
- 얼마나 빨리 배달되는지
- 특정 식단 조건을 만족하는지
- 과거에 어떤 음식을 주문했는지
- 현재 사용자가 어디에 있는지
Uber Rides에서도 검색은 중요합니다. 목적지를 검색하고 자동완성 결과를 제공하며 사용자의 상황에 맞는 목적지를 예측해야 합니다.
더 나아가 승객과 드라이버를 연결하는 과정 역시 본질적으로는 검색 문제로 볼 수 있습니다. 현재 주변에 어떤 드라이버가 있는지, 드라이버가 어떤 위치에 있는지, 어떤 조건을 만족하는지 등 다양한 실시간 정보를 바탕으로 적절한 결과를 찾아야 하기 때문입니다.
즉 Uber에서 검색은 단순한 검색창 뒤에서 동작하는 기능이 아닙니다. 실제 서비스의 요청을 처리하고 사용자를 적절한 대상과 연결하는 핵심 인프라에 가깝습니다.
이런 환경에서는 빠른 검색만으로 충분하지 않습니다. 검색 결과가 정확해야 하고, 데이터가 최신 상태여야 하며, 수많은 요청을 안정적으로 처리할 수 있어야 합니다.
초기에는 Elasticsearch로 빠르게 확장
Uber의 검색 플랫폼은 초기 단계에서 Elasticsearch를 활용했습니다.
Elasticsearch는 2010년에 출시된 이후 검색과 로그 분석을 위한 기술로 빠르게 확산됐습니다. 빠르게 성장하던 Uber 입장에서도 검증된 검색 기술을 활용해 서비스 규모를 확장하는 것은 자연스러운 선택이었습니다.
당시 Search 팀이 가장 중요하게 생각했던 것은 검색 엔진의 내부 동작을 깊게 수정하는 것보다 안정적으로 운영하고 확장하는 일이었습니다.
Uber의 성장 속도는 매우 빨랐습니다. 검색 클러스터의 용량과 인프라 규모를 약 6개월마다 두 배로 늘려야 할 정도였습니다.
따라서 당시 Search 팀은 검색 엔진 자체를 세밀하게 개발하는 조직이라기보다 SRE 관점에서 검색 인프라를 안정적으로 운영하고 확장하는 역할에 가까웠습니다.
중요한 검색 서비스에는 전용 Elasticsearch 클러스터를 배치하고 이를 담당하는 엔지니어를 별도로 운영했습니다.
이 단계에서 Elasticsearch는 일종의 블랙박스처럼 활용됐습니다.
핵심은 새로운 기능을 직접 개발하는 것이 아니라 높은 가용성과 안정성을 확보하면서 빠르게 증가하는 트래픽을 처리하는 것이었습니다.
하지만 서비스가 성장하면서 상황이 달라졌습니다.
특히 Uber의 일부 핵심 기능에서는 Elasticsearch가 제공하는 검색 모델만으로 해결하기 어려운 문제가 나타났습니다.
실시간 검색을 위해 Sia를 구축하다
Uber의 검색 플랫폼이 자체 기술로 전환하게 된 중요한 이유 중 하나는 실시간성이었습니다.
Elasticsearch의 검색 엔진 기반에는 Apache Lucene이 있습니다. Lucene은 NRT(Near Real-Time) 방식으로 동작합니다. 데이터가 변경됐다고 해서 즉시 검색 가능한 상태가 되는 것은 아니며, 일정한 처리 과정을 거쳐 검색 인덱스에 반영됩니다.
일반적인 검색에서는 이러한 지연이 큰 문제가 되지 않을 수 있습니다.
하지만 드라이버 매칭과 같은 서비스에서는 상황이 다릅니다.
드라이버는 계속 이동합니다. 따라서 시스템은 드라이버의 위치 변화와 같은 데이터를 빠르게 받아들이고, 최신 상태를 기준으로 검색할 수 있어야 합니다.
Uber는 이런 요구를 충족하기 위해 Lucene을 확장했습니다. 핵심은 데이터가 계속 업데이트되는 상황에서도 읽기와 쓰기를 동시에 수행하면서 검색할 수 있도록 만드는 것이었습니다.
이 기술을 기반으로 Uber는 자체 검색 엔진인 Sia를 개발했고, 이후 주요 검색 작업에서 Elasticsearch를 대체했습니다.
Sia의 BSL 인덱스 구조
Sia의 핵심적인 특징은 Live Index, Snapshot Index, Base Index로 구성되는 계층형 인덱스 구조입니다.
가장 먼저 새로운 데이터는 메모리에 있는 Live Index에 저장됩니다.
Live Index는 아직 확정된 형태의 인덱스가 아니라 새롭게 들어오는 데이터를 임시로 보관하면서 실시간 검색을 지원하는 역할을 합니다.
일정한 주기가 지나면 Live Index의 데이터가 Snapshot Index로 만들어집니다. 기존 Snapshot과 결합하면서 데이터가 점차 정리됩니다.
다만 Live Index는 메모리를 많이 사용하는 데이터 구조를 사용하기 때문에 계속 유지할 수는 없습니다. 따라서 주기적으로 데이터를 Snapshot으로 옮겨 메모리 부담을 줄입니다.
시간이 지나면서 Snapshot이 계속 쌓이면 또 다른 문제가 발생합니다. 이를 해결하기 위해 주기적으로 원본 데이터를 다시 읽어 더 작고 효율적인 Base Index를 생성합니다.
정리하면 Sia의 흐름은 다음과 같습니다.
Live Index → Snapshot Index → Base Index
이러한 구조를 통해 Sia는 실시간 데이터 처리와 전체 인덱스 관리 사이의 균형을 맞췄습니다.
Sia가 Elasticsearch와 달랐던 세 가지 핵심
Sia는 단순히 Lucene을 확장한 검색 엔진에 그치지 않았습니다. Uber의 인프라와 대규모 서비스 환경에 맞춰 여러 부분을 다시 설계했습니다.
gRPC와 Protobuf를 활용한 통신
Elasticsearch는 REST API와 JSON을 기반으로 통신합니다.
반면 Sia는 Uber 인프라에서 널리 사용되는 gRPC와 Protobuf를 사용했습니다.
Protobuf는 데이터를 보다 compact한 형태로 직렬화할 수 있기 때문에 통신 데이터 크기와 처리 비용을 줄이는 데 도움이 됩니다.
Uber 입장에서는 이미 내부 인프라에서 사용하던 통신 방식과 검색 엔진의 통신 방식을 일치시킬 수 있다는 장점도 있었습니다.
Kafka 기반 Pull 방식 데이터 수집
데이터를 검색 인덱스에 넣는 방식도 변경했습니다.
기존 Elasticsearch의 방식에서는 외부 애플리케이션이 REST API를 통해 검색 서버에 데이터를 전달했습니다.
문제는 쓰기 요청이 급격하게 증가했을 때 검색 서버가 이를 감당하지 못할 수 있다는 점입니다. 서버가 쓰기 요청을 거부하면 데이터를 보내는 애플리케이션이 다시 속도를 조절하는 등 복잡한 Backpressure 처리가 필요합니다.
Sia는 이 구조를 Kafka 기반 Pull 방식으로 변경했습니다.
데이터 생산자와 Sia를 직접 연결하는 대신 Kafka를 중간에 두고, Sia가 자신의 처리 속도에 맞춰 데이터를 가져가도록 구성했습니다.
이렇게 하면 생산자와 소비자를 분리할 수 있습니다. 검색 시스템의 처리 속도가 일시적으로 느려지더라도 upstream 시스템에 직접적인 압박을 주지 않으면서 데이터를 처리할 수 있습니다.
Active-active 구조
Uber에서는 서비스의 연속성과 장애 대응도 중요합니다.
Sia는 Uber의 Active-active Kafka 인프라를 활용해 여러 지역의 Kafka 데이터를 서로 복제하고 이를 기반으로 글로벌한 데이터 관점을 유지할 수 있도록 구성했습니다.
이를 통해 지역 장애가 발생하더라도 다른 지역에서 검색 서비스를 유지할 수 있는 기반을 마련했습니다.
결국 Sia는 단순히 "더 빠른 검색 엔진"을 만드는 프로젝트가 아니었습니다.
Uber가 실제로 필요로 하는 실시간성, 데이터 처리, 고가용성, 확장성을 검색 플랫폼 자체에 반영한 결과였습니다.
그런데 왜 다시 자체 검색 엔진의 한계가 생겼을까?
Sia는 Uber의 성장에 맞춰 검색 플랫폼을 확장하는 데 중요한 역할을 했습니다.
하지만 시간이 지나면서 새로운 문제가 나타났습니다.
가장 큰 문제 중 하나는 Sia의 BSL(Base/Snapshot/Live) 구조 자체가 새로운 Lucene 기능을 적용하는 데 걸림돌이 되었다는 것입니다.
예를 들어 Lucene에 벡터 검색 기능이 추가되었을 때, Uber는 해당 기능을 Sia의 BSL 구조에 맞게 다시 구현해야 했습니다.
대표적으로 HNSW 알고리즘을 자체 인덱스 구조에 맞게 다시 구현해야 했습니다.
문제는 하나의 기능에 그치지 않습니다.
Lucene에 새로운 Query Operator가 추가될 때마다 이를 Sia의 사용자 정의 인덱스 구조에서도 별도로 지원해야 합니다.
즉, 자체 검색 엔진을 가지고 있다는 것은 Uber의 요구사항에 맞게 최적화할 수 있다는 장점이 있지만, 동시에 Lucene이 발전하는 속도를 자체적으로 따라가야 한다는 부담을 의미했습니다.
모든 검색에 실시간성이 필요한 것은 아니었다
여기서 Uber는 중요한 사실을 발견했습니다.
모든 검색 사용 사례가 진정한 실시간성을 필요로 하는 것은 아니었습니다.
일부 핵심 기능에서는 실시간 데이터가 반드시 필요하지만, 대부분의 검색 애플리케이션은 NRT 방식으로도 충분히 동작할 수 있었습니다.
그렇다면 모든 검색 서비스를 굳이 복잡한 BSL 구조 위에서 운영할 필요가 없습니다.
Uber는 실시간성이 반드시 필요한 사용 사례와 NRT로 충분한 사용 사례를 분리하기 시작했습니다.
NRT가 충분한 검색은 Lucene을 직접 활용하도록 변경했습니다.
이 방식의 장점은 명확했습니다.
기존 BSL 구조에서 필요했던 주기적인 Snapshot 처리와 Base Index 생성 과정을 제거할 수 있었습니다. Lucene이 자체적으로 인덱스의 Compaction을 관리하기 때문에 Uber가 별도의 복잡한 작업을 운영할 필요도 줄어들었습니다.
결국 검색 플랫폼은 필요한 만큼만 복잡해야 한다는 방향으로 변화하기 시작했습니다.
AI와 검색 기술의 빠른 발전도 새로운 과제가 됐다
또 하나의 문제는 검색과 AI 기술이 빠르게 발전하고 있다는 점이었습니다.
검색 기술에서는 벡터 검색이 중요한 영역으로 성장했고, 데이터를 더 작게 압축하는 Quantization 기반 인덱싱, 메모리 사용을 줄이기 위한 DiskANN과 같은 기술도 등장했습니다.
GPU를 활용해 인덱싱 시간을 크게 줄이는 방식도 발전하고 있습니다.
이런 기술을 자체 검색 엔진에 계속 적용하려면 상당한 엔지니어링 역량과 시간이 필요합니다.
Sia가 Uber에 특화되어 있다는 장점은 분명했지만, 검색과 AI 생태계 전체가 빠르게 발전할수록 새로운 기능을 직접 개발하고 유지하는 비용도 함께 커졌습니다.
결국 Uber는 중요한 질문을 던지게 됩니다.
"검색 엔진을 계속 직접 개발하는 것이 장기적으로도 지속 가능한가?"
Uber가 내린 결론은 그렇지 않다는 것이었습니다.
Project Sunrise, 검색 플랫폼 전략을 다시 설계하다
Uber는 2024년 Project Sunrise를 시작했습니다.
목표는 단순히 기존 검색 엔진을 다른 제품으로 교체하는 것이 아니었습니다.
검색 플랫폼의 장기적인 개발 전략 자체를 다시 정의하는 것이었습니다.
핵심 철학은 명확했습니다.
모든 기술을 직접 만들기보다 오픈소스 생태계와 함께 발전한다.
Uber가 필요로 하는 기능은 계속 유지하되, 이미 산업에서 검증되고 활발한 커뮤니티가 존재하는 기술을 기반으로 검색 플랫폼을 발전시키는 방향입니다.
특히 오픈소스를 활용하면서 Uber가 자체적으로 개발한 기술을 다시 커뮤니티에 기여하는 것도 중요한 목표였습니다.
이를 통해 Uber만을 위한 기술을 만드는 데 그치지 않고, 검색 기술 생태계 전체의 발전에 기여하려는 것입니다.
Uber가 OpenSearch를 선택한 이유
Uber는 검색 플랫폼 전략을 재정립하면서 Elasticsearch, OpenSearch, Apache Solr 등을 포함한 여러 기술을 비교했습니다.
평가 기준은 단순한 검색 성능만이 아니었습니다.
- 확장성
- 유연성
- 비용 효율성
- 오픈소스 거버넌스
- 커뮤니티 지원
- 장기적인 기술 발전 가능성
여러 요소를 종합적으로 검토한 결과 Uber는 OpenSearch가 자사의 요구사항에 가장 적합하다고 판단했습니다.
OpenSearch의 오픈소스 특성은 특히 중요한 선택 기준이었습니다.
Apache 2.0 라이선스를 기반으로 하는 OpenSearch는 장기적으로 특정 벤더에 종속되지 않고 플랫폼을 유연하게 발전시킬 수 있는 기반을 제공합니다.
또한 활발하게 성장하고 있는 커뮤니티 역시 중요한 요소였습니다.
Uber는 OpenSearch Software Foundation의 출범을 지원하고 창립 멤버로 참여했습니다. 이를 통해 검색 기술의 거버넌스와 개발, 장기적인 방향 설정에도 참여하고 있습니다.
여기서 중요한 점은 Uber가 단순히 OpenSearch를 "사용하는 것"에 그치지 않는다는 것입니다.
기존에 Sia와 LucenePlus를 개발하면서 얻은 경험을 OpenSearch에 다시 반영하려고 하고 있습니다.
Sia에서 얻은 기술을 OpenSearch로 가져오다
Uber가 OpenSearch로 전환한다고 해서 Sia에서 쌓아온 기술과 경험을 버리는 것은 아닙니다.
오히려 핵심 기술을 오픈소스 생태계에 기여하는 방향으로 이어가고 있습니다.
대표적인 것이 두 가지입니다.
Pull-based ingestion
Sia에서 사용했던 Kafka 기반 Pull 방식 데이터 수집 구조를 OpenSearch에서도 활용할 수 있도록 발전시키고 있습니다.
이를 통해 높은 쓰기 트래픽을 처리할 때 데이터 생산자와 검색 시스템의 결합도를 낮추고 보다 안정적인 데이터 수집 구조를 만들 수 있습니다.
gRPC API
Sia에서 사용했던 gRPC 기반 통신 방식 역시 OpenSearch에 적용하려는 핵심 기술입니다.
기존 REST 기반 통신의 대안으로 고성능 gRPC API를 제공해 대규모 환경에서 보다 효율적인 통신을 지원하려는 것입니다.
Uber는 이러한 기술을 OpenSearch 3.0에도 기여했습니다.
즉 Uber가 자체 시스템에서 얻은 경험이 다시 오픈소스 검색 플랫폼의 기능으로 돌아가는 구조입니다.
LucenePlus가 해결하려는 Parent-Child 검색 문제
OpenSearch를 기반으로 전환하는 과정에서도 Uber만의 요구사항을 해결해야 하는 과제는 남아 있습니다.
대표적인 문제가 Parent-Child 관계를 가진 데이터 검색입니다.
Uber Eats를 예로 들어보겠습니다.
하나의 음식점에는 여러 개의 메뉴가 존재합니다.
즉 데이터 구조는 다음과 같이 볼 수 있습니다.
Store → Items
사용자가 특정 지역에서 "milk"라는 단어가 들어간 메뉴를 찾는다고 가정해보겠습니다.
이때 단순히 메뉴 이름만 검색하면 충분하지 않습니다.
메뉴가 속한 음식점이 사용자의 특정 지역에 있어야 하고, 결과를 음식점 단위로 그룹화하면서 각 음식점에서 상위 몇 개의 메뉴만 가져와야 할 수도 있습니다.
따라서 검색 과정에서 부모인 Store와 자식인 Item을 동시에 고려해야 합니다.
문제는 Lucene이 Uber의 규모와 성능 요구사항을 만족하는 Parent-Child Join 기능을 제공하지 않는다는 점입니다.
Lucene에서 사용할 수 있는 방식에는 크게 두 가지가 있습니다.
Index-time Join
부모와 자식 문서를 하나의 연속된 블록으로 저장하는 방식입니다.
검색 시 부모와 자식의 관계를 빠르게 찾을 수 있다는 장점이 있습니다.
하지만 부모나 자식 중 하나만 변경되어도 전체 블록을 다시 인덱싱해야 합니다.
데이터가 자주 변경되는 Uber의 환경에서는 적합하지 않은 방식입니다.
Query-time Join
부모와 자식 문서를 독립적으로 저장하고 Query 시점에 관계를 연결하는 방식입니다.
데이터를 독립적으로 업데이트할 수 있다는 장점이 있습니다.
하지만 검색 과정에서 많은 데이터를 미리 가져와야 하는 Over-fetching 문제가 발생할 수 있으며, 그만큼 검색 지연 시간도 증가할 수 있습니다.
Uber는 이 두 방식의 한계를 해결하기 위해 데이터 배치 자체를 다시 설계했습니다.
데이터 구조를 바꿔 검색 효율을 높이다
Uber는 메뉴 데이터를 음식점 단위로 묶고, 음식점을 UUID 기준으로 분할했습니다.
각 음식점 내부에서는 메뉴를 연속적으로 저장하고 정적인 Rank Score를 기준으로 정렬했습니다.
이렇게 하면 검색할 때 필요한 데이터를 무작정 전체 탐색할 필요가 줄어듭니다.
검색 시스템은 부모 문서 전체를 탐색하는 Iterator와 실제 조건에 맞는 부모 문서의 Iterator, 그리고 해당 부모에 속한 자식 문서의 Iterator를 관리합니다.
그리고 필요한 수의 자식 문서를 확보하거나 특정 부모에 속한 자식 문서를 모두 확인하면 다음 부모로 넘어갑니다.
결과적으로 필요하지 않은 데이터를 계속 탐색하지 않으면서 Parent-Child 검색을 수행할 수 있습니다.
하지만 여기에도 문제가 있습니다.
데이터가 계속 들어오고 수정되고 삭제되면 정렬된 데이터 구조를 지속적으로 유지해야 합니다.
인덱스 정렬은 비용이 높은 작업입니다.
특히 Lucene의 Forced Merge를 검색 서비스가 데이터를 제공하는 과정에서 수행하면 검색 지연 시간이 크게 증가할 수 있습니다.
Uber는 이를 해결하기 위해 Read/Write Separation 구조를 적용했습니다.
LucenePlus의 Read/Write Separation
LucenePlus에서는 데이터 수집과 검색을 분리합니다.
데이터를 수집하는 Ingester는 Kafka에서 데이터를 가져와 주기적으로 인덱스를 Commit합니다.
이 과정에서 Forced Merge를 수행해 하나의 최적화된 Segment를 만들고, 이를 Apache HDFS나 Google Cloud Storage와 같은 원격 저장소에 업로드합니다.
검색을 담당하는 Searcher는 원격 저장소에 있는 최적화된 인덱스를 가져와 검색 요청을 처리합니다.
이 구조의 핵심은 검색 요청을 처리하는 경로에서 데이터 정리 작업을 제거하는 것입니다.
데이터를 정렬하고 Merge하는 데 필요한 비용은 ingestion 단계에서 부담합니다.
검색 단계에서는 이미 최적화된 인덱스를 사용하기 때문에 데이터 처리 때문에 검색 성능이 영향을 받는 문제를 줄일 수 있습니다.
이것이 LucenePlus 아키텍처의 중요한 특징입니다.
OpenSearch API와 Search Gateway
Uber는 내부 구현을 변경하면서도 기존 사용자가 검색 시스템의 내부 구조를 신경 쓰지 않도록 만들 필요가 있었습니다.
이를 위해 Search Gateway를 구성했습니다.
Search Gateway는 OpenSearch API를 구현하는 역할을 합니다.
데이터 쓰기는 Kafka를 통해 전달되고, 검색 요청은 여러 Backend Searcher 노드로 분산됩니다.
사용자 입장에서는 내부에서 실제로 Sia나 LucenePlus가 사용되는지, 혹은 향후 OpenSearch 기반으로 변경되는지를 알 필요가 없습니다.
항상 안정적인 OpenSearch 호환 API를 사용할 수 있습니다.
이 구조는 Uber가 자체적으로 개발한 LucenePlus 기반 구현을 점진적으로 OpenSearch에 통합할 수 있는 기반도 제공합니다.
즉 클라이언트의 코드 변경을 최소화하면서 내부 검색 플랫폼을 단계적으로 바꿀 수 있습니다.
자체 기술을 오픈소스에 다시 기여하다
Uber의 검색 플랫폼 전략에서 흥미로운 부분은 자체적으로 만든 기술을 다시 커뮤니티에 돌려준다는 점입니다.
Sia와 LucenePlus를 구축하면서 얻은 경험을 기반으로 Uber는 OpenSearch에 여러 기능을 기여하고 있습니다.
대표적인 기능이 Pull-based ingestion과 gRPC API입니다.
이러한 기능은 Uber의 대규모 인프라에서 실제로 필요했던 요구사항에서 출발했습니다.
따라서 단순한 이론적인 기능이 아니라 높은 처리량과 운영 안정성이 필요한 환경에서 얻은 경험을 바탕으로 합니다.
Uber는 여기서 더 나아가 Cloud-native OpenSearch 방향도 추진하고 있습니다.
목표는 기존 검색 클러스터가 가진 확장성의 한계를 줄이고, 작업량에 따라 리소스를 탄력적으로 확장할 수 있는 구조를 만드는 것입니다.
또한 대규모 클러스터에서는 Cluster State 조정이 안정성의 문제가 될 수 있습니다.
Uber는 이 문제를 보다 강력한 외부 Coordinator에 상태 관리와 조정 기능을 맡기는 방식으로 해결하는 방향도 검토하고 있습니다.
궁극적으로는 더 높은 확장성과 장애 대응 능력을 갖춘 검색 플랫폼을 만드는 것이 목표입니다.
앞으로는 AI와 Semantic Search로 확장
Uber의 검색 플랫폼 전략은 OpenSearch로 전환하는 데서 끝나지 않습니다.
앞으로 중요한 영역 중 하나는 Semantic Search입니다.
기존 검색은 사용자가 입력한 단어나 문서의 명시적인 일치 여부가 중요한 경우가 많았습니다.
하지만 AI 기반 검색에서는 단순한 단어 일치를 넘어 사용자의 의도와 문맥을 이해하고 보다 관련성이 높은 결과를 찾는 것이 중요합니다.
Uber 역시 AI 기반 검색 사용 사례가 빠르게 증가하고 있기 때문에 Semantic Search를 중요한 우선순위로 보고 있습니다.
이를 위해 Vector-based Retrieval 기술을 발전시키고 검색 품질을 높이면서도 비용 효율적으로 서비스를 제공하는 방향을 추진하고 있습니다.
특히 OpenSearch에 이미 포함된 머신러닝 관련 기능을 활용하면서 Uber의 실제 서비스에 필요한 새로운 벡터 검색 기술을 개발하고 이를 다시 생태계에 기여하는 방향을 모색하고 있습니다.
검색과 Observability의 통합도 고려한다
Uber가 바라보는 또 하나의 방향은 검색과 Observability의 통합입니다.
대규모 서비스에서는 검색 플랫폼과 함께 시스템의 상태를 관찰하고 문제를 파악하는 Observability 역시 중요합니다.
Uber는 향후 OpenSearch를 검색뿐만 아니라 Observability 스택에도 활용하는 방안을 검토하고 있습니다.
이는 여러 시스템을 별도로 운영하는 대신 하나의 일관된 플랫폼을 활용해 인프라를 단순화하고 운영 효율성을 높이려는 방향으로 볼 수 있습니다.
Uber의 검색 플랫폼 진화가 보여주는 것
Uber의 검색 플랫폼은 Elasticsearch에서 시작해 Sia를 거쳐 OpenSearch 중심의 새로운 전략으로 이동하고 있습니다.
이 과정을 단순한 제품 교체로 이해하면 중요한 의미를 놓칠 수 있습니다.
처음에는 빠르게 성장하는 서비스를 안정적으로 확장하기 위해 Elasticsearch를 사용했습니다.
그러나 실시간성이 중요한 서비스가 등장하면서 기존 기술의 한계를 해결하기 위해 Sia를 직접 개발했습니다.
Sia는 Uber의 요구사항에 맞는 실시간 검색과 대규모 데이터 처리를 가능하게 했지만, 시간이 지나면서 자체 검색 엔진을 유지하는 것 자체가 새로운 부담이 됐습니다.
Lucene에 새로운 기능이 추가될 때마다 Sia에 맞춰 다시 구현해야 했고, 벡터 검색과 같은 AI 관련 기술이 빠르게 발전하면서 이를 따라가는 데 필요한 개발 비용도 증가했습니다.
결국 Uber는 모든 문제를 자체 기술로 해결하는 것이 항상 최선은 아니라는 결론에 도달했습니다.
특히 모든 검색이 실시간성을 필요로 하는 것은 아니었습니다.
실시간성이 필요한 영역은 별도로 최적화하고, NRT로 충분한 검색은 Lucene과 같은 표준 기술을 활용하는 방식으로 구조를 단순화할 수 있었습니다.
그리고 장기적으로는 OpenSearch와 오픈소스 커뮤니티의 힘을 활용하는 방향으로 전략을 전환했습니다.
Uber 검색 플랫폼의 변화는 Elasticsearch → Sia → OpenSearch라는 기술 스택의 변화만을 의미하지 않습니다.
그 안에는 대규모 IT 서비스가 성장하면서 겪게 되는 중요한 기술적 고민이 담겨 있습니다.
처음에는 검증된 오픈소스를 활용하는 것이 빠르고 효율적일 수 있습니다.
하지만 특정 서비스의 요구사항이 매우 강해지면 자체적인 최적화가 필요해질 수 있습니다.
반대로 자체 시스템이 충분히 성장한 이후에는 새로운 기능을 계속 개발하고 빠르게 변화하는 기술 생태계를 따라가는 데 큰 비용이 발생합니다.
Uber가 Sia를 통해 얻은 경험은 바로 이 지점에서 중요한 의미를 가집니다.
직접 만드는 것과 오픈소스를 활용하는 것 중 하나가 항상 정답인 것은 아닙니다.
어떤 기능은 서비스에 반드시 필요한 차별화 영역이므로 직접 개발해야 하지만, 모든 기술을 직접 유지할 필요는 없습니다.
Uber가 Project Sunrise를 통해 선택한 방향은 이러한 경계를 다시 나누는 것입니다.
실시간성이 꼭 필요한 영역은 최적화하고, 일반적인 검색은 표준 기술을 활용하며, 자체적으로 개발한 핵심 기술은 오픈소스 커뮤니티와 공유합니다.
앞으로 검색 플랫폼은 단순한 키워드 검색을 넘어 Vector Retrieval, Semantic Search, AI 기반 검색으로 더욱 발전할 가능성이 큽니다.
이런 환경에서는 특정 시점에 가장 빠른 검색 엔진을 만드는 것만큼이나 새로운 기술을 지속적으로 받아들이고 확장할 수 있는 구조를 만드는 것이 중요합니다.
Uber가 OpenSearch를 선택하고 자체 기술을 다시 커뮤니티에 기여하려는 이유도 여기에 있습니다.
결국 Uber의 검색 플랫폼 진화가 보여주는 가장 큰 시사점은 하나입니다.
대규모 검색 시스템에서 장기적인 경쟁력은 모든 것을 직접 만드는 데 있는 것이 아니라, 직접 최적화해야 할 부분과 오픈소스 생태계의 힘을 활용할 부분을 적절하게 구분하는 데 있습니다.
The Evolution of Uber’s Search Platform
Search is a foundational pillar of Uber’s user experience, directly influencing key aspects of our core business. Whether you’re looking for a meal on Uber Eats or requesting a ride, search is what connects you with the right options—quickly, accurat
www.uber.com

'인공지능' 카테고리의 다른 글
| Seedance 2.5·MiniMax H3 영상 생성 모델 비교, 같은 프롬프트에서 드러난 결과 차이 (0) | 2026.08.07 |
|---|---|
| 100배 저렴한 오픈 모델로 GPT-5.6 Sol 수준의 검색 정확도 구현하기 (0) | 2026.08.07 |
| Qwen3.8-Max, 16일 동안 스스로 코딩했다: 265개 커밋이 보여준 AI 자율 개발의 현재 (0) | 2026.08.07 |
| Muse Code와 Muse Spark 1.2 공개, 장시간 복잡한 개발 작업을 수행하는 AI 코딩 에이전트 (0) | 2026.08.06 |
| Pi의 미니멀리즘이 AI 코딩 하네스의 경쟁력이 되는 이유 (0) | 2026.08.06 |