피드로 돌아가기
컬리 기술블로그Backend
원문 읽기
카트 개발 연대기
마켓컬리의 카트 도메인이 4세대 진화를 거쳐 다중 세션의 카트 경합 문제를 카트 아이템 공유 구조로 해결
AI 요약
Context
카트는 기존에 1개의 row를 여러 세션이 동시에 접근하려면서 데드락이 발생했다. 비회원은 1세션 1카트지만 회원은 n개 세션에서 1개 카트만 유지하려는 Clean Up 정책 때문에 다중 플랫폼 동시 로그인 시 카트 간 경합이 발생했다. 또한 물류센터 확장에 따른 지역 기반 재고 관리 필요성이 있었고, 기존 트리 구조에서 선형 구조로의 마이그레이션 또한 필요했다.
Technical Solution
- 1세대 Legacy Cart: Controller의 3,000줄 코드를 Service 단위로 분해 및 Manager Pattern 도입, Eager Loading으로 N+1 쿼리 문제 해결
- 2세대 Stack Cart: Dual Write 패턴으로 구 카트(트리 구조)와 신규 카트(선형 구조)에 동시 적재하여 데이터 마이그레이션 준비 시도 → 데드락 심화로 2주 만에 롤백 불가능 상황 발생
- 3세대 Modern Cart: Stack Cart 기반 코드 리팩토링으로 배포, 주문서 진입 전에 구 카트로 부분 마이그레이션하는 방식 채택, 데드락 감소하나 고트래픽 시 성능 저하 지속
- 4세대 Multi Cart: Cart Item을 공유 구조로 변경하여 n개 카트가 같은 상품 아이템을 참조, cart_id 대신 cart_item.id 기반으로 추가/수정/삭제/조회 로직 리팩토링, 100원딜 상품 검증 쿼리 최적화
- 주소 기반 물류센터 조회: TAM 시스템으로 사용자 주소 기반 cluster center code 추출, 해당 물류센터의 vsms(가상 재고), dsms(전시 관리), 할인 API 조회
Impact
아티클에서 정량적 수치가 제시되지 않음
Key Takeaway
다중 세션이 동일 리소스 경합 시 한 쪽을 우선순위로 정해 억압하는 구조보다 리소스를 공유하고 쿼리 복잡도를 수용하는 설계가 근본적인 장애 원인을 제거할 수 있다. 마이그레이션 전략에서 Dual Write는 동시성 제어 문제가 해결되지 않으면 기존 문제를 가중시킬 수 있으므로, API 규격 변경이 강제 업데이트를 요구하는 상황에서는 단계적 롤백 가능성을 먼저 확보해야 한다.
실천 포인트
동일 계정의 다중 플랫폼 접근이 가능한 서비스에서 세션별 독립 리소스 설계로 인한 데드락이 발생 시, 리소스를 공유 구조로 전환하되 기본 키를 row id에서 item id 기반으로 변경하고 조회 쿼리에 group by 및 sum을 도입하면 경합을 완전히 제거할 수 있다.