Skip to content

TreeStone94/shop-api

Repository files navigation

shop-api

🚀 과제명: "0.1초의 전쟁, 한정판 스니커즈 타임세일"

이 과제는 **'재고 100개'**라는 한정된 자원을 두고 **'초당 1,000명 이상의 사용자'**가 동시에 달려들 때, 어떻게 데이터 오차 없이 정확히 100명에게만 판매할 것인지를 해결하는 것이 목표입니다.

📅 1단계: 동시성 지옥 맛보기 (Basic)

가장 먼저 '아무런 조치도 하지 않은' 상태에서 문제가 발생하는 것을 확인합니다.

  • 미션: 상품 재고 조회 -> 재고 -1 -> 주문 생성 로직을 구현합니다.
  • 검증: JMeter나 Gatling 같은 도구로 100개의 스레드가 동시에 요청을 보내게 합니다.
  • 결과 확인: 분명 재고는 10개인데, DB를 열어보니 주문은 10개보다 더 많이 생성되어 있고 재고는 음수가 되어 있는 'Race Condition'을 직접 목격해 보세요.

🔒 2단계: 데이터베이스 수준의 해결 (Intermediate)

DB의 기능을 이용해 문제를 해결해 봅니다. 두 방식의 성능 차이를 체감하는 것이 핵심입니다.

  • 미션 A (Pessimistic Lock): SELECT ... FOR UPDATE를 사용하여 데이터에 물리적인 락을 겁니다. (줄 세우기)
  • 미션 B (Optimistic Lock): 데이터에 version 컬럼을 추가하여, 수정할 때 내가 읽은 버전이 맞는지 확인합니다. (충돌 시 재시도 로직 필요)
  • 고민 포인트: 사용자가 많아질수록 어떤 방식이 더 느려질까요? 타임아웃 처리는 어떻게 할까요?

⚡ 3단계: 분산 환경에서의 해결 (Advanced)

서버가 2대 이상으로 늘어나는 '분산 환경'을 가정합니다. 이제 Java의 synchronized나 단순한 DB 락만으로는 부족합니다.

  • 미션: Redis를 활용한 **분산 락(Distributed Lock)**을 구현합니다. (Redisson 라이브러리 추천)
  • 특징: DB까지 요청이 가기 전에 Redis 단계에서 락을 획득하게 하여 DB 부하를 획기적으로 줄여봅니다.
  • 고민 포인트: 락을 획득하지 못한 사용자는 계속 대기해야 할까요? 아니면 바로 "실패"를 알려줘야 할까요?

🏗️ 4단계: 비동기와 대기열 (Expert)

실제 대형 이커머스(쿠팡, 무신사 등)가 사용하는 방식입니다.

  • 미션: KafkaRabbitMQ 같은 메시지 큐를 도입합니다.
  • 로직: 사용자가 '구매'를 누르면 즉시 DB에 쓰는 게 아니라, **'대기열'**에 집어넣습니다. 백엔드 워커가 순차적으로 큐에서 꺼내 재고를 차감합니다.
  • 결과: 사용자에게는 "대기 중입니다"라는 메시지를 보여주고, 서버는 폭주하지 않고 안정적으로 주문을 처리합니다.

🛠️ 추천 스택 및 도구

  • Language: Java (Spring Boot) or Kotlin
  • Database: MySQL (InnoDB)
  • Cache/Lock: Redis
  • Stress Test: JMeter (강력 추천), K6, Locust

💡 이 과제를 통해 얻게 될 인사이트

  1. 재고 부족(Overselling) 방지 로직 설계 능력.
  2. Lock의 범위에 따른 성능 오버헤드 이해.
  3. 멱등성(Idempotency): 네트워크 오류로 같은 요청이 두 번 와도 한 번만 처리되는 설계.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages