Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#3] DB 설계 고정 데이터들 ENUM으로 변경 #28

Merged
merged 2 commits into from
Jun 21, 2022

Conversation

memoer
Copy link
Contributor

@memoer memoer commented Jun 17, 2022

  • category 관련 테이블 모두 room_category 테이블로 묶음
  • facility_category 테이블은 facilitry 테이블의 category 컬럼으로 넣음
  • 고정 데이터들은 자바 애플리케이션 단에서 ENUM으로 관리하기로 결정

airjnc-ERD

Related Issues

Description

COMMON

  1. DELETE 매커니즘은 HardDelete가 아닌 SoftDelete로 진행했습니다.
    • deletedAt 컬럼 사용
  2. 시간 관련 타입은 "DATETIME, DATE" 칼럼이 아닌 "TIMESTAMP"로 통일했습니다.
    • 시간 관련 타입을 여러 개의 종류를 섞어서 쓸 경우, 시간 관련 데이터를 조작할 때 혼란이 올 가능성이 있기 때문입니다.
    • "DATETIME, DATE" 같은 경우는 DB 커넥션 타임존에 관계없이 클라이언트로부터 입력된 값을 그대로 저장하고, TIMESTAMP같은 경우는 타임존에 따라 시간이 보정됩니다. 이로 인해 두 가지의 데이터 타입을 섞어 쓸 경우, 어느 API는 시간을 보정하는 로직이 생기고, 어느 API는 시간을 보정하는 로직이 생기지 않는 상황을 방지하기 위해 날짜 데이터 타입을 하나로 통일했고, TIMESTAMP로 통일했습니다.
  3. 외래키 같은 경우엔 제약을 걸지 않았습니다.
    • 외래키 제약을 걸 경우, 데이터 일관성과 그에 따른 제약 때문에 성능 이슈가 발생할 수 있기 때문에 외래키를 물리적으로 제약 걸지 않았습니다.
    • 외래키를 물리적으로 제약을 걸지 않았고, 해당 외래키에 대해서는 하나하나씩 인덱스를 생성했습니다. 왜냐하면, 외래키같은 경우 JOIN문으로 사용할 경우가 아주 많이 발생하는데, JOIN 문에서 성능 최적화를 위해서는 INNER TABLE의 조인키에 인덱스가 있어야 하기 때문입니다.
  4. 다대다 테이블의 이름 같은 경우, 해당 테이블이 다대다 테이블임을 명시하기 위해 중간에 "__"를 넣었고 양 옆에 연결되는 테이블을 적었습니다.
    • Ex) room_category_dateil__room_type, room__room_facility
  5. 다대다 테이블에서 유니크 제약을 걸었습니다.
    • room_category_detail__room_type 테이블에선, room_category_detail_idroom_type_id를 한 쌍으로 유니크 제약을 걸었습니다.
    • room__room_facilitiy 테이블에선, room_idfacility_id 를 한 쌍으로 유니크 제약을 걸었습니다.
    • 유니크 제약을 건 이유 -> MySQL의 InnoDB 에서는 PK가 물리적으로 디스크상에서 저장시 정렬하면서 저장됩니다. 다대다 테이블에서 PK를 2개의 로우에 대해서 걸어버릴 경우, 데이터 저장시 소팅되면서 저장되는 성능 이슈가 발생할 수 있습니다. 때문에 PK를 2개의 로우에 대해서 설정하지 않았고, 자동 증가 값인 AUTO_INCREMENT를 통해 설정했습니다. 이렇게 설정할 경우, 기본에 row 2개에 대해서 PK를 걸어버리는 상황과 달리 중복 이슈가 발생할 수 있습니다. "room__room_facility를 예로 들면, 방 하나에 대해서 동일한 편의시설이 저장되는 등.." 이러한 중복 이슈를 방지하기 위해 유니크 제약을 걸었습니다.

[TABLE] host

  1. 유저 별로 여러 개의 호스트를 가질 수 있기 때문에, host Table을 따로 뺐습니다. [1:다 관계]

