RedisConf 키노트 데모를 기억하시나요? 기억하고 계시다면, 그 자리에서 공개되었던 소매 애플리케이션 RedisMart가 어떻게 개발되었는지 그 이면의 이야기를 확인해 보시는 것도 좋은 경험이 될 것입니다. 처음 접하시는 분이라면 Yiftach와 Ash의 발표 영상을 먼저 시청해 보시길 권합니다.
이 글은 시리즈의 첫 번째 아티클로, RedisMart 소매 애플리케이션의 핵심 요구사항과 아키텍처를 살펴봅니다. 제품 카탈로그, 분산형 실시간 재고 관리, AI 기반 제품 검색을 어떻게 구현할 수 있는지 소개하고, Redis Enterprise가 이 모든 기능을 어떻게 뒷받침하는지도 함께 다룹니다.
요구사항
소프트웨어 개발에서 늘 그렇듯, 기본적인 요구사항부터 정리해 보겠습니다. 다음은 비공식적으로 작성된 사용자 스토리입니다.
소매 고객으로서
- 다양한 조건(전문 검색, 가격대, 다른 고객의 평점, 패싯 검색 등)을 기반으로 제품을 찾고, 100ms 미만의 엔드투엔드 지연 시간으로 카탈로그와 제품 상세 정보에 빠르게 접근하고 싶습니다. 응답 속도가 느리면 이탈률(bounce rate)이 급격히 상승합니다.
- 제품의 브랜드명을 모르거나, 이전에 구매한 것과 비슷한 제품을 찾고 싶을 때 이미지로 쇼핑하고 싶습니다. 내가 가진 카메라와 유사하거나 외관상 닮은 카메라를 찾을 수 있다면 정말 멋진 일이겠죠.
- 안전한 배송을 받거나, 온라인으로 구매한 후 매장에서 직접 수령하거나 커브사이드 픽업(클릭 앤 컬렉트)을 이용하고 싶습니다.
재고 관리자로서
- 고객에게 최고의 주문 이행(fulfillment) 경험을 제공하기 위해 정확한 실시간 재고 현황이 필요합니다.
- 수요가 높은 상품은 재고를 유지하고, 잘 팔리지 않는 상품의 재고는 줄여 재고를 최적화하고 싶습니다.
- 재고를 최적화하기 위해 여러 매장 및 물류센터에 걸친 재고 현황을 거의 실시간으로 파악해야 합니다.
아키텍처
요구사항을 파악했으니, Redis가 어떻게 도움을 줄 수 있는지 살펴보겠습니다.
- RediSearch는 숫자 필터, 전문 검색, 지리적 인덱싱, 스코어링, 집계 기능을 갖춘 풍부한 제품 검색을 가능하게 합니다.
- Redis Enterprise의 Active-Active 기능은 별도의 추가 작업 없이 지역 간 복제된 실시간 재고 업데이트를 기본적으로 제공합니다.
- RedisAI, RedisGears, RediSearch를 활용하면 데이터베이스에 통합된 머신러닝 파이프라인을 구축하여 실시간 추론과 벡터 유사도 검색을 수행할 수 있습니다.

이를 바탕으로 다음과 같은 설계를 자연스럽게 도출할 수 있었습니다.

