Skip to content

KMGeon/hhplus-e-commerce

Repository files navigation

⚓️ 항해플러스 - 이커머스 프로젝트

대용량 트래픽을 견디는 실전 이커머스 플랫폼
_"선착순 쿠폰 이벤트에서 300명이 동시에 몰려도 끄떡없는 시스템"

HH+ 이커머스

🤔 이 프로젝트는 왜 만들어졌나요?

흔히 볼 수 있는 간단한 쇼핑몰이 아닙니다. 실제 서비스에서 겪는 까다로운 문제들을 해결하기 위해 만들어진 프로젝트예요.

  • 💥 선착순 이벤트 때 서버가 터지는 문제 → Redis 분산락과 Kafka로 해결
  • 🐌 상품 조회가 느려지는 문제 → 다층 캐시 전략으로 해결
  • 🔄 재고 동기화 문제 → 이벤트 드리븐 아키텍처로 해결
  • 📊 장애 상황을 모르는 문제 → 모니터링과 알림 시스템으로 해결

⚡ 핵심 특징

🎯 실전 경험: 실제 운영 환경에서 발생하는 문제들을 시뮬레이션
🚀 고성능: 300+ TPS 선착순 쿠폰 발급 처리 가능
🛡️ 안정성: Redis Sentinel 클러스터 + Kafka 클러스터로 무중단 서비스
📈 확장성: MSA 구조로 언제든 서비스 분리 가능
🔍 관찰성: Prometheus 메트릭으로 모든 것을 추적

🏗️ 아키텍처 한눈에 보기

🔥 선착순 쿠폰 시스템

한정 수량 쿠폰을 놓고 수백명이 동시에 요청할 때의 실제 상황을 구현했습니다.

요청 흐름: 사용자 → Spring Boot → Redis 분산락 → 쿠폰 차감 → Kafka 이벤트

🎯 기술 스택

Backend

  • Spring Boot 3.4.1 (Java 17)
  • JPA + QueryDSL (복잡한 쿼리 최적화)
  • Redis Sentinel (캐시 + 분산락)
  • Kafka Cluster (이벤트 스트리밍)
  • MySQL 8.0 (메인 데이터)

Infrastructure

  • Docker Compose (로컬 개발)
  • HAProxy (로드밸런싱)
  • Prometheus (메트릭 수집)
  • K6 (성능 테스트)

🚀 3분만에 실행하기

# 1️⃣ 저장소 클론
git clone [repository-url]
cd hhplus

# 2️⃣ 인프라 전체 실행 (MySQL, Redis, Kafka 등)
docker-compose up -d

# 3️⃣ 애플리케이션 실행
./gradlew bootRun

# 4️⃣ 브라우저에서 확인
# API 문서: http://localhost:8080/swagger-ui.html
# Kafka UI: http://localhost:8081
# Redis 모니터링: http://localhost:9000

💡 Tip: 초기 데이터가 필요하면 python dataInit.py 실행

🎮 실제로 해볼 수 있는 것들

1. 🔥 선착순 쿠폰 스트레스 테스트

# K6로 실제 부하 테스트 실행
k6 run k6/couponPublish_spike.js

# 결과: 300+ TPS에서도 정확한 쿠폰 발급

2. 📊 실시간 성능 모니터링

  • Actuator: localhost:8080/actuator - JVM 메트릭, 헬스체크
  • Kafka UI: localhost:8081 - 메시지 흐름 실시간 확인
  • Redis Stats: HAProxy 통해 Redis 클러스터 상태 확인

3. 🔍 장애 시뮬레이션

# Redis Master 장애 상황 테스트
docker stop redis-master
# → Sentinel이 자동으로 Slave를 Master로 승격

# Kafka 브로커 장애 테스트  
docker stop kafka1
# → 다른 브로커들이 파티션을 자동으로 리밸런싱

📋 주요 API 둘러보기

🎫 쿠폰 발급 (핵심 기능!)

curl -X POST localhost:8080/api/v1/coupon/publish \
  -H "Content-Type: application/json" \
  -d '{"userId": 1, "couponId": 1}'

🛒 주문 생성

curl -X POST localhost:8080/api/v1/order \
  -H "Content-Type: application/json" \
  -d '{
    "userId": 1,
    "items": [{"productId": 1, "quantity": 2}]
  }'

💳 결제 처리 (쿠폰 할인 적용)

curl -X POST localhost:8080/api/v1/payment \
  -H "Content-Type: application/json" \
  -d '{
    "orderId": 1,
    "couponId": 1
  }'

🔧 개발 이야기

