티스토리 뷰
개인 프로젝트를 하다보면 서버 개발자가 없을 때 데이터들을 저장할 곳이 필요하다.
그래서 Firebase를 사용하여 데이터들을 관리하게 되는데 사용하기 전에 RDBMS와 NoSQL에 대해 알아보고자 한다.
먼저 내가 생각하는 둘의 느낌을 보자면 아래 사진 같다.
사진예시가 많이 아쉬운데 적절한 사진을 잘 못찾았다.
RDBMS는 잘 정리되고 관계적으로 데이터가 연결되어있는 느낌이라면,
NoSQL은 흩뿌려진 느낌으로 정리가 되지 않는 느낌이다.
먼저 데이터를 저장하는 프로그램 중 하나인 RDBMS를 알아보자.
Relational DataBase Management System의 줄임말로 모든 데이터들이 관계되어있는 구조를 뜻한다.
테이블 형식으로 데이터를 구성하는데
Jero가 한국은행의 서울카드를, 네로가 한국은행의 부산카드를 사용하고 있다고 가정해보자.
위 표처럼 관계형 데이터 베이스는 같은 의미를 가지는 값의 논리적인 연결을 통해 설계하는 방식이다.
열과 행의 순서는 중요하지 않다고 한다.
장점은,
명확하게 데이터 구조를 손 쉽게 설계할 수 있고, 필요한 데이터들만 조회하여 가져올 수 있다.
(개인적인 생각이지만 개발자가 편하게 코드를 짤 수 있다...)
단점은,
전체 조회가 어렵고, 서로 관계를 맺고 있어서 분리를 시킬 수 없다.
DB가 커질 경우 서버의 성능을 무한정 향상시켜야한다.
그렇다면 NoSQL은 어떨까?
NoSQL의 특징 중 하나는 RDBMS 경우에는 관계를 지어 똑같은 정보를 담고 있어야 하는데
데이터 간의 관계를 정의하지 않아 조금 더 유동적으로 스키마를 짤 수 있어 데이터들을 관리하기 좋고,
RDBMS에 비해 훨씬 더 대용량의 데이터를 저장할 수 있다.
NoSQL의 종류 중 하나인 Firebase Firestore에 대해 정리하고자 한다.
Firebase Firestore는 컬렉션과 그 안에있는 문서들로 데이터를 관리한다.
데이터가 변경되거나 특정 문서의 특정 필드의 값만 넣고 싶을 때에도 가능하다.
예를 들자면 폴더가 있으면 폴더가 컬렉션이고 폴더 안의 파일들이 문서라고 생각하면 된다. (엄밀히 말하자면 조금 결이 다를 수도 있지만)
또 컬렉션 안의 하위 컬렉션으로 데이터들을 관리할 수 있어서 매우 자유롭다.
하지만 이런 방식에는 단점이 있다.
자유로운 만큼 관리하기는 까다롭고 복잡해진다.
음식점의 정보를 보여주는 것이 목적인 앱이 있다고 가정해보자.
강남구 소재의 A음식점, 종로구 소재의 B음식점, 성북구 소재의 C음식점에 대한 정보를 데이터로 들고 있다.
이 때, 사용자들이 각각의 음식점에 리뷰를 남기고 싶어할 때 각각의 음식점마다 subCollection으로 리뷰를 가지고 있게하면 된다.
만약 서울시 음식점 컬렉션 안에 다큐먼트로 A음식점 정보를 들고 있고,
하위 컬렉션인 리뷰에서 평점이 4.5점이상인 리뷰를 조회하여 데이터를 가져오기 어렵지 않다.
그런데 만약 다수의 기능이 들어있는 커뮤니티 앱을 만들 때에는 주의해야하는 사항들이 있다.
유저에게 종속되어 있는 데이터들이 많기 때문에 유저의 데이터를 들고 있는 다큐먼트에서 하위 컬렉션을 만들어서 관리해줘야할 때가 있다.
그렇게 되면 유저의 정보를 가지고 있는 Users에 많은 하위 컬렉션이 생길 것이고,
다른 유저가 쓴 글에 대한 조회를 어떻게 할 지, 다른 유저 게시글에 내가 댓글을 단 것을 어떻게 수정할 지 등.. 코드짜기가 번거롭고 어려워진다. 이게 단점이라면 단점이다.
다시 정리하자면
장점은,
언제든지 저장된 데이터를 조정하고, 새로운 필드를 추가해서 데이터 구조를 유동적으로 짤 수 있다.
독립적으로 데이터가 분리되어 있어서 데이터들을 나누어 관리할 수 있어 RDBMS의 단점을 해결할 수 있다.
단점은,
데이터 중복이 발생할 수 있으며 중복된 데이터가 변경 될 경우 수정을 모든 컬렉션에서 수행을 해야 한다.
스키마가 존재하지 않기에 명확한 데이터 구조를 보장하지 않으며 데이터 구조 결정가 어려울 수 있습니다.
개발자가 코드를 짜기 번거롭고, 어려워진다는 점?
그리고 음식점에 리뷰를 쓸 때에도 유저의 닉네임과 프로필 이미지와 같은 데이터의 복제가 일어나기 때문에
유저가 프로필 사진을 변경하거나 닉네임을 변경할 때, 모든 게시글에 추가적으로 업데이트를 해줘야한다는 점이다.
자 그러면 Firebase Firestore 데이터 구조 방식은 어떤 게 있을까?
1. 필드에 다 때려박는 데이터 구조
상위 20개의 레스토랑을 검색한다고 할 때 위와 같은 방법은 좋지 않다.
이유는 레스토랑에 대한 모든 정보를 확인하고,
안에 필드로 있는 review에 대한 정보들까지 불필요하게 조회하여 불러오기 때문이다.
그리고 데이터 용량 제한 또는 4000필드 제한과 같은 이슈에 부딪힐 것이다.
모든 리뷰가 포함된 거대한 레스토랑 문서만 반환될 것이고,
해당 리뷰에 대한 정보를 필터링을 하고자하면 클라이언트에서 수행하는 것에 따라
리뷰를 별도의 컬렉션에 보관하는 것이 올바른 방법이라고 생각한다.
2. Top-Level 방식 (별도의 최상위 컬렉션에 있는 경우)
collection("Review")
.where("restaurantId", "==", "샐러드 포케집")
.orderBy("date", "desc") // 예시로 보여준 필드에는 date라는 필드는 없지만... 이런 식으로도 쓸 수 있다.
300만개의 리뷰가 있는 단일 컬렉션에서 하나의 레스토랑에 대한 모든 리뷰를 가져오는데에
단일 하위 컬렉션에서 모든 리뷰를 가져오는 것과 본질적으로 같은 시간이 걸린다.
장점은 최상위 컬렉션에 모든 것을 넣으면 개별 작성자의 모든 리뷰를 검색할 수 있는 것처럼
여러 레스토랑에 걸친 리뷰를 검색할 수 있다는 것이다.
하지만 예시 상황에서처럼 보통은 음식점 리뷰를 볼 때는 특정 음식점에 대한 리뷰만 보기 때문에
모든 리뷰들을 보고 싶어하지는 않을 것이라고 생각해 이럴 때 종속된 하위 컬렉션으로 빼는 방법도 좋을 것 같다.
3. 해당 문서에 대해 하위 컬렉션으로 빼기
collection("Restaurant/DocumentID/Reviews")
.orderBy("date", "desc") // 예시로 보여준 필드에는 date라는 필드는 없지만... 이런 식으로도 쓸 수 있다.
위와 같이 따로 별도의 하위 컬렉션에서 관리하는 방법이 있다.
2번 Top-Level 방식 (별도의 최상위 컬렉션에 있는 경우)처럼
where절로 전체 리뷰에 대해 조회하고, 필터링해주는 것이 아닌 특정 음식점의 하위 컬렉션에 대한 것만 조회가 가능하다는 장점이 있다.
또한 만약에 내가 쓴 리뷰에 대해 모든 정보를 보여주고 싶으면 Firebase에서 제공해주는
CollectionGroup을 통해 보여줄 수 있다.
CollectionGroup("Reviews") 이렇게 컬렉션 이름만 같으면 Reviews라는 컬렉션에 대해 전체 조회가 가능하다.
이처럼 해당 예시에서처럼 모든 레스토랑에 대한 리뷰들을 보여주는 횟 수나 내가 쓴 리뷰들을 모아서 보여주는 횟 수가
특정 레스토랑에 대한 리뷰들을 보는 횟 수보다 많은지 적은 지에 따라 데이터 구조는 유동적으로 짤 수 있다.
하고자 하는 서비스의 방향에 따라 합리적인 선택을 하면 좋을 것 같다!
왜냐하면 모든 것은 다 비용이기 때문에.....
우선 이 글은 여기서 마무리하겠다.
'Firebase' 카테고리의 다른 글
Firebase - Firestore CollectionGroup 뽀개는 중.. (0) | 2023.01.13 |
---|