[TABLE] user

  1. is_active -> 활성화 여부를 판단
  2. gender -> 성별
    • 해당 컬럼은 향후로도 남자/여자 외에는 데이터 추가할 일이 전혀 없을 것 같으므로, 테이블을 따로 빼서 참조하는 식으로 설계하지 않았고 VARCHAR 타입으로 설계 이후, 애플리케이션 단에서 데이터 규격을 잡아 저장합니다.

[TABLE] room

  1. (min/max)_number_of_nights -> 최소 숙박 일수, 최대 숙박 일수
    • 사용자는 명시한 최소 숙박 일수 이상으로만 예약할 수 있습니다.
    • 사용자는 명시한 최대 숙박 일수 이하로만 예약할 수 있습니다.
  2. room_cnt -> 해당 방에 대한 개수
    • 명시적으로 설정하지 않을 경우, DEFAULT 값은 1입니다.
    • 방의 카테고리에는 "호텔"이 존재합니다. 어떠한 특정 카테고리에서는 방을 1개만 제공하는 서비스가 아닌 2개 이상을 제공할 수 있습니다. 때문에, 방의 개수를 지정할 컬럼을 추가했습니다.
    • "호텔"같은 여러 방을 제공하는 카테고리가 아닌, 단순히 저택같은 경우 해당 컬럼의 값은 1입니다.
  3. check_in, check_out
    • 해당 방의 체크인/체크아웃 시간입니다.
    • 해당 컬럼같은 경우, 날짜[2022/06/15 같은]의 존재가 필요없고, 또한 저희 기능상으론 체크인/체크아웃에 분단위[30분 같은]가 들어가지 않습니다.
    • 최종적으로, 체크인/체크아웃은 "시간"단위로만 입력되기 때문에, 날짜타입[TIMESTAMP]가 아닌 VARCHAR 타입으로 설정했으며 이 경우, 저장시에는 "11"->11시(or)"15"->15시 형태로 저장됩니다.

[TABLE] room_price

  1. 특정 방에 대해서 월별로 가격을 설정하는 기능을 구현하기 위해 1:다 테이블로 설계했습니다.
  2. price 는 해당 월[ex)month=1이면 1월]에 대한 기본 가격이며, weekly_price 는 주간 할인 가격입니다.

[TABLE] room_status

특정 방에 대한 상태값을 저장하는 테이블입니다.

  1. 현재 초기 기능 요구서에서 나온 상태값은 총 3개입니다.
    • IN_OPERATION : 영업 중, 게스트가 숙소를 검색하고 예약 요청을 보내거나 예약 가능 날짜를 예약할 수 있습니다
    • SHUT_DOWN : 운영 중지, 게스트가 숙소를 예약하거나 검색 결과에서 찾을 수 없습니다.
    • DISABLED : 비활성화, 에어비앤비에서 영구적으로 숙소 비활성화
  2. 방에 대한 상태값을 초기 기능 요구서에서 정의한 상태값에서, 추후에 추가될 가능성이 높기 때문에 테이블을 따로 빼서 참조하게끔 했습니다.

[TABLE] room_photo

방에 대한 사진

  1. order -> 방에서 노출시키는 사진에 대한 우선순위

[TABLE] room__faciltiy / facility

  1. facility
    • 편의시설에 대한 이름과 설명을 저장하는 테이블입니다.
    • 해당 테이블의 category 컬럼을 통해 편의시설에 대한 카테고리를 설정합니다.
  2. room__faciltiy
    • 방은 여러 개의 편의시설을 가질 수 있고, 편의시설 또한 여러 개의 방을 가질 수 있습니다. 때문에, 다대다 테이블로 설정했습니다.
    • 방-편의시설을 "일:다"로 설계할 경우, 편의시설에 "드라이기"라는 아이템이 있을 경우 room_facility 테이블에서 "드라이기__roomId-1, 드라이기__roomId-2, 드라이기__romId-3" 으로 저장됩니다. 이 경우, 만약 "드라이기"라는 아이템의 이름을 변경해야 할 때는 "드라이기"의 모든 row에 대해서 이름을 변경해야 하기 때문에 변경지점이 한 곳이 아닌, 여러 개가 되어버립니다. 이를 방지하기 위해 다대다 테이블로 설계했습니다.

