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, 실패 시에는 오류를 반환합니다.

 

전체적인 흐름

  1. collectionUsers(add:) 함수는 사용자 데이터를 받으면, 이 데이터를 TwitterUser로 변환합니다.
  2. Firestore의 users 컬렉션에 해당 사용자의 데이터를 저장합니다.
  3. 데이터가 성공적으로 저장되면 true를 반환하고, 이를 Publisher 형태로 감싸서 반환합니다.
  4. AnyPublisher는 비동기 작업을 다루며, sink나 receiveValue 등의 Combine 연산자로 후속 작업을 처리할 수 있게 합니다.