UIKIT
Firestore에 새로운 트윗 저장 + Combine 비동기 처리
밤새는 탐험가89
2025. 1. 9. 14:51
https://explorer89.tistory.com/304
Firestore 데이터베이스에서 문서 업데이트, Combine 비동기작업
https://explorer89.tistory.com/303 Firebase - Combine 프레임워크 사용 비동기 작업 처리 (저장) map VS flatmaphttps://explorer89.tistory.com/302 collectionUsers(retreive id: String)https://explorer89.tistory.com/301 CreateUser 함수?https
explorer89.tistory.com
func collectionTweets(dispatch tweet: Tweet) -> AnyPublisher<Bool, Error> {
db.collection(tweetsPath).document(tweet.id).setData(from: tweet)
.map { _ in true}
.eraseToAnyPublisher()
}
주어진 함수는 Firestore 데이터베이스의 특정 컬렉션(tweetsPath)에 Tweet 객체를 저장하고, Combine의 AnyPublisher로 작업 결과를 반환하는 함수입니다.
- func collectionTweets(dispatch tweet: Tweet):
- dispatch라는 이름으로 Tweet 객체를 파라미터로 받습니다.
- 이 객체를 Firestore의 tweetsPath 컬렉션에 저장합니다.
- -> AnyPublisher<Bool, Error>:
- Firestore 데이터 저장 작업의 결과를 Combine의 AnyPublisher로 반환합니다.
- 성공 시 Bool 타입의 true 값을 방출하고, 실패 시 Error를 방출합니다.
db.collection(tweetsPath).document(tweet.id).setData(from: tweet)
- db.collection(tweetsPath):
- Firestore의 tweetsPath라는 이름의 컬렉션을 참조합니다.
- tweetsPath는 Firestore에서 트윗 데이터를 저장하는 경로입니다.
- .document(tweet.id):
- tweet.id를 키로 하는 문서를 지정합니다.
- 동일한 ID의 문서가 이미 존재하면 덮어쓰기가 발생합니다.
- .setData(from: tweet):
- Firestore의 setData 메서드를 사용해 Tweet 객체의 데이터를 문서에 저장합니다.
- 이 메서드는 Encodable을 준수하는 객체(Tweet)를 Firestore에 저장할 수 있도록 지원합니다.
- Firestore에서 비동기 작업으로 실행되며, 성공 또는 실패 여부를 클로저로 전달합니다.
.map { _ in true }
.eraseToAnyPublisher()
- .map { _ in true }:
- Firestore 작업이 성공하면 반환 값을 무시하고 항상 true를 방출하도록 설정합니다.
- true는 작업이 성공적으로 완료되었음을 나타냅니다.
- .eraseToAnyPublisher():
- 반환 타입을 AnyPublisher<Bool, Error>로 제한합니다.
- 이는 호출자가 Combine 구현 세부사항에 종속되지 않도록 추상화하는 데 사용됩니다.
수정된 코드
func collectionTweets(dispatch tweet: Tweet) -> AnyPublisher<Bool, Error> {
Future<Bool, Error> { promise in
db.collection(tweetsPath).document(tweet.id).setData(from: tweet) { error in
if let error = error {
promise(.failure(error)) // Firestore 작업 실패
} else {
promise(.success(true)) // Firestore 작업 성공
}
}
}
.eraseToAnyPublisher()
}
수정 사항
- Future 사용:
- Firestore의 비동기 setData 작업을 Combine 스트림으로 감싸기 위해 Future를 사용했습니다.
- promise를 통해 작업 성공 시 true, 실패 시 Error를 반환합니다.
- 에러 처리 추가:
- Firestore 작업 실패 시 에러를 promise(.failure(error))로 처리하여 Combine 스트림에 전달합니다.
- eraseToAnyPublisher 유지:
- 반환 타입을 AnyPublisher<Bool, Error>로 제한하여 추상화를 유지합니다.
func dispatchTweet() {
guard let user = user else { return }
let tweet = Tweet(author: user, tweetContent: tweetContent, likesCount: 0, likers: [], isReply: false, parentReference: nil)
DatabaseManager.shared.collectionTweets(dispatch: tweet)
.sink { [weak self] completion in
if case .failure(let error) = completion {
self?.error = error.localizedDescription
}
} receiveValue: { [weak self] state in
self?.shouldDismissComposer = state
}
.store(in: &subscriptions)
}
주어진 함수는 dispatchTweet이라는 이름으로, Firestore에 새로운 트윗(Tweet 객체)을 저장하고, 성공/실패 여부를 Combine을 통해 처리합니다. 이전에 설명한 collectionTweets 함수를 사용하고 있으며, 트윗 저장과 관련된 비동기 작업을 수행하는 구조입니다.
func dispatchTweet() {
guard let user = user else { return }
...
}
- dispatchTweet:
- 현재 사용자가 작성한 트윗을 데이터베이스에 저장하는 함수입니다.
- 내부에서 트윗 데이터(Tweet 객체)를 생성하고, Firestore에 저장 요청을 보냅니다.
- guard let user = user:
- user가 nil이 아닌지 확인합니다. 사용자가 nil이라면 작업을 중단합니다.
- user는 현재 트윗을 작성하는 사용자를 나타냅니다.
let tweet = Tweet(author: user, tweetContent: tweetContent, likesCount: 0, likers: [], isReply: false, parentReference: nil)
- Tweet 객체 생성:
- 트윗 데이터를 표현하는 모델입니다.
- Tweet의 필드:
- author: 트윗 작성자 (현재 로그인된 사용자).
- tweetContent: 트윗 내용 (작성된 텍스트).
- likesCount: 좋아요 수 (초기값: 0).
- likers: 좋아요를 누른 사용자 목록 (초기값: 빈 배열).
- isReply: 답글 여부 (초기값: false).
- parentReference: 답글일 경우 부모 트윗의 참조 (초기값: nil).
DatabaseManager.shared.collectionTweets(dispatch: tweet)
.sink { [weak self] completion in
if case .failure(let error) = completion {
self?.error = error.localizedDescription
}
} receiveValue: { [weak self] state in
self?.shouldDismissComposer = state
}
.store(in: &subscriptions)
- DatabaseManager.shared.collectionTweets(dispatch: tweet):
- collectionTweets 함수 호출.
- Firestore의 tweetsPath 컬렉션에 Tweet 객체를 저장합니다.
- collectionTweets는 Combine의 AnyPublisher<Bool, Error>를 반환합니다.
- 성공 시: true를 방출.
- 실패 시: Firestore 오류를 방출.
- sink:
- Combine의 sink를 사용하여 비동기 작업 결과를 처리합니다.
- completion:
- 작업 완료 시 호출됩니다.
- 실패 (.failure):
- error.localizedDescription을 통해 에러 메시지를 저장하고 UI에 반영합니다.
- 성공 (.finished):
- 별도의 작업을 수행하지 않습니다.
- receiveValue:
- Firestore 저장 성공 시 호출됩니다.
- state 값을 shouldDismissComposer에 저장하여 트윗 작성 창을 닫습니다.
- store(in: &subscriptions):
- Combine 구독을 subscriptions에 저장하여 메모리 누수를 방지합니다.
- subscriptions는 Set<AnyCancellable> 타입이어야 합니다.