핵심요약
Gmarket 모바일 웹 상품 상세 페이지의 실시간 조회자 수 기능 구현을 위해 Redis와 MongoDB의 다양한 자료구조 설계를 비교 분석하고 성능 및 유지보수 측면의 장단점을 상세히 탐구한 글입니다. 실시간 사용자 집계의 효율성과 데이터 일관성을 최적화하는 방안을 중점적으로 다룹니다.
상품 상세 페이지 실시간 조회자 수 기능 구현 설계
기능 요구사항 및 초기 접근
- 실시간으로 중복 없는 사용자의 상품 조회 수를 집계 및 표시하는 기능 구현을 목표로 합니다.
- 사용자가 상품 상세 페이지에 접속 시
상품 번호와사용자 인식 정보를 저장하고, 이탈 시 해당 정보를 제거하는 프로세스를 가집니다. - 대규모 트래픽과 실시간 집계 요구사항을 고려하여 NoSQL 데이터베이스 기반의 설계를 검토했습니다.
Redis 기반 자료구조 설계 및 분석
- Redis는 인-메모리(In-memory) 기반의 고성능 Key-Value 저장소로, 빠른 처리 속도가 장점입니다.
- Set 자료구조: 단순히 사용하면 브라우저 이탈 감지 실패 시 데이터가 영구히 남아 정확성 문제를 야기합니다.
- Set + ExpireTime: 키 단위 만료는 가능하나, 개별 사용자 이탈 감지에 부적합하여 오차가 크다는 단점이 있습니다.
- Set X Hash: 배치 작업을 통해 이탈 사용자를 제거할 경우, Hash 필드 수에 비례하는 O(N) 시간 복잡도로 Redis 및 애플리케이션에 부하를 줄 수 있습니다.
- Sorted Set (최종 선택):
상품번호를 Key,사용자 인식 정보를 Value,현재 시간을 Score로 저장합니다.ZADD명령어로 upsert 시 O(log N),ZCARD로 조회자 수 집계 시 O(1) 성능을 보이며,ZREMRANGEBYSCORE를 활용해 만료된 사용자 정보를 효율적으로 제거할 수 있습니다.
MongoDB 기반 자료구조 설계 및 분석
- MongoDB는 Document-oriented NoSQL 데이터베이스로, 유연한 스키마, 고가용성, 확장성을 제공합니다.
- Collection Structure 1 (Separate Documents):
itemNo,loginId,timestamp를 개별 문서로 저장하고,itemNo에 **인덱스(O(log N))**를,timestamp에 TTL(Time-To-Live) 인덱스를 설정하여 자동 만료를 구현합니다. - Collection Structure 2 (Embedded Array):
itemNo문서 내users배열에loginId와timestamp를 저장하는 방식으로, 배열 업데이트는 **O(1)**입니다. 그러나 인기 상품의 경우users배열의 무한 성장 및 데이터 양 증대 문제가 발생하며, 결국 배치 작업을 통한 배열 내 이탈 사용자 제거가 필요하여 성능 오버헤드가 발생할 수 있습니다.
결론 및 최적화 고려사항
- Redis는 인-메모리 특성상 실시간 성능이 우수하지만 비용이 높은 단점이 있습니다.
- MongoDB는 TTL 인덱스를 통해 유지보수 간편성을 제공하지만, 만료 정확성 및 잠재적 성능 저하 가능성이 존재합니다.
- 최종적으로
Sorted Set을 활용한 Redis가 현재 기능 요구사항에는 가장 적합하다고 판단되었으나, 각 데이터베이스의 장단점을 면밀히 검토하여 비용과 성능 간의 트레이드오프를 고려해야 합니다.