firebase 의 document 가져오기

Hyun·2023년 11월 25일
0

코틀린

목록 보기
1/3
post-thumbnail

firebase에서 document 를 가져오는 2가지 방법

1. .data 사용

Review.kt

data class KeyValueElement(
    val userId: String,
    val userNickName: String,
    val content: String,
    val createdDate: Date
)


class Review()// 기본 생성자를 사용하면서 reviewList를 초기화
{
    //db에 저장된 배열을 꺼내서 여기 있는 배열의 값이랑 합쳐서 다시 넣어줘야 한다.
    var markerId: String = "" //마커 아이디
    var reviewList = mutableListOf<KeyValueElement>()//컴페니언 오브젝트는 firebase에 저장되지 않는다.


    // 리뷰를 추가하는 메서드
    fun addReview(userId: String, userNickName: String, content: String, createdDate: Date) {
        reviewList.add(KeyValueElement(userId, userNickName, content, createdDate))
    }
}

위 형식의 코틀린 클래스인 Review 형식을 firebase 에 저장한 후, 다시 가져올때는 document.data?.get("reviewList") 를 사용하여 해당 데이터를 Map<String, Any> 형태로 가져온다. 이때 as MutableList 를 통해 명시적으로 타입을 반환한다.
=> .data 로 데이터를 가져오는게 핵심

이 방식은 클래스의 구조를 몰라도 특정 필드만 가져오는 경우에 사용할 수 있다.
사용 코드는 아래와 같다.

ShowPlaceActivity.kt

//리뷰 등록 버튼  
binding.submitCommentButton.setOnClickListener {
    //입력창 내용 가져오기
    val content = binding.commentEditText.text.toString()
    val review = Review()
    review.markerId = id
    review.addReview(MainActivity.staticUserId.toString(), MainActivity.staticUserNickname, content, Date())
    //리뷰 등록
    val db = FirebaseFirestore.getInstance()
    val docRef = db.collection("reviews").document(id)
    docRef.get()
        .addOnSuccessListener { document: DocumentSnapshot ->
            if(document != null && document.exists()){
                //기존에 문서가 존재하는 경우, 기존의 reviewList 가져옴
                val existingReviewList = document.data?.get("reviewList") as MutableList<KeyValueElement>
                //새 리뷰를 기존 reviewList에 추가
                existingReviewList.addAll(review.reviewList)
                //firebase 문서 업데이트
                docRef.update("reviewList", existingReviewList)
                    .addOnSuccessListener {
                        Log.d("DB", "reviewList successfully updated in existing document!")
                    }
                    .addOnFailureListener { e ->
                        Log.d("DB", "Fail, can not updated exsisting reviewList", e)
                    }
            } else{
                //기존 문서가 존재하지 않는 경우, 새 문서 생성
                docRef.set(review)
                    .addOnSuccessListener {
                        Log.d("DB", "new reviewList successfully created!")
                    }
                    .addOnFailureListener { e ->
                        Log.w("DB", "Fail, can not create new reviewList", e)
                    }
            }
        }
}

2. toObject 사용

두번째 방법으로는 toObject 를 사용하여 Firebase 문서를 지정한 클래스의 객체로 직접 변환할 수 있다.
따라서 Review 클래스에 정의된 동일한 프로퍼티와 동일한 이름을 가진 데이터가 firebase에 있는 경우 편하게 사용할수있다.

::class.java를 사용하여 코틀린 클래스를 자바 클래스로 변환하는 이유는, firebase firestore에서 데이터를 가져올때, toObject 메서드를 사용하려면 java class 를 사용해야 해서 그렇다. 이렇게 하면 반환값으로 kotlin review 객체를 받아오게 된다.

따라서 나는 Review 코틀린 객체를 저장해서, db에서 받아올때도 document.toObject(Review::class.java) 로 받아오려 했으나!, 무슨 이유에서인지 받아올때마다 문제가 발생하였다.

=> 해결했다. toObject 도 사용할 수 있도록 하려면 Review 클래스가 "data class" 여야 한다.
(만약 toObject 를 사용하지 않는다면 일반 클래스 인스턴스를 db에 넣어도 무관하다.)

따라서 Review.kt 클래스를 데이터 클래스로 변경하면 다음과 같다. 변경 후에도 기존 코드에 영향을 미치지 않는 것을 확인했다.

Review.kt

data class KeyValueElement(
    val userId: String,
    val userNickName: String,
    val content: String,
    val createdDate: Date
)

data class Review(
    var markerId: String = "",
    var reviewList: MutableList<KeyValueElement> = mutableListOf()
) {
    fun addReview(userId: String, userNickName: String, content: String, createdDate: Date) {
        reviewList.add(KeyValueElement(userId, userNickName, content, createdDate))
    }
}
profile
better than yesterday

0개의 댓글