[TABLE] room_category

Screen Shot 2022-06-15 at 5 09 04 PM
Screen Shot 2022-06-15 at 5 09 14 PM

  1. �root_category -> "회원님의 숙소에 가장 적합한 유형을 선택하세요"에서 나오는 값들을 저장하는 컬럼
  2. reaf_category -> 첫 번째 숙소 유형에 나오는 값들을 저장하는 컬럼
  3. room_type -> 두 번째 숙소 유형에 나오는 값들을 저장하는 컬럼
    • "전체/개인실/다인실" 3개의 데이터만 존재한다.

변경 사항

main/java/resources에 schema.sql 파일 추가

질문 사항

기타

(Optaionl) 어떻게 테스트하셨나요?

- category 관련 테이블 모두 room_category 테이블로 묶음
- facility_category 테이블은 facilitry 테이블의 category 컬럼으로 넣음
- 고정 데이터들은 자바 애플리케이션 단에서 ENUM으로 관리하기로 결정
@memoer memoer added Type: Setting 개발 환경 설정 Size: X 변경/추가된 파일 10개 이하 Communication Needed 논의 필요 labels Jun 17, 2022
@hoon25
Copy link
Contributor

hoon25 commented Jun 17, 2022

  • category 관련 테이블 모두 room_category 테이블로 묶음

저희가 ENUM으로 카테고리의 상하위 그룹도 관리하기로 했기 때문에
room_category테이블

  • roof_category
  • leaf_category
  • room_type

위 세개컬럼이 한개의 컬럼으로 구성되고 코드내부에서(상하위그룹)을 관리하는 방식으로 가야되는게 아닐까요?

  • facility_category 테이블은 facilitry 테이블의 category 컬럼으로 넣음
  • 고정 데이터들은 자바 애플리케이션 단에서 ENUM으로 관리하기로 결정

airjnc-ERD

Related Issues

@memoer
Copy link
Contributor Author

memoer commented Jun 17, 2022

말씀하신 것처럼 세 개의 컬럼을 하나의 컬럼으로 묶으면 DB에는 어떻게 저장될까요?
"부티크호텔/호텔/다인실" 이런식으로 저장될까요?

@hoon25
Copy link
Contributor

hoon25 commented Jun 17, 2022

말씀하신 것처럼 세 개의 컬럼을 하나의 컬럼으로 묶으면 DB에는 어떻게 저장될까요? "부티크호텔/호텔/다인실" 이런식으로 저장될까요?

Enum에서 해당 필드는 코드에서

  • 카테고리끼리 묶는 정책에 따라 바뀜
    • (DBInput값, 부티크호텔 ,호텔 ,다인실) <- 코드의 상위정보 전체 저장
    • (DBInput값, 이름, 상위개념값) <- 코드의 한단계상위 정보만 저장

이런식으로 들어가게되지않을까요?
DB컬럼에는 최하단 카테고리의 DBInput값이 들어가게됩니다.

+) 위에 Enum구성은 하나의 예시이고 코드상 ENUM 구조 설계를 토의 후 정해야겠네요

@memoer
Copy link
Contributor Author

memoer commented Jun 17, 2022

DB에 3개의 데이터를 합쳐서 넣어버리면, 특정 카테고리나 특정 타입에 대해서 방을 검색하고 싶을 때 LIKE 로 후방일치로 검색하는 상황이 생길텐데, 이 경우엔 인덱스를 전혀 사용하지 못 합니다. 한 컬럼에 데이터를 모두 넣어서 저장할 경우 검색에 있어서 성능 이슈가 발생할 것 같은 생각이 듭니다.
때문에 저는 각각 3개의 컬럼으로 데이터를 넣어두고 LIKE 검색이 아닌 = 검색으로 인덱스를 활용하여 검색하는 게 낫다고 생각이 듭니다.

