본문 바로가기
SQL/NoSql

[firebase] 팀프로젝트 DB구조 보완안

by Pendine 2025. 4. 4.
728x90

firebase 데이터 구조

1. accommodations (숙소 정보)

문서 ID: 숙소 고유 ID

📍 필드

  • name (string): 숙소 이름
  • type (string): 숙소 유형 (hotel, motel, pension, guesthouse, camping)
  • location (map):
    • latitude (number): 위도
    • longitude (number): 경도
    • place_name (string): 지역 이름
    • city (string): 도시 대분류
    • sub_city (string): 도시 소분류
  • description (string): 숙소 설명
  • host (map):
    • name (string): 호스트 이름
    • email (string): 이메일
    • contact (string): 연락처
  • images (array): 숙소 사진 URL 리스트
  • total_rating (number): 리뷰 평점 총합
  • review_count (number): 리뷰 총 개수

2. rooms (객실 정보)

문서 ID: 객실 고유 ID

📍 필드

  • accommodation_id (string): 객실이 속한 숙소의 ID
  • name (string): 객실 이름
  • type (string): 객실 유형 (single, double, suite, family)
  • stay_type (string): 객실 유형 (stay 숙박, day_use 대실)
  • original_price (number): 원가
  • discount_rate (number): 할인율 (예: 0.1 → 10%)
  • availability (boolean): 객실의 예약 가능 여부 (true/false)
  • stock (number): 객실의 재고 수
  • capacity (map):
    • adults (number): 성인 수
    • children (number): 미성년자 수
  • services (array): 제공하는 서비스 (예: ['wifi', 'parking', 'tv', 'breakfast', 'barbecue'])
  • images (array): 객실 사진 URL 리스트
  • check_in (timestamp): 체크인
  • check_out (timestamp): 체크아웃
  • description (string): 객실 설명
  • room_group_id (string): 객실 그룹 ID

2. users (사용자 정보)

문서 ID: 사용자 UID (Firebase Auth와 연동)

📍 필드

  • username (string): 사용자 이름
  • nickname (string): 닉네임
  • email (string): 이메일
  • phone (string): 전화번호
  • profile_image (string): 프로필 사진 URL
  • wishlist (array): 찜 목록 (accommodation_id 리스트)
  • points (number): 사용 가능한 포인트
  • created_at (timestamp): 생성 날짜

3. orders (주문 정보)

문서 ID: 주문 ID

📍 필드

  • user_id (string): 주문한 사용자 UID
  • room_id (string): 객실 ID
  • payment_status (string): 결제 상태 (completed, canceled)
  • order_date (timestamp): 주문 날짜
  • used_points (number): 사용한 포인트
  • duration (map):
    • hours (number): 시간
    • minutes (number): 분
  • selectedTime (array): 선택된 시간 배열 (예: ["14:00", "14:30", ...])
  • cancel_reason (string): 취소 사유

4. reviews (리뷰 정보)

문서 ID: 리뷰 ID

📍 필드

  • accommodation_id (string): 숙소 ID
  • user_id (string): 작성자 UID
  • rating (number): 평점
  • comment (string): 리뷰 내용
  • created_at (timestamp): 작성 날짜

6. carts (장바구니)

문서 ID: 장바구니 ID 객실id_유저id

📍 필드

  • created_at (timestamp): 작성 날짜
  • duration (map):
    • hours (number): 시간
    • minutes (number): 분
  • room_id (string): 객실 ID
  • selectedTime (array): 선택된 시간 배열 (예: ["14:00", "14:30", ...])
  • type (string): (stay 숙박, day_use 대실)
  • user_id (string): 사용자 UID

 

 

이런식으로 구조를 짰었음.

내가 볼 때 보완이 필요한 구조로 보임

그렇다고해서 내가 바꾸는 구조가 정답이라고는 할 수 없지만.

서비스를 제공하는 입장에서 각 숙소의 정보나 객실 정보는 정적이라고 볼 수 있고

객실 정보는 숙소 정보에 포함되어있어야 한다고 보임

