domino8788 / SKHUMap

SKHU MAP
1 stars 0 forks source link

즐겨찾기 DB 설계 #103

Closed domino8788 closed 4 years ago

domino8788 commented 4 years ago

users DB에 즐겨찾기 데이터가 저장 될 favorites 컬렉션과 문서, 필드 규격을 설계 및 구현한다.

다음 정보가 담겨야 한다.

domino8788 commented 4 years ago

해당 DB는 다음 규칙을 따른다.

Collection(favorites){
   Document(id -  타입 : String, id 값으로 favorites 문자열을 지정한다.) {
      Field(favoritesArray) - 타입 : array, 즐겨찾기 목록이 저장된다. {
            Field(favoritesMap) - 타입 : Map, 즐겨찾기 정보가 담긴다. {
                  Field(department) -  타입 : Reference, 건물 참조가 담긴다.
                  Field(floorNumber) - 타입 : Number, 층 번호가 담긴다.
                  Field(facility) - 타입 : Reference, 시설 참조가 담긴다.
            }
      }
   }
} 

image

domino8788 commented 4 years ago

원래는 위와 같은 구조가 아닌 즐겨찾기를 각각 문서로 저장하는 구조를 사용하려 했지만 다음과 같은 문제가 발생한다.

즐겨찾기를 저장할때 순서 정보를 함께 저장해야 한다.

이러한 이유로 자동으로 순서가 할당되며 배열 값에 대한 추가(push), 삭제(remove) 가 용이한 array 필드에 map을 item으로 담는 구조를 사용하기로 결정했다.

설계를 완료했으므로 변경사항이 발생할때까지 이슈를 닫도록 한다.

domino8788 commented 4 years ago

구현 도중 문제가 발생해서 이슈를 재개했다.

https://firebase.google.com/docs/firestore/solutions/arrays?hl=ko#android 위의 문서를 참고하면 Firestore는 문서의 크기를 1MB로 속성은 20000개로 제한한다. 그러므로 유저가 즐겨찾기를 무수히 추가하면 에러가 발생할 수 밖에 없다. Firestore는 데이터를 문서단위로 저장하길 권장하며 확장 될 수 있는 배열을 사용할 경우 성능이 더 우수한 하위 컬렉션을 사용하는 것을 권장한다.

위에 명시한 문제점을 최대한 개선해서 문서 단위로 저장하는 구조로 다시 설계한다.

domino8788 commented 4 years ago

해당 DB는 다음 규칙을 따른다.

Collection(favorites){
   Document(id -  타입 : String, id 값으로 즐겨찾기 정보를 기반으로 건물id_층번호_시설id 문자열을 지정한다.) {
      Field(index) - 타입 : Number, 순서 정보가 담긴다.
      Field(department) -  타입 : Reference, 건물 참조가 담긴다.
      Field(floorNumber) - 타입 : Number, 층 번호가 담긴다.
      Field(facility) - 타입 : Reference, 시설 참조가 담긴다.
}

설계를 완료했으므로 변경사항이 발생할때까지 이슈를 닫도록 한다.

domino8788 commented 4 years ago

구현도중 id 값으로도 건물, 층, 시설에 대한 Reference를 만들 수 있다는 결론에 도달했다. 효율을 위해 다음과 같이 수정한다.

해당 DB는 다음 규칙을 따른다.

  • 문서의 id는 건물id_층번호_시설id 로 한다.
  • 순서정보가 반영 될 수 있도록 설계한다.
Collection(favorites){
   Document(id -  타입 : String, id 값으로 즐겨찾기 정보를 기반으로 건물id_층번호_시설id 문자열을 지정한다.) {
      Field(index) - 타입 : Number, 순서 정보가 담긴다.
}

위는 DB에 담길 정보를 명시한 것이며 실제 DTO 클래스에서는 건물, 층, 시설 참조가 담길 변수가 추가된다.

아래에서 발견된 문제에 의해 새로 제시한 방안을 따르도록 한다.

domino8788 commented 4 years ago

새로 제시한 설계에 문제점이 발견됐다. id 값을 기반으로 건물, 층, 시설에 대한 문서참조를 만들어야 하는데 firestore의 toObject는 객체를 기본 생성자로 생성한 후 나중에 값을 채워넣는다. 그러므로 생성함과 동시에 각 정보를 초기화 하는것은 불가능하다. toObject() 호출 이후 체이닝으로 각 정보를 초기화 하는 함수를 호출하는 방안을 생각해봤지만 바람직해 보이지 않는다. id 를 생성자에서 빼 멤버변수로 편입시키고 setter를 통해 값이 변할때마다 각 정보에 반영하도록 하는 방안이 있지만 해당 방안은 데이터를 쓸때 별도로 id 초기화 작업을 해주지 않으면 안된다. 이는 위의 바람직하지 않은 상황과 비슷하다.

결과적으로 Reference를 DB 구조에 넣는것이 더 낫다는 결론에 도달했으므로 아래 구조를 따른다.

해당 DB는 다음 규칙을 따른다.

Collection(favorites){
   Document(id -  타입 : String, id 값으로 즐겨찾기 정보를 기반으로 건물id_층번호_시설id 문자열을 지정한다.) {
      Field(index) - 타입 : Number, 순서 정보가 담긴다.
      Field(department) -  타입 : Reference, 건물 참조가 담긴다.
      Field(floorNumber) - 타입 : Number, 층 번호가 담긴다.
      Field(facility) - 타입 : Reference, 시설 참조가 담긴다.
}

설계를 완료했으므로 변경사항이 발생할때까지 이슈를 닫도록 한다.

domino8788 commented 4 years ago

문제점이 생겨 대체방안을 마련해야 했던 방안의 문제가 다음 해결책에 의해 해결 되었다.

다음과 같이 즐겨찾기 DB의 설계를 변경한다.

구현도중 id 값으로도 건물, 층, 시설에 대한 Reference를 만들 수 있다는 결론에 도달했다. 효율을 위해 다음과 같이 수정한다.

해당 DB는 다음 규칙을 따른다.

Collection(favorites){
   Document(id -  타입 : String, id 값으로 즐겨찾기 정보를 기반으로 건물id_층번호_시설id 문자열을 지정한다.) {
      Field(index) - 타입 : Number, 순서 정보가 담긴다.
}

위는 DB에 담길 정보를 명시한 것이며 실제 DTO 클래스에서는 건물, 층, 시설 참조가 담길 변수가 추가된다

domino8788 commented 4 years ago

107 위의 커밋을 통해 변경된 설계를 반영했으므로 이슈를 닫는다.