UIKIT
Combine, FirebaseStore 데이터 저장
밤새는 탐험가89
2025. 1. 8. 11:54
https://explorer89.tistory.com/298
eraseToAnyPublisher(), Set<AnyCancellable>
https://explorer89.tistory.com/297 Combine을 활용한 함수https://explorer89.tistory.com/296 viewModel.$user에서 user 앞에 $를 붙이는 이유https://explorer89.tistory.com/295 ViewModel을 사용하는 목적https://explorer89.tistory.com/294
explorer89.tistory.com
import Foundation
import Firebase
import FirebaseFirestoreCombineSwift
import FirebaseFirestore
import FirebaseAuth
import Combine
class DatabaseManager {
static let shared = DatabaseManager()
let db = Firestore.firestore()
let userPath: String = "users"
func collectionUsers(add user: User) -> AnyPublisher<Bool, Error> {
let twitterUser = TwitterUser(from: user)
return db.collection(userPath).document(twitterUser.id).setData(from: twitterUser)
.map { _ in
return true
}
.eraseToAnyPublisher()
}
}
위의 DatabaseManager 클래스는 Firebase Firestore와 Firebase Authentication을 사용하여 사용자 데이터를 Firestore 데이터베이스에 저장하는 기능을 제공합니다. 이를 위해 Combine 프레임워크를 사용하여 비동기 작업을 처리하고, 반환 타입으로 AnyPublisher<Bool, Error>를 사용합니다. 이제 코드의 각 부분을 자세히 설명하겠습니다.
클래스 선언과 공유 인스턴스
class DatabaseManager {
static let shared = DatabaseManager()
- DatabaseManager 클래스는 싱글톤 패턴을 사용하여 하나의 인스턴스를 공유합니다. 이를 통해 앱 전체에서 DatabaseManager를 한 번만 초기화하고 재사용할 수 있습니다.
- shared는 DatabaseManager 클래스의 인스턴스를 반환하는 정적 속성입니다. 이 속성을 통해 어디서든 DatabaseManager.shared를 사용하여 인스턴스에 접근할 수 있습니다.
Firestore 데이터베이스와 사용자 경로
let db = Firestore.firestore()
let userPath: String = "users"
- db: Firestore의 인스턴스를 가져와서 db 변수에 할당합니다. 이 인스턴스를 사용하여 Firestore 데이터베이스와 상호작용합니다.
- userPath: Firestore에서 사용자의 데이터를 저장할 컬렉션 경로입니다. 이 예제에서는 users라는 컬렉션에 사용자 데이터를 저장한다고 가정하고 있습니다.
사용자 데이터 추가 함수 - collectionUsers(add:)
이 함수는 Firebase Firestore에 사용자 데이터를 추가하는 작업을 수행합니다.
func collectionUsers(add user: User) -> AnyPublisher<Bool, Error> {
let twitterUser = TwitterUser(from: user)
return db.collection(userPath).document(twitterUser.id).setData(from: twitterUser)
.map { _ in
return true
}
.eraseToAnyPublisher()
}
let twitterUser = TwitterUser(from: user)
- user는 입력으로 받는 사용자 객체입니다. 이 객체는 User 타입으로 추정됩니다. User 객체는 다른 타입의 사용자 모델일 수 있으며, 이를 TwitterUser로 변환하여 Firestore에 저장할 수 있는 형태로 만듭니다.
- TwitterUser(from: user)는 User 객체를 TwitterUser 객체로 변환하는 초기화 메서드일 것입니다. 이 과정에서 User 모델의 데이터를 TwitterUser 모델로 매핑하는 로직이 있을 것입니다.
db.collection(userPath).document(twitterUser.id).setData(from: twitterUser)
- db.collection(userPath): Firestore의 users 컬렉션을 참조합니다.
- document(twitterUser.id): 해당 컬렉션 내에서, twitterUser 객체의 id를 사용하여 문서를 식별합니다. 이 id는 해당 사용자의 고유 식별자로 사용됩니다.
- setData(from: twitterUser): twitterUser 객체의 데이터를 Firestore 문서에 저장합니다. setData는 TwitterUser 객체를 Firestore 문서에 맞게 자동으로 변환하여 저장합니다. (Firestore는 Codable을 준수하는 객체를 자동으로 처리할 수 있습니다.)
.map { _ in
return true
}
- map: setData(from:)의 반환값을 처리합니다. setData(from:)는 Void를 반환하며, 이 메서드는 Firestore에 데이터를 성공적으로 저장했을 때 호출됩니다. map을 사용하여 반환값을 true로 변환합니다. true는 데이터가 성공적으로 저장되었음을 나타내며, 이후의 처리에서 사용됩니다.
.eraseToAnyPublisher()
- eraseToAnyPublisher: AnyPublisher로 타입을 추상화합니다. setData(from:)는 기본적으로 Publishers.Create나 다른 형태의 Publisher를 반환할 수 있지만, 반환 타입을 AnyPublisher로 변환하여 외부에서 사용할 수 있도록 합니다. 이렇게 하면 반환 타입을 구체적으로 알 필요 없이 Publisher를 다룰 수 있습니다.
-> AnyPublisher<Bool, Error>
- 이 함수는 비동기적으로 데이터를 추가하고, 그 결과를 Publisher로 반환합니다. 반환 타입은 AnyPublisher<Bool, Error>입니다. Bool 값은 성공 여부를 나타내며, Error는 오류가 발생했을 때 전달됩니다.
- AnyPublisher<Bool, Error>는 반환 값이 Bool이고 오류가 발생할 수 있다는 것을 나타냅니다. 성공 시에는 true, 실패 시에는 오류를 반환합니다.
전체적인 흐름
- collectionUsers(add:) 함수는 사용자 데이터를 받으면, 이 데이터를 TwitterUser로 변환합니다.
- Firestore의 users 컬렉션에 해당 사용자의 데이터를 저장합니다.
- 데이터가 성공적으로 저장되면 true를 반환하고, 이를 Publisher 형태로 감싸서 반환합니다.
- AnyPublisher는 비동기 작업을 다루며, sink나 receiveValue 등의 Combine 연산자로 후속 작업을 처리할 수 있게 합니다.