Skip to content

Firebase SDK → Rest API 변경에 따른 업데이트 로직 수정 이야기

백지현 edited this page Mar 3, 2022 · 1 revision

Firebase SDK를 이용한 Update 로직 구현

  • 프로젝트에 데이터를 Fetch 해오는 로직은 있었지만 Update하는 로직은 구현되지 않았었기 때문에, 이에 대한 학습과 프로젝트 적용 과정이 필요했습니다. 다행히 Firebase SDK를 활용한 업데이트는 Firebase 공식문서에 잘 안내되어 있었기 때문에 이를 활용해 어렵지 않게 구현이 가능했습니다.

    // #1 
    db.collection("challenge")
       .whereField("id", isEqualTo: challenge.id)
       .whereField("owner_id", isEqualTo: challenge.ownerID)
       .getDocuments { (result, error) in
           guard let result = result, error == nil else { return }
           guard let document = result.documents.first else { return }
           // #2
           db.collection("challenge").document(document.documentID).setData([
               "auth_example_image_url": challenge.authExampleImageURL,
               "auth_method": challenge.authMethod,
               "category_id": challenge.categoryID,
               "desc": challenge.desc,
               "end_date": challenge.endDate,
               "id": challenge.id,
               "image_url": challenge.imageURL,
               "owner_id": challenge.ownerID,
               "participant_count": challenge.participantCount,
               "start_date": challenge.startDate,
               "thumbnail_image_url": challenge.thumbnailImageURL,
               "title": challenge.title,
               "week": challenge.week
             ], merge: true)  // #3
       }
    • #1: 컬렉션의 필드값과 같은 문서를 찾습니다.
    • #2: 해당 문서의 documentID를 이용해 데이터를 변경시켜줍니다.
    • #3: 기존의 문서와 병합하기 위해서는 merge 옵션을 true로 맞춰줍니다.
  • firestorage에 이미지 업데이트 시키기

    let storage = Storage.storage().reference()
    
    let imageReference = storage.child("\(challenge.id)/image.jpeg")
    guard let imageURL = URL(string: challenge.imageURL) else { return }
    imageReference.putFile(from: imageURL, metadata: nil)
    
    let authExampleImageReference = storage.child("\(challenge.id)/auth.jpeg")
    guard let authExampleImageURL = URL(string: challenge.authExampleImageURL) else { return }
    authExampleImageReference.putFile(from: authExampleImageURL, metadata: nil)
    • firestorage에 이미지 업데이트 시키는 로직은 기존에 firestorage에 이미지 넣는 로직과 동일하였기 때문에 그대로 사용하였습니다.

Firebase SDK를 제거하고 Rest API를 활용하는 과정에서 Update 로직 변경 작업

  • 빌드 속도 개선을 위해 Firebase SDK를 제거하고 Rest API를 활용하여 네트워크 요청이 일어나도록 수정됨에 따라 완성된 Update 로직도 변화시켜야 했습니다. 하지만, Firebase SDK를 활용해 업데이트 시키는 것보다 참고자료를 찾기가 어려웠던 문제를 겪었습니다. 따라서 기존의 Firebase SDK를 활용해 업데이트한 구현 과정을 되돌아보면서 어떤 것이 필요할 것이라고 예상을 한 다음에, 파편화된 자료를 하나씩 찾아나서 REST API로 수정하는 로직을 구현할 수 있었습니다.

  • SDK를 활용해 Update로직을 짰을 때도 documentID를 활용해 작업하였기 때문에 Rest API를 활용해 Update 하는 것도 documentID를 활용해서 Update 시킬것으로 예상했었습니다. 그래서 가장 먼저 챌린지를 fetch해 documentID를 가져오는 작업부터 하였습니다.

  • Postman으로 challenge를 fetch해온 결과 document의 name의 마지막 component가 documentID인 것을 확인하였습니다.

    스크린샷 2021-12-04 오후 6 55 28

    따라서, Challenge DTO에 documentID 프로퍼티를 추가하였습니다.

    var documentID: String? {
        return self.document?.name?.components(separatedBy: "/").last
    }
  • Firebase REST API 통신을 위해 데이터 업데이트를 위한 URL을 만들어주어야 했습니다. URL은 참고자료를 활용해 만들었습니다.

    // #1 
    guard let findChallenge = try? await challenge(ownerID: ownerID, challengeID: challengeID),
    let documentID = findChallenge.documentID else { return }
    
    // #2 
    var urlComponent = URLComponents(string: "\(firestoreURL)/challenge/\(documentID)?")
    • #1: 찾고자하는 챌린지를 가져와서, 해당 챌린지의 documentID를 가져옵니다.
    • #2: 해당 챌린지 업데이트를 요청할 URL을 만들어줍니다.
  • 업데이트할 필드를 쿼리 매개변수로 붙여주어야 했습니다. 따라서 URL은 urlComponents를 이용해 만들었으며, 쿼리는 URLQueryItem을 활용해 urlcomponent에 쿼리를 더해주었습니다. 참고문서에 나온 대로 따라서 해보았으나, 데이터가 업데이트되지 않았습니다. 해당 내용은 stackoverflow의 검색 내용에 따라 작업해주었습니다.

    let queryItems = [URLQueryItem(name: "updateMask.fieldPaths", value: "auth_method"),
        URLQueryItem(name: "updateMask.fieldPaths", value: "category_id"),
        URLQueryItem(name: "updateMask.fieldPaths", value: "title"),
        URLQueryItem(name: "updateMask.fieldPaths", value: "desc"),
        URLQueryItem(name: "updateMask.fieldPaths", value: "week"),
        URLQueryItem(name: "updateMask.fieldPaths", value: "end_date"),
    ]
    urlComponent?.queryItems = queryItems
    guard let url = urlComponent?.url else { return }
  • 전체 데이터를 변경하는게 아니라 일부 데이터를 변경하기 위해서는 PATCH HTTP Method를 이용해야했습니다.

    var request = URLRequest(url: url)
    request.addValue("text/plain", forHTTPHeaderField: "Content-Type")
    request.httpMethod = HTTPMethod.patch.rawValue
    
    request.httpBody = RoutinusQuery.updateChallenge(document: challengeField)
    
    try await URLSession.shared.data(for: request)
  • 성공적으로 REST API를 활용해 챌린지를 업데이트 시킬 수 있었습니다.

  • 주말 추가 작업을 통해 Firebase SDK를 활용해 업데이트 로직을 구현하였음에도 불구하고, REST API로 네트워크 구조가 변경되면서 주말 작업이 물거품이 된 것과 부족한 자료 덕분에 업데이트 로직을 수정하는데 꼬박 하루를 쓰는 등의 어려움을 겪었었지만, 팀원들이 업데이트 로직을 구현할 때 참고할 레퍼런스 코드를 만들 수 있어서 뿌듯했던 순간이라 기억이 많이 남습니다.

Clone this wiki locally