✅ 로그인 기능 구현
/// 이메일과 비밀번호로 로그인하는 함수
func loginUser(email: String, password: String) -> AnyPublisher<User, Error> {
return Auth.auth().signIn(withEmail: email, password: password)
.map(\.user) // ✅ authResult?.user 만 추출
.eraseToAnyPublisher()
}
✅ 특징
✔️ signIn(withEmail:password:)는 원래 Future 형태로 제공됨 → 따로 감쌀 필요 없음
✔️ map(\.user)를 사용해 authResult?.user만 반환하여 더 간결한 코드
✔️ .eraseToAnyPublisher()로 반환 타입을 AnyPublisher<User, Error>로 변환
https://explorer89.tistory.com/368
❓ Firebase 로그인 메서드 내 map의 역할
✅ map(\.user)의 역할func loginUser(with email: String, password: String) -> AnyPublisher { return Auth.auth().signIn(withEmail: email, password: password) .map(\.user) // ✅ 여기서 map이 동작 .eraseToAnyPublisher()} 🔹 Firebase의 signIn(wit
explorer89.tistory.com
✅ 회원정보를 FireStore 저장
class DatabaseManager {
// MARK: - Variable
static let shared = DatabaseManager()
let db = Firestore.firestore()
let userPath: String = "users"
// MARK: - Function
/// ✅ 회원정보를 fireStore에 저장하는 메서드
func collectionUsers(add user: User) -> AnyPublisher<Bool, Error> {
let movieClipUser = MovieClipUser(from: user)
return db.collection(userPath)
.document(movieClipUser.id)
.setData(from: movieClipUser) // ✅ 여기까지, firebase FireStore의 특정 문서에 데이터를 저장하는 비동기 작업
.map { _ in return true } // ✅ Firebase에 데이터를 저장한 후, 성공적으로 완료되었음을 나타내는 true 값을 반환
.eraseToAnyPublisher() // ✅ 타입을 AnyPublisher<Bool, Error>로 변환하여 외부에서 사용하기 쉽게 만듦
}
...
final class AuthenticationViewModel: ObservableObject {
...
/// ✅ 회원 정보를 firebase FireStore의 특정 문서에 저장하는 메서드
func createRecord(for user: User) {
DatabaseManager.shared.collectionUsers(add: user)
.sink { [weak self] completion in
switch completion {
case .failure(let error):
self?.error = error.localizedDescription
case .finished:
print("회원 정보 저장 성공")
}
} receiveValue: { state in
print("Adding user record to database: \(state)")
}
.store(in: &cancelable)
}
}
✅ FireStore에 저장한 회원정보 불러오기
class DatabaseManager {
...
/// 회원정보를 반환하는 메서드
func collectionUsers(retrieve id: String) -> AnyPublisher<MovieClipUser, Error> {
db.collection(userPath)
.document(id)
.getDocument() // ✅ 여기까지 Firestore에서 특정 문서를 가져오는 비동기 작업
.tryMap { try $0.data(as: MovieClipUser.self) } // ✅ DocumentSnapshot을 MovieClipUser 모델로 변환, 변환 실패하면 tryMap이 자동으로 에러를 throw (map은 단순 변환만 가능, 에러 throw 불가능)
.eraseToAnyPublisher()
}
}
✅ FireStore 내에 회원정보를 불러오는 데 왜 tryMap?
https://explorer89.tistory.com/370
class HomViewController: UIViewController {
...
private func bindView() {
// ✅ 회원정보 가져오기
viewModel.retrieveUser()
// ✅ 회원정보가 작성되지 않았다면 ➡️ ProfileDataFormViewController 이동
viewModel.$user
.sink { [weak self] user in
guard let user = user else { return }
if !user.isUserOnboarded {
self?.completeUserOnboarding()
}
}
.store(in: &cancelable)
}
func completeUserOnboarding() {
let profileDataFormVC = ProfileDataFormViewController()
present(profileDataFormVC, animated: true)
}
📌 회원 가입에서 프로필 작성까지 순서
회원가입 ➡️ 회원정보 저장 ➡️ 회원정보 불러오기 ➡️ 프로필 작성 창 띄우기
'Project > MovieClip' 카테고리의 다른 글
❌ 문제 해결... ProfileItem이 Hashable 및 Equatable 프로토콜을 준수하지 않는다? (0) | 2025.03.01 |
---|---|
💾 Firestore 에 유저 정보 저장 및 이미지 업로드 (0) | 2025.02.28 |
👤 Firebase에 이메일 & 비밀번호 회원가입 기능 (MVVM + Combine) (0) | 2025.02.26 |
🌟 회원 가입 화면 뷰 관리? 순서?는 어떻게 해야하나? (0) | 2025.02.26 |
❌ 문제 해결 - 검색 결과의 상세페이지 이동이 안됨.. (0) | 2025.02.24 |