😅 동시성 지옥에서 탈출하기

  • 동시성에 대해서 처리하는 다양한 방식을 배울 수 있었습니다. 처음에는 단순히 애플리케이션 공유자원을 사용을 하였을 때 synchronized, ReentrantLock을 통해서 문제를 해결할 수 있었고

  • 이후에 DB의 동시성 문제의 경우에는 다양한 트랜잭션 격리수준 + 비관적, 낙관적 락, 네임드 락을 통해서 문제를 해결할 수 있었습니다.

  • 하지만 분산 환경에서의 동시성 문제는 DB의 락만으로 처리하면 안된다고 이해했습니다. 이때 Redis의 분산락에 대해서 학습을 하였습니다.

    • Redis 분산락의 사용하는 이유는 동시성의 문제를 인메모리로 빠른 장점이 있기도 하지만 가장 큰 이유는 DB의 부화를 분산을 하는데 있습니다.

🐌 캐시 전략의 진화

  • 1단계: 단순 Redis 캐시 → TTL 관리가 어려움
  • 2단계: Cache-Aside 패턴 → 캐시 무효화 타이밍 문제
  • 3단계: 이벤트 기반 캐시 갱신 → 지금 상태 (안정적!)

📊 모니터링의 중요성 깨닫기

장애가 발생했을 때 원인을 찾느라 밤새 코드를 뒤지던 경험이 있어서, 이번엔 처음부터 Actuator + Prometheus로 모든 지표를 수집하도록 했어요. 덕분에 병목 지점을 바로 찾을 수 있게 됐습니다.

🤖 이벤트 드리븐 아키텍처 깨달음

  • 이번 프로젝트에서 가장 재미있었던 부분은 이벤트에 대해서 학습한 것이다. 이벤트를 생각하면 이전에는 제일 먼저 Kafka에 대해서 생각을 했는데, 가장 중요한 개념은 이벤트 그 자체였다는 걸 깨달았다.

🚨 대용량 트래픽에서 이벤트를 사용하는 이유

  • 우리는 쓰기 작업의 경우에는 명확한 한계가 존재한다. 왜냐하면 우리는 DB를 사용하기 때문이다. WAS의 스케일 아웃으로 수많은 요청을 받을 수 있게 되더라도, 결국 모든 요청이 DB에 긴 트랜잭션을 요구하면 락 경합과 성능 저하의 문제가 발생할 수밖에 없다. 특히 주문, 결제, 재고 관리 같은 핵심 비즈니스 로직이 하나의 트랜잭션에 묶여있으면 DB가 병목 지점이 된다.

  • 이벤트를 통해 이 문제를 해결할 수 있다. 요청을 받는 부분과 실제 처리하는 부분을 완전히 분리해서 처리량을 조절할 수 있게 된다. 사용자에게는 빠른 응답을 주고, 무거운 작업들은 백그라운드에서 자기 페이스대로 처리하는 구조다. 이렇게 시스템의 책임을 분리하고 느슨하게 결합시키는 것이 바로 이벤트라는 개념의 핵심이다.

⚡ 카프카: 이벤트의 이점을 극대화하는 도구

  • 카프카는 이러한 이벤트의 이점을 극대화하기 위한 도구라고 생각한다. 단순히 메시지를 전달하는 것을 넘어서, 카프카는 이벤트를 안정적으로 전달하고, 내구성을 보장하며, 수평 확장이 용이한 구조로 설계되어 있다. 특히 대용량 환경에서 이벤트 기반 아키텍처를 구현할 때 필수적인 기능들을 제공한다. 카프카의 핵심 장점들:
  1. 영속화: 디스크에 저장되어 서버가 재시작되어도 이벤트가 유실되지 않는다
  2. 다중 컨슈머: 서로 다른 컨슈머가 동일한 메시지에 대해서 각자 자기 작업만 처리할 수 있다
  3. 독립적 처리: 각 컨슈머가 자기 페이스로 일할 수 있어서 하나의 서비스 장애가 다른 서비스에 영향을 주지 않는다
  4. 순서 보장: 파티션 내에서 메시지 순서가 보장되어 데이터 일관성을 유지할 수 있다

📚 설계 문서 & 트러블슈팅

더 깊이 알고 싶다면 이 문서들을 읽어보세요:

🎯 시스템 설계

⚡ 성능 최적화 보고서

🚨 운영 경험

🧪 테스트는 어떻게?

# 단위 테스트 실행
./gradlew test

# 성능 테스트
 k6 run \
 --out influxdb=http://localhost:8086/myk6db \
 couponPublish_spike.js

# 전체 시스템 헬스체크
curl localhost:8080/actuator/health

⚡ 이 프로젝트로 배운 것들

  • 대용량 트래픽 처리를 위한 시스템 설계
  • 분산 환경에서의 데이터 일관성 관리
  • 모니터링과 장애 대응의 중요성
  • 성능 테스트와 튜닝의 필요성

About

대용량 트래픽 이커머스

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •