안녕하세요. 컴동쌤입니다. 오늘은 Firebase에 관한 포스팅입니다. Firebase에서 Database를 써보신 분들은 다 아시겠지만 Firebase는 데이터를 snapshot의 형태로 보냅니다. 해당 snapshot 안에는 데이터가 Dictionary 형식으로 들어 있습니다.
먼저 제 DB에 저장된 데이터부터 보여드릴께요. 제 DB에는 users라는 컬렉션 아래 user의 id를 이름으로 가지는 document들이 있습니다. 해당 document에는 user의 이메일, 이름, 프로필 사진 url, 프로필 메시지, 그리고 id가 저장되어 있습니다.
기존의 방식을 활용할 때는 아래처럼 모델 구조를 짜게 됩니다. 어차피 수동으로 데이터를 하나하나 넣어줄 것이기 때문에 DB의 key와 property의 이름을 맞추어 줄 필요는 없어요!
struct User: Identifiable {
let name: String
let message: String
let imageURL: String
let email: String
let id: String
}
기존의 방법은 아래와 같습니다. snapshot 안에 있는 데이터를 dictionary 형태로 가져와서 일일히 key마다 값을 가져온 뒤 User의 initializer를 통해 객체를 만들어야 합니다.
func fetchUser(id: String) {
COLLECTIONS_USERS.document(id).getDocument { snapshot, _ in
guard let dictionary = snapshot?.data() else { return }
guard let name = dictionary["name"] as? String else { return }
guard let profileMessage = dictionary["profileMessage"] as? String else { return }
guard let profileImageURL = dictionary["profileImageURL"] as? String else { return }
guard let email = dictionary["email"] as? String else { return }
guard let uid = dictionary["uid"] as? String else { return }
let user = User(name: name, message: profileMessage, imageURL: profileImageURL, email: email, id: uid)
}
}
위 과정을 새로운 Firebase의 기능을 활용해서 훨씬 간단하게 만들어 봅시다!
처음에 Firebase SDK를 설치할 때 FirebaseFirestoreSwift를 설치해주어야 합니다. (아직 Beta 버전이네요.)
모델의 정의도 기존의 방식과 달라야 합니다. 일단 Codable 프로토콜을 준수해야합니다. 그리고 DB의 key와 property의 이름이 동일해야 합니다. 아니라면 CodingKey를 통해서 별도로 정의해주어야겠죠? (저는 일단 동일하게 합니다.)
그리고 @DoumentID라는 property wrapper를 가진 property를 하나 선언해야 하는데요. 해당 property에는 document의 이름 자체가 디코딩되게 됩니다. (해당 property는 optional로 선언해주세요!)
struct User: Identifiable, Codable {
@DocumentID var id: String?
let name: String
let profileMessage: String
let profileImageURL: String
let email: String
}
이제 Codable을 준수하는 객체를 만들었으니 Decoding을 통해서 객체를 만들어 보겠습니다. 마치 JSON 데이터를 받아와서 디코딩을 하듯이 간단하게 User 객체를 만들 수 있습니다!
func fetchUser(id: String) {
COLLECTIONS_USERS.document(id).getDocument { snapshot, _ in
let user = try? snapshot?.data(as: User.self)
}
}