Swift - Firebase 사용하기 (1)
Firebase Authentication
- Firebase 사이트에서 프로젝트를 만들고,
- 해당 프로젝트에서 iOS 앱을 만들고
- GoogleService-Info.plist 파일을 추가
- 그리고 Firestore configure 코드(초기화 코드)까지 추가한 상태이다.
서버 백엔드를 따로 구축한다고 해도, Firebase Authentication은 따로 쓰는 것도 괜찮다. 왜냐하면 Firebase Authentication은 따로 만드는 것보다 더 간편하고 효율적이기 때문이다.
Firebase auth 에서 볼 수 있듯이 인증 한도도 일일 활성사용자량 3000명 정도로, 초기 앱에 사용하기에는 괜찮은 편이다.
사용자의 인증 상태를 관리하는 AuthViewModel 코드를 살펴보자.
import SwiftUI
import FirebaseAuth
final class AuthViewModel: ObservableObject {
@Published var user: User?
func listenToAuthState() {
Auth.auth().addStateDidChangeListener { [weak self] _, user in
self?.user = user
}
}
}
listenToAuthState 라는 함수를 호출 시 addStateDidChangeListener 를 통해 파이어베이스 서버로부터 인증 상태를 계속 관리할 수 있다.
사용자의 인증 상태가 변경될 때마다 호출되므로 즉 파이어베이스에서 로그인 / 로그아웃 시, 인증 상태가 변경되므로 addStateDidChangeListener가 호출된다.
그리고 해당 user가 있는지 없는 지에 따라 로그인 뷰나 컨텐츠뷰로 리디렉션하는 HolderView 를 구성하는 것부터 시작이다.
로저 내부에서 self를 약하게 캡처하여 메모리 누수를 방지한다. 이는 AuthViewModel 객체가 더 이상 필요하지 않을 때 메모리에서 해제될 수 있도록 한 것이다.
struct HolderView: View {
@EnvironmentObject var authViewModel: AuthViewModel
var body: some View {
Group {
if authViewModel.user == nil {
SignUpView()
} else {
ContentView()
}
}
.onAppear {
authViewModel.listenToAuthState()
}
}
}
그리고 로그인, 로그아웃 그리고 회원가입을 위한 function 을. 만든다. 이것도 마찬가지로 Firebase Auth 에 이미 정의되어 있는 함수를 사용하기만 하면 된다..
func signIn(emailAddress: String, password: String) {
Auth.auth().signIn(withEmail: emailAddress, password: password) { result, error in
if let error = error {
print("Error: \(error.localizedDescription)")
return
}
}
}
func signUp(emailAddress: String, password: String) {
Auth.auth().createUser(withEmail: emailAddress, password: password) { result, error in
if let error = error {
print("Create Error: \(error.localizedDescription)")
return
}
dump(result)
}
}
func signOut() {
do {
try Auth.auth().signOut()
} catch let signOutError as NSError {
print("Sign Out Error: \(signOutError.localizedDescription)")
}
}
인증된 사용자의 컨텐츠만 보이도록 하기
이번에는 Firebase Auth 와 Firebase firestore 를 함께 사용해볼 것이다.
그리고 인증된 사용자가 생성한 콘텐츠, 예를 들어 Note 라는 콘텐츠를 특정 사용자가 만든 것만 보이게 할 것이다.
그러면, 해당 note 컬렉션을 그냥 만드는 것이 아니라, User 모델 안에 note 컬렉션을 만들 수 있다.
이게 아니라,
아래와 같이 User 안에 userId 안에서 Note를 만들겠다는 것.
코드로는
// private var databaseReference = Firestore.firestore().collection("Notes")
private lazy var databaseReference: CollectionReference? = {
guard let userId = Auth.auth().currentUser?.uid else { return nil }
let ref = Firestore.firestore().collection("Users").document(userId).collection("Posts")
return ref
}()
이렇게 될 것이다.
Security roles
그리고 반드시 인증한 유저만 해당 uid의 document 만 볼 수 있도록, Firestore 규칙을 설정해줘야 한다.
service cloud.firestore {
match /databases/{database}/documents {
// your rules
match /{document=**} {
allow read, write: false;
}
match /Users/{uid}/{document=**} {
allow read, write: if uid == request.auth.uid;
}
}
}
서버에