파란색 박스는 서비스를, 빨간색 박스는 해당 서비스가 사용하는 데이터베이스를 나타냅니다.
우리는 다음과 같은 마이크로서비스 원칙을 따랐습니다.
- 서비스별 독립 데이터 저장소: 각 서비스는 자체 데이터 저장소를 가지며, 데이터는 서비스 인터페이스를 통해서만 교환됩니다. 다른 서비스의 데이터 저장소에 직접 접근하지 않습니다.
- Polyglot Persistence(폴리글랏 퍼시스턴스): 각 서비스는 요구사항에 가장 적합한 데이터 저장소를 사용합니다. Redis는 모듈들이 제공하는 다양한 기능과 데이터 모델을 조합해 요구사항에 맞는 데이터 저장소를 만들 수 있는 데이터 플랫폼입니다. 빨간색 박스를 Redis와 여러 Redis 모듈로 구현했다는 사실은 놀라운 일이 아니죠.
구현
RedisMart는 웹샵 웹 애플리케이션이 제공하는 사용자 인터페이스를 갖추고 있습니다. 고객용 프런트엔드 UI(소매 웹사이트)와 재고 관리용 백엔드 UI를 모두 제공하며, 애플리케이션은 내부적으로 여러 서비스를 활용합니다.
- 구매(Purchasing): 구매 서비스는 이름 그대로 고객의 구매를 처리합니다.
- 재고(Inventory): 재고 서비스는 현재 재고 수량에 대한 질의에 응답하며, 고객이 상품을 구매하면 수량이 감소합니다. 재고 업데이트는 Redis Enterprise의 Active-Active 기능을 통해 다른 위치의 재고에 거의 실시간으로 복제됩니다. Redis Enterprise는 동시 업데이트 충돌 처리를 위해 CRDT(Conflict-free Replicated Data Types, 충돌 없는 복제 데이터 타입)를 활용하는데, 여기서는 카운터 값 손실을 방지하기 위해 리셋 가능한 양수/음수 카운터 데이터 타입을 사용합니다.
- 제품 카탈로그(Product Catalog): 제품 카탈로그 서비스는 제품 관련 정보를 제공하고 정교한 제품 검색 방법을 제공합니다. RediSearch + RedisJSON 모듈이 배포된 Redis 데이터베이스를 사용하며, RedisJSON 덕분에 제품 상세 정보를 JSON 문서로 직접 저장할 수 있습니다. RediSearch는 JSON 문서를 인덱싱하고 질의하며 전문 검색까지 지원합니다. 또한 Redis Enterprise의 Active-Active 기능을 활용하면 제품 업데이트를 여러 사이트에 손쉽게 전파할 수 있습니다.
- 이미지 인식(Image Recognition): 이미지 인식 서비스는 이미지에 대한 벡터 유사도 검색을 위한 AI 모델 서빙 기능을 제공합니다. RedisGears, RedisAI, RediSearch 모듈이 설치된 Redis 데이터베이스를 사용하며, RedisGears로 데이터 파이프라인을 구축해 데이터가 있는 곳에서 바로 실행할 수 있습니다. RedisAI는 AI 모델 서빙과 추론에 활용되고, RediSearch는 AI 모델의 출력 결과를 기반으로 유사한 이미지를 실제로 검색하는 데 사용됩니다.
앞서 언급했듯이 이 글은 시리즈의 첫 번째 아티클입니다. 각 서비스를 어떻게 구현했는지 자세히 알아보려면 다음 아티클도 기대해 주세요.
RedisMart 둘러보기
무대 뒤 모습을 살펴봤으니, 이제 무대 위의 애플리케이션이 어떤 모습인지 확인해 보겠습니다.

홈 페이지에는 주요 제품 카테고리가 표시됩니다. 카테고리를 클릭하면 제품 카탈로그 서비스를 통해 검색 쿼리가 실행되고, 해당 카테고리에 속한 첫 16개 제품이 반환됩니다.
“제품 검색(Search products)” 입력란에서 제품 전문 검색을 수행할 수 있으며, 검색 시 다음과 같은 결과 페이지로 이동합니다.

검색 결과 페이지는 패싯 검색 영역과 실제 결과 목록 두 부분으로 구성됩니다. 패싯 검색을 활용하면 메인 카테고리, 하위 카테고리, 가격, 평점으로 검색 결과를 더 좁힐 수 있습니다. RediSearch로 이러한 패싯 검색을 구현하는 방법은 시리즈 2편에서 자세히 다룰 예정입니다. 그 전에 RedisMart의 디버그 뷰를 통해 힌트를 드리자면,

보시다시피 태그(tag)와 집계(aggregation)가 중요한 역할을 합니다.
오른쪽 상단의 작은 카메라 아이콘을 클릭하면, 카탈로그에서 찾고 싶은 대상의 사진을 촬영할 수 있습니다. Doug의 사진을 검색했지만 데이터베이스에서 다른 Doug는 찾지 못했습니다…

…하지만 헤드폰은 아주 잘 찾아냈습니다.

이제 헤드폰 한 켤레를 골라 구매하기로 했다고 가정해 보겠습니다. 선택을 마치면 RedisMart는 해당 상품을 장바구니에 담을 수 있게 해주고, 결제 과정에서 배송을 받을지 근처 수령지에서 픽업할지 선택할 수 있습니다.

이 로컬 픽업 기능은 RediSearch의 지리 검색(geo-search)으로 구동됩니다. 디버그 뷰를 보면 이 기능이 내부적으로 어떻게 구현되었는지 힌트를 얻을 수 있습니다.

