UIKIT

collectionUsers(retreive id: String)

밤새는 탐험가89 2025. 1. 8. 12:32

https://explorer89.tistory.com/301

 

CreateUser 함수?

https://explorer89.tistory.com/300 AnyPublisher?https://explorer89.tistory.com/299 Combine, FirebaseStore 데이터 저장https://explorer89.tistory.com/298" data-og-description="https://explorer89.tistory.com/297 Combine을 활용한 함수https://expl

explorer89.tistory.com

 

func collectionUsers(retreive id: String) -> AnyPublisher<TwitterUser, Error> {
    db.collection(userPath).document(id).getDocument()
        .tryMap {
            try $0.data(as: TwitterUser.self)
        }
        .eraseToAnyPublisher()
}

 

함수의 역할

이 함수는 Firestore 데이터베이스에서 특정 id를 기반으로 사용자의 데이터를 가져옵니다. 가져온 데이터는 TwitterUser 타입으로 디코딩되어 반환됩니다. 반환 타입은 Combine의 AnyPublisher<TwitterUser, Error>로, 비동기적으로 데이터를 처리하며 성공 시 TwitterUser 객체를 방출하고 실패 시 Error를 방출합니다.

 

db.collection(userPath).document(id).getDocument()

  • Firestore에서 데이터를 가져오는 메서드입니다.
  • userPath는 컬렉션 이름으로, 여기서 "users"가 됩니다.
  • document(id)는 특정 문서를 지정합니다. id는 문서의 고유 식별자로 사용됩니다.
  • getDocument()는 Firestore에서 해당 문서를 비동기적으로 가져오는 작업을 수행합니다. 성공 시 문서 데이터를 반환하며, 실패 시 에러를 반환합니다.

tryMap

  • tryMap은 Combine에서 제공하는 연산자로, 방출된 데이터를 변환하면서 오류를 던질 수 있는 클로저를 실행할 수 있습니다.
  • Firestore에서 가져온 문서 데이터를 TwitterUser 타입으로 변환합니다. 
tryMap {
    try $0.data(as: TwitterUser.self)
}

 

 

  • $0는 Firestore에서 가져온 문서를 나타냅니다.
  • data(as:):
    • Firestore SDK에서 제공하는 메서드로, 문서 데이터를 특정 타입(여기서는 TwitterUser)으로 디코딩합니다.
    • 문서가 없는 경우 또는 디코딩이 실패하면 Error를 던집니다.
    • tryMap 덕분에 이 과정에서 발생한 에러가 상위로 전파되어, 함수의 결과로 에러를 방출할 수 있게 됩니다.

위의 후행 클로저를 풀어서 쓴다면?

tryMap { documentSnapshot in
    do {
        let twitterUser = try documentSnapshot.data(as: TwitterUser.self)
        return twitterUser
    } catch {
        throw error
    }
}

 

 

 

  • 후행 클로저 구조:
    • 클로저의 인자로 Firestore에서 가져온 documentSnapshot 객체가 전달됩니다.
    • 이 객체에서 데이터를 꺼내고, TwitterUser로 변환하려는 작업을 수행합니다.
  • try:
    • documentSnapshot.data(as: TwitterUser.self)는 TwitterUser로 변환을 시도합니다.
    • 변환 중에 실패하면 에러를 던지고, 상위 tryMap 연산자가 이 에러를 처리하도록 합니다.
  • do-catch 블록:
    • 데이터 변환 중 에러가 발생할 수 있으므로, 명시적으로 do-catch를 사용해 에러를 처리하고 다시 상위로 던질 수 있습니다.
    • throw error를 사용하여 에러를 상위 Combine 스트림으로 전파합니다.

 

import Foundation
import Combine
import FirebaseAuth

final class HomeViewViewModel: ObservableObject {
    
    @Published var user: TwitterUser?
    @Published var error: String?
    
    private var subscription: Set<AnyCancellable> = []
    
    func retreiveUser() {
        guard let id = Auth.auth().currentUser?.uid else { return }
        DatabaseManager.shared.collectionUsers(retreive: id)
            .sink { [weak self] completion in
                if case .failure(let error) = completion {
                    self?.error = error.localizedDescription
                }
            } receiveValue: { [weak self] user in
                self?.user = user
            }
            .store(in: &subscription)
    }
}

 

위의 retreiveUser 함수는 Firebase Firestore 데이터베이스에서 현재 사용자의 정보를 가져와 user 프로퍼티에 할당하는 역할을 합니다. 이 과정을 Combine을 활용해 비동기적으로 처리하고, 에러 발생 시 이를 처리하는 구조로 작성되어 있습니다.

 

 

guard let id = Auth.auth().currentUser?.uid else { return }

  • Firebase Authentication을 통해 현재 로그인한 사용자의 uid를 가져옵니다.
  • Auth.auth().currentUser가 nil이면 사용자가 로그인하지 않은 상태이므로 함수를 종료합니다.

DatabaseManager.shared.collectionUsers(retreive: id)

  • DatabaseManager의 collectionUsers(retreive:) 메서드를 호출하여, 주어진 uid를 기반으로 Firestore에서 사용자 데이터를 가져옵니다.
  • 이 메서드는 AnyPublisher<TwitterUser, Error>를 반환하므로, Combine의 구독(subscribe)을 통해 결과를 처리합니다.

 

.sink { completion in ... } receiveValue: { user in ... }

  • .sink는 Combine에서 Publisher를 구독(subscribe)하고, 그 결과를 처리하는 클로저를 제공합니다.
  • sink는 두 개의 클로저를 받습니다:
    1. Completion Handler:
      • completion 클로저에서 성공 또는 실패 상태를 처리합니다.
      • if case .failure(let error) = completion을 통해 실패 시의 에러를 error 프로퍼티에 저장합니다.
    2. Value Handler:
      • receiveValue 클로저에서 성공적으로 가져온 데이터를 처리합니다.
      • 여기서는 Firestore에서 가져온 사용자 데이터를 user 프로퍼티에 저장합니다.

 

작동 흐름

  1. 사용자가 로그인되어 있으면 Auth.auth().currentUser?.uid에서 uid를 가져옵니다.
  2. Firestore 데이터베이스에서 해당 uid에 해당하는 사용자 데이터를 가져옵니다.
  3. 데이터베이스 요청 성공:
    • 반환된 사용자 데이터는 TwitterUser로 디코딩되어 user 프로퍼티에 저장됩니다.
  4. 데이터베이스 요청 실패:
    • 발생한 에러는 error.localizedDescription으로 변환되어 error 프로퍼티에 저장됩니다.