멀티 모듈 마이크로서비스 기반 이커머스 플랫폼. 상품 관리, 주문 처리, 재고 관리, 배송, 결제, 검색까지 전체 이커머스 도메인을 8개 모듈로 분리하고, 메시지 기반 비동기 통신으로 모듈 간 결합도를 최소화.
도메인별 모듈 분리로 독립적 개발·배포·테스트가 가능한 마이크로서비스 모노레포
상품 CRUD, 카테고리, 브랜드 관리
주문 생성, 결제, 상태 관리
회원, OAuth2 (카카오/네이버)
재고 관리, Redisson 분산 락
배송 생성, 추적, 상태 관리
JWT, OAuth2, 인증/인가
Selenium 쿠팡 상품 크롤링
공통 DTO, 예외, 유틸리티
동시성 제어, 검색 엔진, 메시징 전략까지 — 이커머스의 핵심 기술 과제 해결
다수 사용자의 동시 주문 시 상품별 재고 차감의 원자성 보장. 락 키를 정렬된 순서로 획득하여 데드락 방지. DB 비관적 락 대비 DB 부하 분산.
Nori 형태소 분석기로 한국어 자연어 검색. combinedField copy_to 패턴으로 상품명/설명/브랜드 통합 검색. 자동완성 + 유사 상품 추천(MLT).
판매 수량을 Redis HINCRBY로 실시간 집계 → 60초 배치로 ES Painless 스크립트 업데이트. ES 쓰기 부하 60배 감소.
도메인 이벤트(주문→재고, 결제→배송)는 RabbitMQ로 안정성 확보. 검색 인덱스/인기도 집계는 Redis Streams로 저지연 처리.
OpenFeign 기반 모듈 간 동기 호출에 Circuit Breaker 적용. 장애 전파 차단 + fallback 응답으로 부분 장애 격리.
주문 이벤트 발생 시 RabbitMQ를 통해 Redis에 판매 수량을 원자적으로 집계(HINCRBY). 60초 주기로 누적된 변경분을 배치 플러시하여 ElasticSearch의 salesCount를 Painless 스크립트로 업데이트. 건별 실시간 쓰기 대비 ES 쓰기 부하 60배 감소.
8개 도메인 모듈(product, order, member, stock, shipment, auth, crawler) + common 모듈. 공통 DTO/예외/유틸리티를 common에 집중하여 코드 중복 제거. 단일 빌드 파이프라인으로 의존성 버전 통합 관리.
:product · :order · :stock · :shipment · :auth · :member · :crawler · :common주문에 포함된 N개 상품의 재고를 동시에 차감할 때 정합성 보장. 상품 ID 기준 정렬로 락 획득 순서를 고정하여 데드락 방지. DB 비관적 락 대비 데이터베이스 부하 분산.
lock:stock:{productId} · sorted acquisition · Redisson fairLockNori 한국어 분석기 + combinedField copy_to 패턴으로 상품명/설명/브랜드를 단일 필드로 통합 검색. prefix query 자동완성, More-Like-This 유사 상품 추천, 관리자 교차 엔티티 검색(4개 인덱스). TLS/JKS 보안 연결.
nori_tokenizer · combined_field · more_like_this · 4 indicesRabbitMQ: 주문생성→재고차감, 결제완료→배송생성 등 도메인 이벤트 (메시지 유실 불가). Redis Streams: 검색 인덱스 업데이트, 인기도 집계 등 (저지연 우선, 유실 허용). 동기 호출은 OpenFeign + Circuit Breaker로 장애 전파 차단.
RabbitMQ exchanges · Redis XADD/XREAD · Resilience4j circuitBreaker멀티 레포 대비 공통 모듈 공유가 용이하고 단일 빌드 파이프라인으로 의존성 버전 통합 관리. 초기 개발 속도와 리팩토링 편의성 확보. 추후 각 모듈을 독립 서비스로 분리할 수 있는 구조.
DB 비관적 락은 커넥션을 오래 점유하여 DB 부하 유발. Redisson 분산 락은 Redis 기반으로 부하를 분산하고, MultiLock은 N개 상품 락을 정렬 순서로 획득하여 데드락을 원천 차단.
주문마다 ES를 직접 업데이트하면 쓰기 부하가 검색 성능을 저해. Redis HINCRBY로 원자적 집계 후 60초 배치로 ES에 반영하여 쓰기 부하 60배 감소. 실시간성은 60초 지연으로 충분.
단일 브로커는 모든 요구사항을 최적으로 충족하기 어려움. 주문/결제 같은 핵심 이벤트는 RabbitMQ의 메시지 보장, 검색/집계 같은 보조 이벤트는 Redis Streams의 저지연으로 역할 분리.
필드별 개별 검색은 쿼리 복잡도가 높고 관련성 스코어 통합이 어려움. copy_to로 상품명/설명/브랜드를 combined_field에 통합하여 단일 쿼리로 복합 검색 + 통합 스코어링.
여러 사용자가 동시에 N개 상품을 포함한 주문을 할 때, 상품별 재고 차감이 원자적이지 않으면 재고가 음수로 내려감. 단순 분산 락은 다중 상품 주문 시 데드락 위험 — 사용자 A가 상품 1→2 순서, 사용자 B가 상품 2→1 순서로 락을 잡으면 교착 상태 발생.
1단계 DB 비관적 락 검토 → 커넥션 장시간 점유로 동시성 높을 때 커넥션 풀 고갈 위험. 2단계 Redisson 단일 락 → 상품별로는 해결되지만 다중 상품 주문 시 데드락 미해결. 3단계 락 획득 순서를 고정하면 데드락이 원천 차단된다는 점에 착안.
Redisson MultiLock + 상품 ID 정렬 전략. 주문 내 모든 상품 ID를 오름차순 정렬 → 정렬된 순서로 lock:stock:{productId} 획득 → 전체 재고 차감 → 역순 해제. 모든 스레드가 동일 순서로 락을 잡으므로 데드락 원천 차단.
동시 주문 환경에서 재고 정합성 100% 보장 + 데드락 제로. DB 커넥션 부하를 Redis로 분산하여 DB 비관적 락 대비 커넥션 점유 시간 대폭 감소. 추후 인스턴스 확장에도 Redis 기반이라 스케일링에 안전.
상품 검색 결과에 판매 수량(인기도)을 실시간 반영하고 싶지만, 주문 발생마다 ElasticSearch를 직접 업데이트하면 쓰기 부하가 검색 쿼리 성능을 저해. 특히 세일/이벤트 시 주문 폭증 → ES 쓰기 폭증 → 검색 응답 지연이라는 cascading failure 위험.
방안 1 ES 직접 업데이트 → 쓰기 부하가 검색과 경합, 세일 시 장애 위험. 방안 2 Cron 배치 (1시간) → 인기도 반영이 너무 늦음. 방안 3 쓰기 버퍼 패턴 — Redis에서 원자적 집계 후 짧은 주기로 배치 플러시. "60초 이내 반영이면 사용자 체감상 실시간"이라는 판단.
RabbitMQ → Redis HINCRBY → 60초 배치 → ES Painless. 주문 이벤트를 RabbitMQ로 수신 → Redis HINCRBY product:sales:{id}로 원자적 집계 (N건의 주문이 1개의 카운터에 누적) → 60초 스케줄러가 변경분을 ES Painless 스크립트로 salesCount에 delta 적용 후 Redis 키 삭제.
ES 쓰기 부하 60배 감소 (건별 → 60초 배치). 검색 쿼리 성능과 인기도 반영을 모두 확보. 세일/이벤트 트래픽 폭증에도 Redis가 쓰기를 흡수하여 ES 안정성 보호. 60초 지연은 사용자 체감상 무시 가능한 수준.