Skip to content

f-lab-edu/b-ticketing

Repository files navigation

B-Ticketing

야구 티켓 예매 시스템을 개발하는 프로젝트입니다.

📅 프로젝트 기간

  • **2024-10 ~**

📌 주제 선정 이유

  1. 실제 예매 사이트 사용 경험

    • 티켓 예매 사이트는 쇼핑몰 외에 가장 자주 이용하는 서비스입니다.
    • 특히, 야구 경기를 자주 관람하며 대기열과 좌석 자동 예매의 불편함을 직접 경험하였고, 이를 직접 구현해 보고자 프로젝트를 시작했습니다.
  2. 대규모 트래픽 환경에 대한 학습

    • 티켓팅 오픈 시 수만 명의 사용자가 동시에 몰리는 환경에서, 서버가 어떻게 동작하는지 원리를 이해하고 싶었습니다.
    • 동시 접속자가 많을 때 발생하는 성능 문제를 해결하는 방법을 학습하고 적용해 보고자 하였습니다.
  3. 예매 시스템의 특수성

    • 일반적인 이커머스 시스템과는 다르게, 예매 시스템은 실시간 대기열, 좌석 배정, 결제 시스템이 밀접하게 연관되어 있습니다.
    • 이러한 특수한 기능을 직접 구현하며 개발 역량을 키우기 위해 프로젝트를 기획하였습니다.

🔍 중점을 둔 부분

  • 대규모 트래픽을 고려한 대기열 처리
  • 많은 사용자가 동시 접근할 수 있는 좌석 예매 로직
  • 비동기 결제 시스템을 통한 성능 최적화

🛠️ 사용 기술 및 환경

  • Backend: Spring Boot, Java, JPA
  • Database: MySQL
  • Caching & Messaging: Redis, Kafka
  • Containerization: Docker
  • CI/CD 및 배포: Docker Compose, AWS (예정)

🚀 기능 구현

1️⃣ 대기열 시스템

1) 대기열(Queue) 관리 기능

  • 사용자가 티켓 예매 페이지에 접근하면 자동으로 대기열에 추가됨.
  • 대기열은 120명 단위의 그룹으로 관리되며, 그룹별로 순차적으로 예매 시스템에 접근 가능.
  • 대기열에서 벗어날 수 있는 상태가 되면 클라이언트가 이를 확인 가능.

2) 대기열 상태 확인 및 업데이트

  • 사용자의 대기 상태를 확인하는 Polling API 제공.
  • 대기열 상태는 Redis에 저장되며, 일정 시간이 지나면 자동으로 업데이트됨.
  • 클라이언트는 /queue/status API를 통해 주기적으로 상태를 확인하고, 대기열에서 벗어나면 예매 페이지로 리다이렉트됨.

3) 대기열 그룹 처리 및 동시성 관리

  • Redis 기반의 대기열 데이터 관리
    • List 자료구조를 활용하여 순차적으로 사용자 처리.
    • 대기열 그룹을 120명 단위로 나누어 저장하여 효율적인 관리 가능.
  • AtomicInteger + Redis를 활용한 동기화
    • 여러 사용자가 동시에 대기열에 진입할 때 현재 그룹을 동기화하여 데이터 일관성 유지.

4) 락(Lock) 기반의 대기열 접근 제어

  • 여러 사용자가 동일한 대기열 그룹에 접근할 경우, Sharded Lock을 활용하여 충돌 방지.
  • acquireLockWithSharding 메서드를 통해 그룹별로 락을 부여하고, 순차적인 작업 수행을 보장.
  • Redis의 TTL(Time To Live) 설정을 통해 락이 자동 해제되도록 처리.

5) 사용자 리다이렉트 처리

  • 사용자가 대기열을 벗어나면 자동으로 좌석 선택 페이지로 이동할 수 있도록 상태 업데이트.
  • Redis에 저장된 대기열 상태를 기반으로, 이동 가능하면 클라이언트에서 "/seats/sections" URL을 반환받음.

2️⃣ 좌석 예매 시스템