@hoon25
Copy link
Contributor

hoon25 commented Jun 18, 2022

DB에 3개의 데이터를 합쳐서 넣어버리면, 특정 카테고리나 특정 타입에 대해서 방을 검색하고 싶을 때 LIKE 로 후방일치로 검색하는 상황이 생길텐데, 이 경우엔 인덱스를 전혀 사용하지 못 합니다. 한 컬럼에 데이터를 모두 넣어서 저장할 경우 검색에 있어서 성능 이슈가 발생할 것 같은 생각이 듭니다. 때문에 저는 각각 3개의 컬럼으로 데이터를 넣어두고 LIKE 검색이 아닌 = 검색으로 인덱스를 활용하여 검색하는 게 낫다고 생각이 듭니다.

음.. 근데 위 방식대로 적용을 한다면 단순히 DB를 반정규화 한 것이고 varchar()타입으로 바로 관리를 해도 괜찮은 상황과 동일한 것으로 보입니다.
코드로 ENUM쪽에서 카테고리 구조를 잘 설정하는 방식으로 가야하지 않을까요?

@memoer
Copy link
Contributor Author

memoer commented Jun 18, 2022

  • 한 컬럼 안에 데이터를 여러 개를 동시에 저장하는 형태가 제 1정규화를 반하는 형태라서 좋은 설계는 아니라고 생각이 듭니다.
  • 또한, 상위 카테고리에 "부티크 호텔"이 있고, "부티크 호텔"에 속하는 하위 카테고리에 "산장, 아파트 호텔, 호텔, ..." 이 있는데 이 상황에서 데이터가 한 컬럼에 모두 묶여져버리면 하위 카테고리 "호텔"에 속하는 방을 찾을 때 상위 카테고리의 "부티크 호텔"에서 "호텔"이 매칭되어서 하위 카테고리가 "호텔"이 아닌 "산장"까지도 데이터가 조회될 수 있습니다.
    • 이 경우, 애플리케이션 단에서 저희가 로직상으로 분리는 할 수 있지만, 이렇게 하는 것보단 카테고리별로 컬럼을 나누어 데이터를 저장하여 필터링하는 게 훨씬 쉽기도 하고, 인덱스를 활용할 수 있다고 생각합니다.

코드로 ENUM 쪽에서 카테고리 구조를 잘 설정한다고 하여도, DB 를 조회하는 과정이나 설계방법에서의 정규화 측면에서도 안 좋은 방향이라고 생각이 듭니다.
이 경우에는 카테고리별로 컬럼을 나누어 저장하는 게 효율적이라고 생각이 듭니다.

@memoer memoer changed the title chore(#3): DB 설계 고정 데이터들 ENUM으로 변경 [#3] DB 설계 고정 데이터들 ENUM으로 변경 Jun 20, 2022
- category name 하나만 가져가기로 결정
- 해당 컬럼의 값 -> "부티크 호텔, 게스트 하우스, 저택, 아파트, ... "
@memoer
Copy link
Contributor Author

memoer commented Jun 21, 2022

ERD 최종본
airjnc-ERD

  • category 하나만 가져가기로 결정
  • room_category의 category_name 컬럼의 데이터는 "부티크 호텔, 산장, 아파트, 게스트 하우스, 저택, ..." 하나의 데이터만 들어간다.

@memoer memoer merged commit 61193d3 into master Jun 21, 2022
@memoer memoer deleted the chore/#3-DB_설계 branch June 21, 2022 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Communication Needed 논의 필요 Size: X 변경/추가된 파일 10개 이하 Type: Setting 개발 환경 설정
Projects
None yet
Development

Successfully merging this pull request may close these issues.

DB 설계
2 participants