안녕하세요 iOS 개발자 루크입니다.
이 섹션에서는
Firebase 를 활용해 API 통신을 이해하고 활용해보도록하겠습니다
Firebase 의 여러가지 API 메서드를 알아보기전에 몇가지 알아두면 좋을 원칙을 정리해보았습니다.
1 : API 메서드는 따로 struct 화 해서 사용한다.
struct AuthService {
// 싱글톤 패턴 사용
static let shared = AuthService()
func logUserIn(withEmail email: String, password: String, completion: @escaping (AuthDataResult?, Error?) -> Void) {
//로그인 메서드
}
func registerUser(credentials: AuthCredentials, completion: @escaping (Error?, DatabaseReference) -> Void) {
// 회원가입 메서드
}
}
Swift
복사
위 예제 코드 처럼 특정 서비스와 관련된 메서드들을 하나의 struct 또는 class 로 묶어서 관리하는 것이 좋습니다.
그 중에서도 Authentication 같은 경우 싱글톤 패턴이 적합합니다 ( 앱의 어디서든 로그인, 로그아웃, 회원가입이 가능하게 하도록 함)
2 : 건네줄 파라미터가 많은 경우 struct 로 타입을 생성해 하나의 파라미터로 건네준다.
struct AuthCredentials {
let email: String
let password: String
let fullName: String
let userName: String
let profileImage: UIImage
}
func registerUser(credentials: AuthCredentials, completion: @escaping (Error?, DatabaseReference) -> Void) {
// 회원가입 메서드
}
Swift
복사
함수에 필요한 파라미터가 많아지면 코드의 가독성이 저하됩니다.
그룹의 의미를 가지는 타입을 선언해 파라미터로 건네주면 함수의 역할이 분명해집니다.
3 : escaping 클로져를 활용해 네트워킹 결과를 UI 에 반영
func registerUser(credentials: AuthCredentials, completion: @escaping (Error?, DatabaseReference) -> Void) {
let email = credentials.email
let password = credentials.password
let fullName = credentials.fullName
let userName = credentials.userName
let profileImage = credentials.profileImage
guard let imageData = profileImage.jpegData(compressionQuality: 0.3) else { return }
let filename = NSUUID().uuidString
let storageRef = STORAGE.PROFILE_IMAGES.child(filename)
storageRef.putData(imageData, metadata: nil) { meta, error in
storageRef.downloadURL { url, error in
guard let profileImageUrl = url?.absoluteString else { return }
Auth.auth().createUser(withEmail: email, password: password) { (result, error) in
if let error = error {
print("DEBUG: Error is \(error.localizedDescription) ")
return
} else {
guard let uid = result?.user.uid else { return }
let values = ["email" : email, "username": userName, "fullname": fullName, "profileImageUrl" : profileImageUrl]
//url 을 따로 따서 적어 놓을 것.
DB.REF_UESERS.child(uid).updateChildValues(values, withCompletionBlock: completion)
}
}
}
}
}
Swift
복사
위 예제 코드 처럼 네트워킹의 결과를 UI 에 반응하게 하게끔 escaping 클로져를 활용해 completion 핸들러로 비동기적인 네트워킹 요청에 대한 결과를 UI 에 적절하게 반응하게 해줍니다.
단 이경우와 같이 여러개의 네트워킹 메서드가 중첩되게 되면 분기점이 많아지고 클로져가 중첩되기 때문에 유지보수가 힘들어지므로
이는 RxSwift , Swift 의 await - async 구문 등을 사용해 해결해 보려합니다. ( 해당 부분에 대해서는 추후 포스팅과 함께 코드 리팩토링 예정)
4 : 자주 접근하게되는 URL 또는 Reference 의 경우 타입 프로퍼티로 정의해 사용합니다.
class DB {
static let URL = "https://twitterclone-3af3c-default-rtdb.asia-southeast1.firebasedatabase.app"
static let REF = Database.database(url: DB.URL).reference()
static let REF_UESERS = DB.REF.child("users")
}
class STORAGE {
static let REF = Storage.storage(url: "gs://twitterclone-3af3c.appspot.com/").reference()
static let PROFILE_IMAGES = STORAGE.REF.child("profile_images")
}
Swift
복사