그리고 객실 정보를 따로 분리하는 이유는 현재 잔여 정보를 봐야하는정도라고 생각하고

더이상 군말않고 짠다면

 

1. accommodations (숙소 정보)

  • name (string): 숙소 이름
  • type (string): 숙소 유형 (hotel, motel, pension, guesthouse, camping)
  • location (map) : 위경도
    • latitude (number): 위도
    • longitude (number): 경도
  • place (map) : 지역정보
    • place_name (string): 지역 이름
    • city (string): 도시 대분류
    • sub_city (string): 도시 소분류
  • description (string): 숙소 설명
  • host (map):
    • name (string): 호스트 이름
    • email (string): 이메일
    • contact (string): 연락처
  • room_list (array): 객실들의 정보
    • room (map) : 객실 정보
      • grade (string): 객실 등급 (single, double, suite, family)
      • stay_type (string): 객실 유형 (stay 숙박, day_use 대실, both : 둘 다 가능)
      • original_price (number): 정가
      • discount_rate (number): 할인율
      • stock (numer) : 객실 수량 정보
        • total : 총 객실
        • now : 현재 잔여 객실
      • services (array): 객실 서비스
      • capacity (map) : 수용인원
        • adult : 성인
        • children : 미성년자
  • images (array): 숙소 사진 URL 리스트
  • review (map) : 리뷰정보
    • total_rating (number): 리뷰 평점 총합
    • review_count (number): 리뷰 총 개수
  • check_inout (map) : 입퇴실 시간
    • check_in (timestamp): 입실시간
    • check_out (timestamp): 퇴실시간

이렇게 짤듯.

이렇게 바꾸게되면 하나의 문서에서 관리하는 정보가 많아지기는 하지만

관리포인트를 하나로 몰아서 거의 정적인 정보를 굳이 나눌 필요는 없어짐.

 

굳이 저렇게 하나에 몰아넣은 이유?

https://www.youtube.com/watch?app=desktop&v=Idu9EJPSxiY&%3Bindex=5&%3Blist=PLl-K7zZEsYLlP-k-RKFa7RyNPa9_wCH2s&%3Bhl=ko&hl=ko

조인 거는 방법을 찾아본건데 이쪽도 전부 순회함

순회함? → 인덱스 필요.

인덱스 필요?

→ nosql문 특성상 검색할때 사용할 컬럼을 전부 인덱싱해줘야하는데

인덱싱하는 조건의 모든 경우의 수를 다 입력해줘야하는데다,

컬럼 순서가 다르면 다른 인덱스 정보로 취급하는지 새로 생성해줘야해서

까딱하다간 하나의 컬렉션의 인덱싱을 위해 할당하는 용량이 컬렉션용량보다 많아지게 될 수 있음.

그래서 최소한의 인덱싱 용량으로 핸들링할 수 있도록 인덱스 관리하는게 맞는 것 같아 저렇게 구조를 생각해봤다.

 

 

 

RDB에서 만든다면 방 정보에 대한 테이블을 만들어줘야하는데

그 이유는 테이블의 구조는 고정되어있기 때문이다.

예를들어 RDB로 객실 정보를 숙소테이블에서 관리할때

숙소테이블에서 핸들링 할 수 있는 각 등급별 객실 정보를 컬럼으로 구성해줘야하고

핸들링 할 수 없는 새로운 객실정보가 추가되거나 제거되면

테이블 구조가 변경이 되어야하지만

No sql 특성상 새로운 튜플이라고 해야할지, 컬럼이라고 해야할지.

 여튼 추가해야하는 정보를 위해 테이블 구조를 변경할 필요 없이

동일한 형태의 데이터를 추가만 해주면 됨.

 자주 바뀐다고 해봤자 숙소의 각 객실의 현재 객실 정도뿐인데

컬랙션을 따로 다룬다면 이걸 핸들링하기 위해서 만드는정도 될듯.

핸들링하려고 방정보를 따로 관리하게된다면 room_id 를 추가하면 될 것 같음

