Chapter 3. 데이터 모델링
1. 전체 ERD
2. 테이블별 설명
- 테이블 간 논리적 연관관계는 존재하나, 외래 키 제거를 통해 직접적 참조는 방지할 예정입니다.
- 이는 이후 락(Lock) 사용 시 예상치 못한 다른 테이블 읽기 작업에도 락이 걸려 병목이 발생하는 것을 방지하기 위함입니다.
- 또한, 현 프로젝트는 도메인 모델과 JPA Entity를 분리하는 설계를 차용할 예정입니다.
이때 도메인 모델의 ID는 String.valueOf(UUID.randomUUID())
를 통해 할당할 것이므로, 해당 모델과 대응하는 DB Entity의 ID 또한 VARCHAR(16)
으로 설정하여 두 모델이 아이디를 공유하도록 설계하였습니다.
1. USER
Schema
필드명 |
데이터 타입 |
설명 |
user_id |
VARCHAR(16) PRIMARY KEY AUTO_INCREMENT |
사용자 식별자. |
name |
VARCHAR(100) NOT NULL |
|
created_at |
DATETIME DEFAULT CURRENT_TIMESTAMP |
레코드 생성 시간 기록 |
updated_at |
DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
마지막 수정 시간 |
DDL
CREATE TABLE `USER` (
`user_id` VARCHAR(16) PRIMARY KEY,
`name` VARCHAR(100) NOT NULL,
`created_at` DATETIME DEFAULT (CURRENT_TIMESTAMP),
`updated_at` DATETIME DEFAULT (CURRENT_TIMESTAMP)
);
2. POINTBALANCE
Schema
필드명 |
데이터 타입 |
설명 |
point_balance_id |
INT PRIMARY KEY |
사용자-포인트 잔액 ID |
user_id |
VARCHAR(16) NOT NULL |
해당 잔액 보유 사용자 ID |
balance |
INT NOT NULL |
잔액 |
created_at |
DATETIME DEFAULT CURRENT_TIMESTAMP |
|
updated_at |
DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
|
DDL
CREATE TABLE `POINTBALANCE` (
`point_balance_id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`user_id` VARCHAR(16) NOT NULL,
`balance` INT NOT NULL
);
3. POINTHISTORY
Schema
필드명 |
데이터 타입 |
설명 |
point_history_id |
VARCHAR(16) PRIMARY KEY |
포인트 사용/충전 내역 식별자 |
user_id |
VARCHAR(16) NOT NULL |
사용자 ID |
type |
ENUM('charge', 'use') NOT NULL |
Point Transaction Type |
amount |
INT NOT NULL |
해당 내역에서 발생한 변동액 |
created_at |
DATETIME DEFAULT CURRENT_TIMESTAMP |
생성 일자 및 시간 |
description |
VARCHAR(255) |
포인트 내역 설명 |
DDL
CREATE TABLE `POINTHISTORY` (
`point_history_id` VARCHAR(16) PRIMARY KEY,
`user_id` VARCHAR(16) NOT NULL,
`type` ENUM ('charge', 'use') NOT NULL,
`amount` INT NOT NULL,
`created_at` DATETIME DEFAULT (CURRENT_TIMESTAMP),
`description` VARCHAR(255)
);
4. CONCERT
Schema
필드명 |
데이터 타입 |
설명 |
concert_id |
VARCHAR(16) PRIMARY KEY |
공연 ID |
artist |
VARCHAR(200) PRIMARY KEY |
공연 아티스트 이름 |
name |
VARCHAR(200) PRIMARY KEY |
공연 이름 |
DDL
CREATE TABLE `CONCERT` (
`concert_id` VARCHAR(16) PRIMARY KEY,
`artist` VARCHAR(200) NOT NULL,
`name` VARCHAR(200) NOT NULL
);
5. CONCERT_SCHEDULE
Schema
필드명 |
데이터 타입 |
설명 |
concert_schedule_id |
VARCHAR(16) PRIMARY KEY |
공연일정 식별자 |
concert_id |
VARCHAR(16) |
공연일정 식별자 |
date |
DATETIME |
공연 일자 |
reservation_start_at |
DATETIME NOT NULL |
공연 예약 시작 날짜/시간 |
reservation_end_at |
DATETIME NOT NULL |
공연 예약 종료 날짜/시간 |
created_at |
DATETIME DEFAULT CURRENT_TIMESTAMP |
|
updated_at |
DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
|
DDL
CREATE TABLE `CONCERT_SCHEDULE` (
`concert_schedule_id` VARCHAR(16) PRIMARY KEY,
`name` VARCHAR(200) NOT NULL,
`date` DATETIME NOT NULL,
`reservation_start_at` DATETIME NOT NULL,
`reservation_end_at` DATETIME NOT NULL,
`created_at` DATETIME DEFAULT (CURRENT_TIMESTAMP),
`updated_at` DATETIME DEFAULT (CURRENT_TIMESTAMP)
);
6. Seat
Schema
필드명 |
데이터 타입 |
설명 |
seat_id |
VARCHAR(16) PRIMARY KEY |
좌석 식별자 |
concert_schedule_id |
VARCHAR(16) NOT NULL |
해당 좌석이 속한 공연 일정의 ID |
seat_number |
VARCHAR(10) NOT NULL |
좌석 번호. 공연별로 고유해야 함. |
status |
ENUM('available', 'unavailable') DEFAULT 'available' |
좌석의 현재 상태. 기본값은 'available'. |
price |
INT NOT NULL |
좌석 가격. 편의 상 모두 같은 가격으로 설정한다. |
created_at |
DATETIME DEFAULT CURRENT_TIMESTAMP |
|
updated_at |
DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
|
제약 조건 |
|
concert_schedule_id 와 seat_number 의 조합이 유일해야 함. |
DDL
CREATE TABLE `SEAT` (
`seat_id` VARCHAR(16) PRIMARY KEY,
`concert_schedule_id` VARCHAR(16) NOT NULL,
`number` VARCHAR(10) NOT NULL,
`price` INT NOT NULL,
`status` ENUM ('available', 'unavailalbe') DEFAULT 'available',
`created_at` DATETIME DEFAULT (CURRENT_TIMESTAMP),
`updated_at` DATETIME DEFAULT (CURRENT_TIMESTAMP)
);
7. Reservation
Schema
필드명 |
데이터 타입 |
설명 |
reservation_id |
VARCHAR(16) PRIMARY KEY |
예약 식별자 |
user_id |
VARCHAR(16) NOT NULL |
예약을 한 사용자의 ID. |
seat_id |
VARCHAR(16) NOT NULL |
예약된 좌석의 ID. |
concert_schedule_id |
VARCHAR(16) NOT NULL |
예약된 좌석이 속한 공연 일정의 ID. |
created_at |
DATETIME DEFAULT CURRENT_TIMESTAMP |
예약이 이루어진 시간 |
expire_at |
DATETIME |
예약이 최초 생성된 시점(가예약 시점)으로부터 5분 후. |
reservation_status |
ENUM('BOOKED', 'PAID', 'EXPIRED') DEFAULT 'BOOKED' |
결제 상태. 이후 만료 토큰 삭제 시 "reservation_time"과 함께 참고하여 좌석 상태 변경 결정 |
제약 조건 |
|
seat_id 와 concert_schedule_id 의 조합이 유일해야 함. |
DDL
CREATE TABLE `RESERVATION` (
`reservation_id` VARCHAR(16) PRIMARY KEY,
`user_id` VARCHAR(16) NOT NULL,
`seat_id` VARCHAR(16) NOT NULL,
`concert_schedule_id` BIGINT NOT NULL,
`created_at` DATETIME DEFAULT (CURRENT_TIMESTAMP),
`expire_at` DATETIME NOT NULL,
`reservation_status` ENUM ('paid', 'booked', 'expired') DEFAULT 'booked'
);
8. Queue
Schema
필드명 |
데이터 타입 |
설명 |
token_id |
BIGINT PRIMARY KEY AUTO_INCREMENT |
토큰 식별자 |
user_id |
VARCHAR(16) NOT NULL |
토큰을 발급받은 사용자의 ID |
token_status |
ENUM('active', 'waiting') DEFAULT 'waiting' |
토큰의 현재 상태. 기본값은 'waiting'. |
concert_schedule_id |
VARCHAR(16) NOT NULL |
콘서트 일정 ID |
created_at |
DATETIME DEFAULT CURRENT_TIMESTAMP |
토큰 생성 시간 |
expires_at |
DATETIME NOT NULL |
토큰 만료 시간. 토큰 생성 시점으로부터 4시간 후에 만료. |
DDL
CREATE TABLE Queue (
token_id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id VARCHAR(16) NOT NULL,
concert_schedule_id VARCHAR(16) NOT NULL,
token_status ENUM('active', 'wait') DEFAULT 'wait',
created_at DATETIME DEFAULT (CURRENT_TIMESTAMP),
expires_at DATETIME NOT NULL
);