Android - Firebase Realtime Database Structure

2024. 5. 7. 17:53IT/Android

728x90

<정리>

Realtime Database는 키-값 쌍으로 이뤄지는 JSON 객체들이 모여 트리 구조를 이루고, 루트 노드로부터 최대 32단계의 자식 노드를 가질 수 있다. 하지만 특정 노드의 데이터를 가져오면 해당 노드와 연결된 자식 노드의 데이터도 함께 가져오고, 사용자에게 특정 노드에 대한 권한을 부여하면 해당 노드에 속한 모든 데이터에 대한 권한이 부여된다는 특징 때문에 최대한 낮은 레벨의 트리 구조를 형성하는 것이 좋다. 쉽게 말해, 트리 가장 밑단에 존재하는 노드의 데이터를 얻는다고 할 때 해당 노드만 다운로드하면 그만이지만 루트 노드의 데이터를 얻는다고 하면 루트 노드와 연결된 모든 자식 노드들도 함께 다운로드가 되어 트래픽 사용량을 높인다는 의미다.

 

title 목록을 얻기 위해 chats 노드를 가져오면서 관련 없는 수 많은 데이터도 같이 다운로드가 되는 상황.

{
  // This is a poorly nested data architecture, because iterating the children
  // of the "chats" node to get a list of conversation titles requires
  // potentially downloading hundreds of megabytes of messages
  "chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "messages": {
        "m1": { "sender": "ghopper", "message": "Relay malfunction found. Cause: moth." },
        "m2": { ... },
        // a very long list of messages
      }
    },
    "two": { ... }
  }
}

 

카테고리 별로 노드를 넓게 분산함으로써 필요한 데이터만 다운로드할 수 있도록 하였고, 각각의 상위 노드 아래에 같은 하위 노드를 중첩시켜 검색의 비용을 줄였다.

{
  // Chats contains only meta info about each conversation
  // stored under the chats's unique ID
  "chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "lastMessage": "ghopper: Relay malfunction found. Cause: moth.",
      "timestamp": 1459361875666
    },
    "two": { ... },
    "three": { ... }
  },

  // Conversation members are easily accessible
  // and stored by chat conversation ID
  "members": {
    // we'll talk about indices like this below
    "one": {
      "ghopper": true,
      "alovelace": true,
      "eclarke": true
    },
    "two": { ... },
    "three": { ... }
  },

  // Messages are separate from data we may want to iterate quickly
  // but still easily paginated and queried, and organized by chat
  // conversation ID
  "messages": {
    "one": {
      "m1": {
        "name": "eclarke",
        "message": "The relay seems to be malfunctioning.",
        "timestamp": 1459361875337
      },
      "m2": { ... },
      "m3": { ... }
    },
    "two": { ... },
    "three": { ... }
  }
}

 

구조에 데이터 저장의 중복을 허용하여 읽기 속도를 향상시킬 수 있는데 이를 데이터의 비정규화라고 부르고, 대표적으로 색인을 예시로 들 수 있다. 이해를 돕기 위해 카톡을 예시로 들어보자. 카톡은 한명의 사용자가 여러 채팅방에 포함될 수 있고 하나의 채팅방이 여러 사용자를 포함할 수 있다. 만약 한 사람이 계정 탈퇴를 하여 참석 했던 모든 채팅방에서 나가져야 한다면, 서버에 있는 모든 채팅방을 읽어와서 해당 유저가 포함되어 있는지 확인하고 제거해야 한다. 이는 굉장히 복잡하며 많은 연산을 수반한다. 따라서 많은 비용을 야기하는 정보를 쉽게 검색할 수 있도록 정보의 일부를 양방향으로 갖게 하는데 이를 바로 색인이라고 부른다. 아래의 구조에서는 유저가 그룹의 정보를, 그룹이 유저의 정보를 갖게 하여 검색의 비용을 줄였다.

// An index to track Ada's memberships
{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      // Index Ada's groups in her profile
      "groups": {
         // the value here doesn't matter, just that the key exists
         "techpioneers": true,
         "womentechmakers": true
      }
    },
    ...
  },
  "groups": {
    "techpioneers": {
      "name": "Historical Tech Pioneers",
      "members": {
        "alovelace": true,
        "ghopper": true,
        "eclarke": true
      }
    },
    ...
  }
}

 

 

참조 : https://firebase.google.com/docs/database/android/structure-data?hl=ko

728x90