리뷰는 한 행이 아니라 두 행
한 번의 숙박이 게스트 리뷰와 호스트 리뷰를 만듭니다. 둘은 쓰는 시점이 다르고, 공개되는 규칙이 다르고, 따로 신고될 수 있습니다. 한 행에 담으면 모든 질의가 자기가 어느 쪽을 읽는지 알아야 하고, 한 행을 두 번 공개할 수도 없습니다. type 컬럼을 둔 두 행은 조인 한 번이 더 들지만 "이 사용자가 쓴 글 전부" 가 단순 필터가 됩니다.
호스트 및 게스트 프로필, 편의시설과 사진이 포함된 숙소 리스팅, 가용성 캘린더, 동적 요금 설정, 예약 수명 주기 관리, 양방향 리뷰, 메시징, 위시리스트 및 호스트 대금 지급 추적 기능을 갖춘 에어비앤비 스타일의 단기 임대 마켓플레이스를 위한 전체 데이터베이스 스키마입니다.
이 스키마는 양쪽이 같은 사람일 수 있는 시장을 모델링합니다. 이번 주에 숙소를 내놓은 사람이 다음 주에는 남의 숙소를 예약합니다. 그래서 호스트 테이블을 따로 두지 않았습니다. host_profiles 는 users 에 붙어서, 호스트로 활동할 때만 성립하는 것 — 슈퍼호스트 여부, 응답률 — 만 담습니다.
예약 쪽은 "가격은 숙소가 아니라 날짜의 속성"이라는 전제 위에 있습니다. listings 에 base_price 가 있지만 availability_calendar 가 하루 단위로 덮어씁니다. 주말과 성수기를 다르게 받으면서도 숙소를 복제하지 않는 이유가 이것입니다.
돈은 일부러 두 군데에 적습니다. bookings 에는 게스트가 낸 금액을 base_total·cleaning_fee·service_fee 로 나눠 담고, payouts 에는 호스트가 받은 금액을 담습니다. 플랫폼이 수수료를 떼므로 두 숫자는 다르고, 둘 다 있어야 정산을 예약 건과 맞춰 볼 수 있습니다.
한 번의 숙박이 게스트 리뷰와 호스트 리뷰를 만듭니다. 둘은 쓰는 시점이 다르고, 공개되는 규칙이 다르고, 따로 신고될 수 있습니다. 한 행에 담으면 모든 질의가 자기가 어느 쪽을 읽는지 알아야 하고, 한 행을 두 번 공개할 수도 없습니다. type 컬럼을 둔 두 행은 조인 한 번이 더 들지만 "이 사용자가 쓴 글 전부" 가 단순 필터가 됩니다.
막힌 날은 가격이 없고, 비싼 날은 대개 수요가 많은 날입니다. 둘을 나누면 하루를 바꾸는 데 쓰기가 두 번 일어나고 읽을 때 조인이 붙습니다. 숙소×날짜 한 행이면 달력이 한 번의 스캔으로 끝나고, 기본값과 다른 날만 행을 만들므로 테이블도 크지 않습니다.
listing_photos.position 이 있는 이유는 대표 사진이 시각이 아니라 결정이기 때문입니다. created_at 에 기대면 순서를 바꿀 때마다 행을 다시 써야 하고, 업로드 방식을 손대는 순간 갤러리가 조용히 뒤섞입니다.
문의는 대개 예약보다 먼저 시작합니다 — 반려동물이 되는지 묻는 것처럼. listing_id 는 처음부터 채워지고, booking_id 는 문의가 숙박으로 이어질 때 채워집니다. 예약을 먼저 요구하면 예약 전 문의를 막거나 가짜 예약을 만들어야 합니다.