24.02.24 FireBase로 데이터 저장하기

KSang·2024년 2월 24일
0

TIL

목록 보기
70/101

지난 시간에 로그인 기능에 이어 이번엔 중요한 게시물, 유저 등의 데이터를 파이어 베이스에 저장할 것이다.

파이어 베이스에서 데이터를 저장할땐 Realtime Database와, Firestore를 사용한다.

그럼 둘의 차이가 뭐고, 게시물 데이터, 유저 데이터 등은 어떤걸 사용해서 저장하는게 맞을까?

Firebase Realtime Database vs Cloud Firestore

Firebase Realtime Database

  1. 실시간: 클라이언트와 실시간으로 데이터를 동기화 한다.
    데이터베이스에 어떤 변경이 발생하면 즉시 모든 클라이언트에 이 변경사항이 푸시된다.

  2. 단일 데이터 트리: 모든 데이터가 하나의 큰 JSON 트리로 저장 된다.
    간단한 데이터 구조에는 잘 작동하지만, 복잡한 쿼리를 실행하기 어렵게 만들 수 있다.

  3. 접근 및 규칙 설정: 보안 규칙을 통해 데이터베이스 접근을 제어한다.
    그러나 쿼리 기능의 제한으로 인해 보안 규칙을 세밀하게 설정하기 어려울 수 있다.

  4. 가격 책정: 실시간 데이터베이스는 호스팅된 데이터와 네트워크 대역폭을 기반으로 비용이 청구 된다.

Cloud Firestore

  1. 확장성: Firestore는 데이터베이스 구조를 문서와 컬렉션으로 나누어 더 나은 확장성을 제공한다.
    각 문서는 컬렉션에 있으며, 문서 내에 다시 컬렉션을 가질 수 있다.

  2. 복잡한 쿼리: Firestore는 인덱싱과 복잡한 쿼리를 지원다.
    개발자는 보다 세밀하게 데이터를 조회하고 필터링할 수 있다.
    예를 들어 특정 날짜 순으로 정렬하거나, 특정 조건을 만족하는 문서만 조회하는 것이 가능하다.

  3. 다중 지역 데이터 복제: 데이터의 일관성과 안정성을 위해 자동으로 다중 지역에 걸쳐 데이터를 복제한다.
    무슨 말이냐면 글로벌 애플리케이션의 경우, 사용자가 세계 어느 곳에 있든지 간에 데이터에 빠르게 접근할 수 있도록 하며, 하나의 데이터 센터에 문제가 발생해도 다른 지역의 데이터 센터를 통해 서비스를 지속 할 수 있게 한다.

  4. 실시간 리스너: Firestore도 실시간으로 데이터 변경사항을 앱에 푸시할 수 있는 기능을 제공하지만, Realtime Database와 비교했을때 Firestore의 실시간 통신은 약간의 지연이 발생할 수 있으며, 대규모 동시 연결에는 Realtime Database가 더 최적화되어서 실시간이라는 느낌은 덜 할 수 있다.

  5. 가격 책정: Firestore는 읽기, 쓰기, 삭제 작업의 횟수와 저장된 데이터의 양, 네트워크 대역폭을 기반으로 비용이 청구된다.
    복잡한 쿼리와 더 많은 기능을 제공하지만, 비용이 더 발생할 수 있다.

비교를 해봤을때, 채팅과 같은 실시간 통신이 중요한 경우엔 Realtime Database가 적절해 보이지만

데이터를 저장하고 읽기, 쓰기, 삭제하는 경우에는 firestore가 적절하다고 생각해 firestore로 게시글, 유저정보와 같은 데이터를 저장하게 되었다.

구현

데이터 등록

class UserRepositoryImpl @Inject constructor(
    private val firebaseAuth: FirebaseAuth,
    private val firestore: FirebaseFirestore
) : UserRepository {
    override suspend fun registerUser(user: UserEntity) = suspendCoroutine { continuation ->
        firebaseAuth.currentUser?.uid?.let {
            firestore.collection(DataBaseType.USER.title).document(it).set(user)
                .addOnSuccessListener {
                    continuation.resume(DataResultStatus.SUCCESS)
                }
                .addOnFailureListener { e ->
                    continuation.resume(DataResultStatus.FAIL.apply {
                        this.message = e.message ?: "Unknown Error"
                    })
                }
        }
    }

저번에한 auth에 이어서 추가적인 유저정보를 firestore에 저장하는 코드를 만들었다.

firestore는 컬렉션으로 구별 한다,

컬렉션안에 컬렉션 명을 적어주고 거기에 데이터를 저장하면 된다.

enum class DataBaseType(
    val title: String
) {
    USER(
        title = "users"
    ),
    GROUP(
        title = "groups"
    ),
    POST(
        title = "posts"
    ),
    COMMENT(
        title = "comments"
    ),
    CHATROOM(
        title = "chatRooms"
    ),
    MESSAGE(
        title = "messages"
    )
    ,
    PRODUCT(
        title = "products"
    ),
    RECRUIT(
        title = "recruits"
    ),
    APPINFO(
        title = "app_info"
    ),
    SCHEDULE(
        title = "schedule"
    ),
}

enum으로 컬렉션명을 정리해주고 컬렉션안에 넣어준다.

그리고 문서 document를 유저의 식별자 uid로 설정한뒤, 유저 정보 userEntity를 set으로 넣어주면 파이어 스토어에 데이터가 저장된다.

데이터 불러오기

    override suspend fun getUserDetails(uid: String) = runCatching {
        firestore.collection(DataBaseType.USER.title).document(uid).get().await()
            .toObject(UserEntity::class.java)
    }.onFailure {
        Log.e("getUserDetails", "Exception while getting UserDetails: $it")
    }

불러올때는 컬렉션 명을 맞춰주고 문서부분에 식별자를 넣어준뒤 get해주면 식별자로 유저의 데이터를 얻을 수 있다.

toObject를 사용해서 userEntity형식으로 저장 받는다.

특정 필드 검색해서 불러오기

    override suspend fun getUserBySpecialty(specialty: String) = runCatching {
        firestore.collection(DataBaseType.USER.title).whereEqualTo("specialty",specialty)
            .orderBy("grade",Query.Direction.DESCENDING)
            .get().await()
            .documents.mapNotNull {
                it.toObject(UserEntity::class.java)
            }
    }.onFailure {
        return@onFailure
    }

데이터에 포함되어있는 필드로도 검색이 가능하다

whereEqualTo로 데이터에 specialty에 값이 파라미터로 입력받은 값과 같은 데이터들을 전부 불러온다.

역시나 안드로이드 스튜디오에서 전부 메소드를 지원해주니 어려움이 없었다.

다음엔 리얼타임 데이터베이스로 채팅 부분이랑 스토리지로 이미지를 올리는걸 해봐야겠다.

0개의 댓글