Firebase의 컬렉션 구조

깡스·2023년 7월 14일
1

개인 프로젝트에서 firebase를 사용하기에, 평소에 신경쓰지 않아도 괜찮던 DB구조에 대해 생각해봐야하는 상황이 발생하였습니다.

게시물의 데이터 구조


컬렉션데이터서브컬렉션데이터
postspostcommentscomment
--reactionsreaction
usersuser--

게시물 같은 경우 위와 같은 형태로 posts라는 컬력션 아래 각각의 게시물이 저장되며, 그 게시물의 서브 컬렉션에 comments, reactions 두개의 서브 컬렉션이 위치하고 있습니다.

그리고 users라는 컬렉션에 유저들의 정보를 저장하고 있습니다.

발생한 문제


위와 같이 컬렉션 구조가 설계되어 있으나, 클라이언트 부분에서 게시물을 표시하기 위해 필요한 데이터는

  • post
  • comment
  • reaction
  • user

이렇게 4가지의 데이터가 필요합니다.

하지만 FirebaseNoSQL기반에 서비스이기에 컬렉션을 하나의 필드로 join할 수 없기에 문제가 발생하였습니다.

문제를 해결하기 위해, post하나에 user, comment, reaction를 모두 취합하여 관리하게 되면 문제가 해결되나 이 방법의 문제점은 아래와 같습니다.

  • 덧글과 같은 데이터의 경우 데이터가 많아지면 담을 수 없는 크기가 될 수도 있습니다.
  • 작성자와 같은 데이터의 경우 닉네임이나 프로필사진 등 정보가 변경되면 유저정보뿐 아니라 유저가 작성한 게시물과 같이 연관된 데이터를 모두 수정해주어야 한다는 문제점이 있습니다.

해결한 방법


파이어베이스에서 데이터의 병합이 불가능하다면, 필요한 데이터들을 호출한 후, 클라이언트단에서 병합해 join과 같은 효과를 구현하기로 했다.

export const getPost = async (id: string) => {
  const postDoc = await getDoc(doc(db, POST_COLLECTION, id));

  const { createdAt, ...postData } = postDoc.data() as PostFirebase;

  const userPromise = getUser(postData.uid);
  const reactionsPromise = getReactionList(postDoc.id);
  const commentsPromise = getCommentList(postDoc.id);

  const [user, reactions, comments] = await Promise.all([
    userPromise,
    reactionsPromise,
    commentsPromise
  ]);

  return {
    id: postDoc.id,
    user,
    reactions,
    comments,
    createdAt: createdAt.toDate(),
    ...postData
  } as PostClient;
};

위와 같이 getUser, getReactionList, getCommentList를 통해 필요한 데이터를 호출, Promise.all을 통해서 병렬로 처리해주었습니다.

해결하지 못한 문제


위와 같은 방법은 원하는 형태로 데이터를 받아올 수 있으나, 서버에서 데이터를 정제해주는게 아니기에, 너무 많은 호출이 발생합니다.
많은 호출은 결국에 서버비용을 증가시키기에 아직 문제점이 남아있습니다.

Firebase가 아닌 관계형 데이터베이스를 지원하는 back4app, AWS Amplify와 같은 서비스가 이런 프로젝트에 더 어울리는 것 같아 다음 프로젝트에서는 도입해보려 합니다.

0개의 댓글

관련 채용 정보