고객이 구매를 완료하는 순간 재고 서비스가 개입해 재고 수량을 차감합니다. 이제 애플리케이션의 백엔드, 즉 재고를 관리하는 화면으로 넘어가 보겠습니다. RedisMart는 각 복제 사이트에서 즉각적인 재고 업데이트가 어떻게 반영되는지 시각화해 줍니다. 미국(GCP us-central1)에서 발생한 구매는 눈 깜짝할 새에 유럽(Azure north-europe)으로 복제됩니다.

세부 사항은 이후 아티클에서 더 다룰 예정입니다. 여기서 핵심은 가까운 위치에서 매우 낮은 네트워크 지연 시간으로 데이터에 접근할 수 있고, 여러 사이트에서 동시에 데이터가 수정되더라도 카운터 손실이 방지된다는 점입니다.
다음 영상을 통해 애플리케이션이 실제로 작동하는 모습을 확인할 수 있습니다.
마무리
Redis로 완전한 기능의 소매 애플리케이션을 구축하는 블로그 시리즈의 첫 편을 즐겁게 읽으셨기를 바랍니다. 보셨듯이 Redis 실시간 데이터 플랫폼은 RediSearch + RedisJSON의 문서 데이터베이스 기능을 활용해 100ms 미만의 엔드투엔드 지연 시간으로 제품 정보에 즉시 접근하는 요구사항을 충족합니다. RediSearch + RedisGears + RedisAI의 조합은 카탈로그 내 유사 제품을 찾는 AI 기반 이미지 검색을 가능하게 하며, 패싯 검색과 지리 검색 같은 기능도 함께 다루었습니다. 마지막으로 Redis Enterprise의 Active-Active 기능만으로 지역 간 복제되는 실시간 재고 시스템을 손쉽게 구축할 수 있음을 보여드렸습니다. 이 모든 것을 통해 Redis 실시간 플랫폼은 소매 기업이 전반적인 구매 경험을 개선하고, 고객에게 최고의 주문 이행 경험을 제공하며, 가장 비용 효율적인 방식으로 재고를 최적화하는 데 기여합니다.
RedisMart를 위해 구현한 개별 서비스에 대해 더 알고 싶으신가요? 시리즈의 다음 블로그 아티클을 기대해 주세요!
직접 사용해 보고 싶으신가요? Redis를 실시간 데이터 플랫폼으로 경험해 볼 수 있는 링크를 소개합니다.
- Redis 모듈 더 알아보기
- github.com/RediSearch
- github.com/RedisJSON
- github.com/RedisGears
- github.com/RedisAI
- Redis Enterprise Cloud
- Active-Active Geo-Distribution
감사의 글
이 데모 애플리케이션에 기여해 주신 모든 분들께 진심으로 감사드립니다.
- RedisConf에서 데모 애플리케이션을 발표해 주신 Yiftach Shoolman님과 Ash Sahu님
- 데모 애플리케이션 요구사항 목록 작성, RedisConf 기획, UI 디자인 지원, 그리고 이 블로그 포스트 작성에 기여해 주신 Redis 마케팅 팀(특히 Udi Gotlieb, Ash Sahu, Doug Tidwell, Bryson Coles님)
- 데모 애플리케이션의 구현, 테스트, 설계와 이 블로그 포스트 작성에 기여해 주신 Technical Enablement 팀(특히 Martin Forstner, Greg Georges, David Maier님)
- 모듈과 이미지 인식 서비스를 개발해 주신 CTO 팀(특히 Leibale Eidelman, Guy Korland님)
- 데모 애플리케이션 요구사항 목록 작성과 제품 기능 제공에 기여해 주신 Product Management 팀(특히 Pieter Cailliau, Emmanuel Keller, Jonathan Salomon, Amiram Mizne님)
- 그리고 여기서 언급하지 못한 모든 분들
이 블로그 시리즈를 RedisMart 애플리케이션의 주요 개발자였던 Martin Forstner에게 바칩니다. 그가 최근 세상을 떠났다는 소식을 전하게 되어 무척 슬픕니다. Martin의 지식, 재능, 유머 감각은 타의 추종을 불허했습니다. 그는 Redis의 소프트웨어 엔지니어였을 뿐만 아니라 동료이자 팀원, 멘토, 그리고 친구였습니다. 고이 잠드소서, Martin. 당신을 그리워합니다!