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는 두 개의 클로저를 받습니다:
- Completion Handler:
- completion 클로저에서 성공 또는 실패 상태를 처리합니다.
- if case .failure(let error) = completion을 통해 실패 시의 에러를 error 프로퍼티에 저장합니다.
- Value Handler:
- receiveValue 클로저에서 성공적으로 가져온 데이터를 처리합니다.
- 여기서는 Firestore에서 가져온 사용자 데이터를 user 프로퍼티에 저장합니다.
- Completion Handler:
작동 흐름
- 사용자가 로그인되어 있으면 Auth.auth().currentUser?.uid에서 uid를 가져옵니다.
- Firestore 데이터베이스에서 해당 uid에 해당하는 사용자 데이터를 가져옵니다.
- 데이터베이스 요청 성공:
- 반환된 사용자 데이터는 TwitterUser로 디코딩되어 user 프로퍼티에 저장됩니다.
- 데이터베이스 요청 실패:
- 발생한 에러는 error.localizedDescription으로 변환되어 error 프로퍼티에 저장됩니다.