RDB의 구조

RDB에서 구조는 고정
noSql의 구조

noSql에서는 유동적

앤간한건 숙소 아이디를 키값으로하고, 객실 등급을 enum으로 다루면 해결 될건데

 

그리고 꿋꿋하게 room_id가 만들어져야 한다! 라고 한다면

객실 등급은 동일하지만 객실마다 제공되는 서비스가 다르다! 라고 한다면

분리하는게 맞음.

 

객실 정보 안에 체크인 아웃 이 들어간 이유는 잘 모르겟음.
프로젝트 내에서 실제로 핸들링하는 객실 정보가

특정한 등급의 객실을 개별로 다루는게 아니라서

 => 예를 들면 일반등급의 101호, 102호 103호 객실 이런식으로 다루는게 아니라

 등급별 객실 정보만 다루기때문에 room_id를 굳이 집어넣을 필요가 없었음.

 

 

  • duration (map):
    • hours (number): 시간
    • minutes (number): 분
  • selectedTime (array): 선택된 시간 배열 (예: ["14:00", "14:30", ...])

시간 관련 속성도 내입장에서 이해가 안되는게

객실을 대실할때 시간텀을 지정할수 있도록 만든 컬럼 같은데

주문 정보의 컬랙션에서 방의 아이디로 모든 데이터를 긁어와서 일일이 확인할거 아니라면

주문정보를 다루는 컬럼에서 대실과 숙박 선택시 입력할때 다루는 컬럼명도 아예 다른데

굳이 이걸 나눌 필요가 있었을까? 라는 생각이 있었음.

주문 내역을 다루는 테이블에서 대실, 숙박을 확인하기 위해서 나눴다고 한다면

대실인지, 숙박인지 구분하는 컬럼 하나와,  입실, 퇴실시간을 지정하는 컬럼하나

두개로 충분히 커버 됐을 것 같음

 

그렇게 고려해서 방 정보를 내가 짠다면

2. rooms (객실 정보)

  • accommodation_id (string): 객실이 속한 숙소의 ID
  • grade (string): 객실 등급 (single, double, suite, family)
  • reserved_time (array) : 예약된 시간목록
    • reserved (map): 예약된 시간
      • start (timestamp) : 대실 시작시간
      • end (timestamp) : 대실 종료시간

뭐 이정도로 하면 될듯.

이렇게 만들어놓으면

DB에 스케쥴러를 돌리던지, 백엔드에서든 배치작업을 하던지 처리해서

대실 종료시간 끝나면 예약된 시간 지워버리면 될듯함.

 

굳이 시간을...

대실은 보통 4시간단위에 연장도 가능한데

시간대별로 대실 가능한 재고를 시간대 별로 제공하지도 않는데 설계가 왜 저렇게 들어간건지,

데이터를 왜 저렇게 넣으려고 한건지 의문밖에 안듬.

 

어느정도의 정보를 제공할건지 제한을 안두고 설계한건가...

구조를 최대한 간단하게 가져가야했는데

테이블은 쪼개고, 컬럼 구조는 복잡하게 가져가서 구현할때 이걸 왜이렇게 했을까....

고민? 고뇌? 뭐 한참 했음

 

조언을 해서 듣는 시늉이라도 했으면 구조를 짜줬을텐데,

혼자 'ㅇㅋ 알았음 기다려보셈' 하고 다음날 뒤집어 엎어버렸는데,

예상을 한참 빗나간 구조로 만들어 온데다가 코드 여기저기를 전부 바꿔버려서

그냥.....

뭐하나 쉬운게 없었음ㅋㅋㅋ

 

바꿔온 구조를 처음 봤을때, 들었던 생각이

`아! 테이블 구조 때문에 격노하셨던 부장님 심정이 바로 이거구나!`

하고 웃었었다ㅋㅋㅋ

 

도움을 많이 받았던 터라 나도 도움을 줄 수 있는 상황이 오면 도와주려고 했는데

ㅋㅋㅋㅋㅋㅋㅋㅋ

댓글