Skip to content

⚙ [기술 분석] Firebase & 랜덤 로딩

박봉팔 edited this page Nov 18, 2024 · 1 revision

Firestore기본

FirestoreCollection을 기반으로 데이터를 저장한다. Collection관계형 데이터베이스에서 말하는 Table과 유사한 개념으로 각 CollectionDocument를 사용해 데이터를 저장한다.

DoucumentRow와 비슷하게 개별 데이터를 저장하는 역할로 각 DocumentKeyValue로 이루어진 필드로 구성된다.

Firestore의 경우 NoSQL 기반의 데이터베이스이기 때문에 관계형 데이터베이스처럼 엄격한 스키마 구조를 가지지 않는다. 따라서 각 Document에 필드는 자유롭게 구성이 가능하며, Document 안에 Collection을 중첩 할 수도 있다.


Query

Firestore는 NoSQL기반의 데이터베이스지만, 기본적으로 요청시에 원하는 데이터를 가져오기 위한 간단한 쿼리를 지원한다.

where()

특정 필드의 값을 기반으로 조건에 맞는 값을 필터링 하는 메소드로, .where()로 원하는 필터 내용을 만들 수 있으며, .whereEqualTo(), .whereGreaterThan(), .whereIn()와 같이 특정 값을 기반으로 간단한 필터링을 제공하는 메소드를 사용할 수도 있다.

orderBy()

특정 필드를 기준으로 정렬하는 메소드로, .orderBy("정렬 기준이 될 필드 Key", 정렬 방향) 형식으로 사용해 기준이 될 필드와 해당 값을 기준으로 정렬하는 방향을 지정해줄 수 있다.

orderBy는 다른 쿼리 없이 사용할 경우 기준이 되는 값만 가져와 정렬해 주기 때문에 where와 잘 조합해 시용할 경우 Firestore의 탐색 횟수를 줄일 수도 있다.


데이터 다루기

단일 접근

FriestoreDocument를 기준으로 데이터가 저장되고 불러와 진다. 기본적으로 데이터에 대한 접근은 Collection을 기반으로 하며, Collection명과 Document명을 입력해 Document를 지정한 뒤 .get()메소드를 사용해 데이터를 불러올 수 있다.

val firesotre = Firebase.firestore
val postCollection = firestore.collection("post")

val postA = postCollection.document("postA").get()

Document를 지정한 뒤 데이터를 불러올 경우 DocumentSnapshot의 형태로 반환되며 해당 Snapshot에는 해당 Document에 대한 정보와 함께 저장된 데이터를 함께 반환하게 된다.

.data프로퍼티에 접근해 Map형태로 해당 데이터를 조회할 수 있으며, DocumentSnapshot에서 제공하는 .toObject() 메소드에 해당 필드에 대응되는 구조를 가진 Class형식을 입력해 객체형태로 바로 변환이 가능하다.


Query를 통한 접근

.where()이나 .orderBy()메소드를 사용해 쿼리를 사용해 데이터를 가져올 경우 QuerySnapshot의 형태로 데이터가 가져와 진다. QuerySnapshotQueryDocumentSnapshot들을 가지고 있는 값으로 쿼리를 통해 필터된 DocumentSnapshot들을 QueryDocumentSnapshot의 형태로 가지고 있다. 기본적으로 Collection과 같이 .map(), forEach()와 같은 메소드들을 제공한다.

.map() 메소드를 사용해 각 Snapshot들에 .toObject()를 사용하면 , 해당 타입의 List로 반환된다.

suspend fun getRandomPost(page: Long, perPage: Long): List<Post> {
    val result = postCollection
        .whereGreaterThan("random", page)
        .orderBy("random", Query.Direction.ASCENDING)
        .startAt(page)
        .limit(perPage)
        .get()
        .await()
        .let { q -> q.map { it.toObject(Post::class.java) } }
        // List<Post>로 반환

Random 로직 만들기

Firestore에서는 기본적으로 랜덤하게 값을 가져오는 방법이 존재하지 않는다. 따라서 클라이언트에서 랜덤하게 데이터를 가져와야 했고, 이를 구현하기 위해 각 Post에 random필드를 사용해 시드를 배정할 수 있도록 했다.

Post(
    ...
    random = (0..Long.MAX_VALUE).random()
)

이후 데이터 요청시 쿼리를 통해 랜덤한 값을 기준으로 데이터를 불러와 랜덤한 데이터를 가져온다.

val randomValue = (0..Long.MAX_VALUE).random()

val result = postCollection
    // randomValue를 기준으로 시드가 이상인 값을 가져옴
    .whereGreaterThan("random", randomValue)
    .orderBy("random", Query.Direction.ASCENDING)
    .limit(10)
    .get()

페이징 시 무제한으로 데이터를 제공하기 위해 어떤 방식을 사용할지, Random시드 관리에 대한 부분에 대해서는 추후 결정이 필요하다.

Clone this wiki locally