diff --git a/README.md b/README.md new file mode 100644 index 0000000..f1c5260 --- /dev/null +++ b/README.md @@ -0,0 +1,87 @@ +# 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 그대로이며, 선 위 한글은 관계 설명용입니다 (코드/컬럼명 아님). + +```mermaid +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 트랜잭션 처리 불가|