게시글 상세보기 뷰에서 아무 정보도 불러와지지 않는 게시글들이 있다는 걸 발견했다
파이어스토어 데이터베이스에서 확인해본 결과
문제가 생기는 부분은
"게시글 등록 시 펫을 선택해 등록했고, 이후 선택했던 펫의 프로필이 삭제된 경우" 라고 판단했다.
게시글 상세보기 뷰모델부터 차근차근 문제를 확인하다가
파이어스토어 매니저의 로직을 확인할 때 쯤
뭔가 알 거 같은데 정리가 필요할 거 같아서 이 글을 작성하게 됐다.
case let .document(id):
let documentId = (id.isEmpty && !userId.isEmpty) ? userId : id
return Single.create { [weak self] single in
self?.db.collection(query.collection.rawValue).document(documentId).getDocument { snapshot, error in
if let error = error { single(.failure(error)) }
else if let snapshot = snapshot, let data = try? snapshot.data(as: T.self) { single(.success([data])) }
else { single(.failure(NSError(domain: "NoData", code: -1))) }
}
return Disposables.create()
}
현재 파이어스토어 매니저에서 데이터를 전송하는 방법은 이렇다.
각각의 if문에 print("에러"), print("성공"), print("노 데이터")를 넣어봤다

이런 식으로 나오는데 다른 뷰들에서는 "노 데이터"가 여러 개 있어도 불러온 정보들만을 표시한다

하지만 게시글 상세보기 뷰에서는 이렇게 3개 중 하나의 데이터만 없음에도 모든 정보가 표시되지 않는다.
그래서 데이터를 처리하는 과정에서 예외처리가 필요하겠다는 생각을 했다
let pets = data.petProfile.map { pet in
FirestoreManager.shared.fetchQuery(FirestoreQuery<PetProfile>(
collection: .petProfile,
type: .document(id: pet.petProfileId)
))
.flatMap { profile -> Single<PetProfile> in
guard let profile = profile.first else { return .error(FirestoreError.noData) }
return .just(profile)
}
}
let petZip = Single.zip(pets)
return Single.zip(human, petZip)
.map { human, pet in
var post = data
post.name = human.nickname
post.profileImage = human.image
post.petProfile = pet
return post
}
현재 코드는 이런 식으로 펫 프로필들을 zip으로 만들어 사용하는데
이 중 하나만 데이터가 없어도 파이어스토어 매니저 측에서 failure로 전송하기 때문에 모두 없는 데이터가 되는 구조
그래서 파이어스토어 매니저 측에서 데이터가 없을 시 빈 배열을 전송하도록 else if문을 하나 추가했다
else if let snapshot, snapshot.exists == false { single(.success([])) }
그리고 데이터를 받는 부분에서도 profile.first를 가드문으로 거르는 작업이 있는데
이건 매니저 측에서 데이터를 배열로 보내줘서 배열을 까기 위해 만든 부분인데
빈 배열이라도 여기서 걸릴 것이기 때문에 optional을 리턴하도록 하고
추가 작업하는 부분에서 compactMap으로 거르는 방법으로 변경했다.
let pets = data.petProfile.map { pet in
FirestoreManager.shared.fetchQuery(FirestoreQuery<PetProfile>(
collection: .petProfile,
type: .document(id: pet.petProfileId)
))
.flatMap { profile -> Single<PetProfile?> in // optional 리턴
return .just(profile.first)
}
.catchAndReturn(nil)
}
let petZip = Single.zip(pets)
return Single.zip(human, petZip)
.map { human, pet in
var post = data
post.name = human.nickname
post.profileImage = human.image
post.petProfile = pet.compactMap { $0 } // nil 걸러주기
return post
}
게시글을 업로드할 때 펫의 정보와 유저의 정보를 받기 때문에
그 데이터를 그대로 불러오는 방법이였으면 이런 오류가 없었을텐데
욕심이 생겨서 유저가 사람 프로필이나 펫 프로필을 변경해도 최신 데이터를 가져올 수 있도록 구성을 해둬서 생긴 문제인 듯하다
사람 프로필은 삭제가 불가능하니 우선 이 부분에서 문제가 될 수 있는 부분은 더 이상 없을 것으로 판단 중이다