데이터 모델링 - leonroars/slam GitHub Wiki

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_idseat_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_idconcert_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
);