카테고리 없음

Troubleshooting: 게시글 상세보기 화면에서 펫 프로필 데이터 누락 시 모든 정보가 표시되지 않는 이슈

ghnn 2026. 1. 6. 15:48

게시글 상세보기 뷰에서 아무 정보도 불러와지지 않는 게시글들이 있다는 걸 발견했다

파이어스토어 데이터베이스에서 확인해본 결과

문제가 생기는 부분은

"게시글 등록 시 펫을 선택해 등록했고, 이후 선택했던 펫의 프로필이 삭제된 경우" 라고 판단했다.

 

게시글 상세보기 뷰모델부터 차근차근 문제를 확인하다가

파이어스토어 매니저의 로직을 확인할 때 쯤

뭔가 알 거 같은데 정리가 필요할 거 같아서 이 글을 작성하게 됐다.


        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
            }

게시글을 업로드할 때 펫의 정보와 유저의 정보를 받기 때문에

그 데이터를 그대로 불러오는 방법이였으면 이런 오류가 없었을텐데

욕심이 생겨서 유저가 사람 프로필이나 펫 프로필을 변경해도 최신 데이터를 가져올 수 있도록 구성을 해둬서 생긴 문제인 듯하다

사람 프로필은 삭제가 불가능하니 우선 이 부분에서 문제가 될 수 있는 부분은 더 이상 없을 것으로 판단 중이다