1) 수동 좌석 예매

  • 사용자가 특정 좌석을 직접 선택 가능.
  • 선택한 좌석이 이미 예약된 좌석인지 확인 후, 예약 가능하면 "RESERVED" 상태로 변경.
  • 좌석 예약 데이터는 Redis와 MySQL을 동기화하여 관리.

2) 자동 좌석 배정 기능

  • 사용자가 직접 좌석을 선택하지 않고, 자동 좌석 배정 기능 제공.
  • 연속된 좌석을 우선 배정하며, 부족할 경우 같은 행 내 다른 좌석을 검색.
  • 예약 가능한 좌석이 없으면 새로운 좌석을 생성하여 배정.
  • 좌석 데이터는 Redis에서 우선 조회 후, 필요 시 DB에서 추가 조회하여 성능 최적화.

3) Redis 기반 좌석 상태 관리

  • 좌석 상태를 Redis에 캐싱하여 성능 최적화.
  • 예약된 좌석은 seat:<scheduleId>:<seatId> 키로 Redis에 저장.
  • 좌석 데이터 조회 시 우선적으로 Redis에서 확인 후, 필요 시 DB에서 조회하여 성능 개선.
  • **TTL(시간 제한)**을 적용하여 일정 시간이 지나면 좌석이 자동 해제되도록 설계.

4) 동시성 문제 해결을 위한 락(Lock) 관리

  • Redis 기반의 분산 락을 활용하여 동일 좌석이 동시에 예약되는 문제 방지.
  • acquireLock 메서드를 통해 좌석 선택 시 락을 획득하여 다른 사용자가 동일 좌석을 예약하지 못하도록 설정.
  • 좌석이 예약되면 **비동기 방식(CompletableFuture)**으로 상태 업데이트하여 성능 최적화.

3️⃣ 결제 시스템

1) 결제 요청 및 처리

  • 사용자가 좌석을 예약한 후 결제를 요청하면, Kafka를 통해 비동기적으로 결제 프로세스 진행.
  • 결제 요청 시, **결제 요청 ID(requestId)**를 생성하여 Redis에 저장하며, 초기 상태는 "PENDING"으로 설정.
  • Kafka 이벤트가 처리되면서 결제 상태가 "COMPLETED" 또는 "FAILED"로 업데이트됨.

2) Kafka 기반의 비동기 결제 시스템

  • Kafka를 활용하여 비동기 결제 시스템을 구현하여 성능 최적화.
  • 결제 요청(Payment Requested) → Kafka Producer → Kafka Consumer → 결제 처리(Payment Processed) → 결제 완료(Payment Completed) 방식으로 처리.
  • 결제 완료 이벤트는 이메일 알림 서비스로 전달되어 고객에게 결제 완료 이메일을 자동으로 발송.

3) Redis 기반 결제 상태 관리

  • 결제 요청 상태를 Redis에 저장하여 Polling 방식으로 상태 확인 가능.
  • 결제 요청이 들어오면 payment:status:<requestId> 키로 "PENDING" 상태 저장.
  • Kafka에서 결제 처리가 완료되면 결제 상태를 "COMPLETED" 또는 "FAILED"로 업데이트.
  • 사용자는 /payments/{requestId}/status API를 호출하여 실시간으로 결제 상태 확인 가능.

4) 결제 실패 시 롤백 처리

  • 결제 과정에서 오류 발생 시, 결제 상태를 "FAILED"로 변경하고 예약된 좌석을 다시 “AVAILABLE”로 복구.
  • Redis에 저장된 결제 메시지도 "결제 실패: <오류 메시지>"로 업데이트됨.

5) 이메일 알림 시스템 연동

  • 결제가 완료되면 Kafka 이벤트가 “payment-completed” 토픽으로 전송.
  • 이메일 알림 서비스(EmailNotificationEventListener)가 이를 감지하고 사용자 이메일로 결제 완료 알림 발송.
  • 이메일 내용에는 결제 금액, 예약 번호 등의 정보 포함.

About

야구경기 예매 시스템

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages