No description
Find a file
2026-06-10 00:19:35 +09:00
gradle/wrapper init 2026-06-09 07:11:55 +09:00
src feat: implement reservation MVP backend 2026-06-09 23:48:38 +09:00
.dockerignore build: add Docker and Compose setup 2026-06-09 07:49:36 +09:00
.gitattributes init 2026-06-09 07:11:55 +09:00
.gitignore init 2026-06-09 07:11:55 +09:00
build.gradle deps: add spring-boot-starter-security-oauth2-resource-server 2026-06-09 07:38:25 +09:00
compose.yml build: add Docker and Compose setup 2026-06-09 07:49:36 +09:00
Dockerfile build: add Docker and Compose setup 2026-06-09 07:49:36 +09:00
gradlew init 2026-06-09 07:11:55 +09:00
gradlew.bat init 2026-06-09 07:11:55 +09:00
README.md docs: add README with API spec, schema diagram, and concurrency design 2026-06-10 00:19:35 +09:00
settings.gradle init 2026-06-09 07:11:55 +09:00

reservation-demo

공연 예약을 위한 Spring Boot 백엔드 API입니다. 주최사의 공연 등록, 회차별 좌석 재고 관리, 사용자 예약 및 취소 기능을 제공합니다.

Runtime, Library

  • Java 21
  • Spring Boot 4
  • Spring Data JPA
  • Spring Security + JWT
  • MySQL 8
  • Flyway
  • SpringDoc OpenAPI
  • Testcontainers

패키지 구조

com.reservation.demo
├── api/
│   ├── auth/
│   ├── concert/
│   ├── organizer/
│   └── reservation/
├── config/         # 설정
├── domain/         # JPA Entity, Enum
│   ├── concert/
│   ├── reservation/
│   ├── seat/
│   └── user/
├── repository/     # Spring JPA
├── service/        # 비즈니스 로직
└── common/         # 예외 처리, Security 유틸

API

Method URL 권한 설명
POST /api/v1/auth/signup Public 회원가입
POST /api/v1/auth/login Public 로그인
GET /api/v1/concerts Public 공연 목록
GET /api/v1/concerts/{concertId} Public 공연 상세
GET /api/v1/concerts/performances/{performanceId}/seats Public 좌석 맵
POST /api/v1/organizer/concerts ORGANIZER 공연 등록
POST /api/v1/reservations USER 예약 생성
POST /api/v1/reservations/{id}/cancel USER 예약 취소
GET /api/v1/reservations/me USER 내 예약 목록

스키마

테이블명은 DB 그대로이며, 선 위 한글은 관계 설명용입니다 (코드/컬럼명 아님).

erDiagram
    users ||--o{ concerts : "주최"
    users ||--o{ reservations : "예약"
    concerts ||--o{ performances : "회차"
    concerts ||--o{ seats : "좌석 정의"
    performances ||--o{ seat_inventories : "회차별 재고"
    seats ||--o{ seat_inventories : "좌석 매핑"
    performances ||--o{ reservations : "예약 대상"
    reservations ||--o{ reservation_items : "예약 상세"
    seat_inventories ||--o| reservation_items : "좌석 점유"

동시성 설계

문제

인기 공연 오픈 시, 여러 사용자가 동일 좌석에 동시 예약하면 중복 예약이 발생할 수 있습니다.

현재 해결 전략

  1. DB Unique Constraint — seat_inventories(performance_id, seat_id) UNIQUE
  2. 비관적 락 — SeatInventoryRepository.findAllByIdInForUpdate()
  3. 좌석 ID 정렬 후 락 — 데드락 방지
  4. 단일 트랜잭션 — 좌석 상태 변경 + Reservation / ReservationItem 생성

트레이드오프

방식 장점 단점
비관적 락 (현재) 구현 단순, 정합성 강함 동시성 높을 때 DB 부하 (row 경합)
낙관적 락 읽기 성능 좋음 충돌 시 재시도 로직 필요
Redis 선점 DB 부하 분산 인프라 복잡도 증가, Mysql과 Redis 트랜잭션 처리 불가