티스토리 뷰

Firebase를 이용해 로그인 기능을 만들어보자!

1. 프로젝트에 코코아팟을 이용해 firebase 추가하기

아래표를 보고 프로젝트에서 필요한 기능을 추가해주자!

로그인 기능 사용할거니까 Core랑! Auth 요거 두개!

2. firebase에서 프로젝트 생성

https://console.firebase.google.com/u/0/

위의 링크 들어가서 프로젝트 생성!


firebase에서 프로젝트 생성 했으면 위의 이미지에서 iOS 이미지를 탭해서 iOS 앱 추가해주면 된다!


앱 번들아이디 입력해주고 등록하고!


plist 다운받아서 앱에 추가해주면된다!


요부분은 아까 위에서 추가해줬으니 넘어가자!


요렇게 앱 진입점에서 코드를 추가해주면 된다!


Authentication -> 로그인 방법 들어가서!
이메일과 비밀번호를 활성화 시켜주면된다!

이제 해당 프로젝트에서 사용될 아이디와 비밀번호는 앱에서도 만들수 있지만firebase에서도 만들수 있다!

로그인 되었다면 메인뷰를, 로그인 안되어있으면 로그인뷰를 띄워라.

현재의 로그인뷰 구성은 이렇게 되어있다!

앱을 실행했을때 로그인되어있는지, 로그인 안되어있는지를 체크한뒤 로그인 되어있지 않다면 로그인뷰를 띄워주고, 로그인 되어있다면, 앱의 메인뷰를 띄우도록 만들고 싶었다.

구조는 MVVM-C 이므로 최상단의 코디네이터 AppCoordinator 에서 체크를 하도록 했다.

func loggedinCheck() -> Bool {
    // Auth.auth().currentUser는 현재 로그인 상태를 확인해주는 프로퍼티
        return Auth.auth().currentUser == nil ? false : true
    }

요렇게 로그인 되어있는지 아닌지 메서드를 만들어주고!

final class AppCoordinator: Coordinator, LoggedinCheckable {
    var navigationController: UINavigationController
    var parentCoordinators: Coordinator?
    var childCoordinators: [Coordinator] = []
    var isLoggedIn: Bool = false

    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
        self.isLoggedIn = loggedinCheck()
    }

    func start() {
        if self.isLoggedIn {
            self.showMainView()
        } else {
            self.showLoginView()
        }
    }
}

요렇게 분기 처리를 해줬다.

로그인 하기!

2번째 뷰에서 이메일과 비밀번호를 입력후 로그인 버튼을 눌렀을경우 로그인에 성공하게되면 화면전환을, 실패한다면 Alert을 띄우도록 했다.

func didTapLogin(email: String?, password: String?) {
        self.isLoadingRelay.accept(true)
        guard let email = email else {
            self.errorRelay.accept(LoginError.checkEmail)
            return self.isLoadingRelay.accept(false)
        }

        guard let password = password else {
            self.errorRelay.accept(LoginError.checkPassword)
            return self.isLoadingRelay.accept(false)
        }

        Auth.auth().signIn(withEmail: email, password: password) { (user, error) in
            guard error == nil else {
                self.errorRelay.accept(LoginError.invalidIdentifier)
                return self.isLoadingRelay.accept(false)
            }

            if let user = user {
                //로그인 성공
                //여기서 유저정보 확인하면된다!
                self.loginRelay.accept(())
            }

            self.isLoadingRelay.accept(false)
        }
    }

여기서 중요한건 Auth.auth().signIn(withEmail: email, password: password) 요 메서드.
email과 password를 인자로 받아 성공할경우 user 데이터를 전달받고, 실패할경우 error를 전달받는다.

회원가입 하기!

위의 로그인과 비슷하다!

func didTapMembershipRegistrationButton(
        email: String?,
        password: String?,
        passwordCheck: String?
    ) {
        self.isLoadingRelay.accept(true)
        guard let email = email else {
            self.errorRelay.accept(LoginError.checkEmail)
            return self.isLoadingRelay.accept(false)
        }

        guard let password = password else {
            self.errorRelay.accept(LoginError.checkPassword)
            return self.isLoadingRelay.accept(false)
        }

        guard password == passwordCheck else {
            self.errorRelay.accept(LoginError.notEqualPassword)
            return self.isLoadingRelay.accept(false)
        }

        Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
            guard error == nil else {
                self.errorRelay.accept(LoginError.generateMembershipFail)
                return self.isLoadingRelay.accept(false)
            }

            if let user = user {
                print("회원가입 성공-----\(user.user)")
                //유저 정보
            }

            self.isLoadingRelay.accept(false)
        }
    }

텍스트필드에 입력된 정보를 체크해준뒤 Auth.auth().createUser(withEmail: email, password: password) 이녀석을 사용해 아이디를 생성해주면 된다!

회원가입이 성공하면 자동으로 로그인된다!

로그아웃 하기!

로그아웃은 간단하다!

do { try Auth.auth().signOut() }
catch { print("에러처리") }

요렇게 처리해주면된다!
로그아웃에 실패할 수 있기때문에 signOut 는 throws 함수로 되어있다.

역할분리 SignManager

로그인과, 회원가입, 로그아웃 기능을 담당할 SignManager를 만들었다!
ViewModel에서 소유할수있도록 주입해주고 메서드 호출해주면 될것같다.

import Firebase
import RxSwift

final class SignManager {
    func signOut() throws {
        return try Auth.auth().signOut()
    }

    func signIn(email: String?, password: String?) -> Observable<Void> {
        return Single.create { single in
            let verifiedEmail: String
            let verifiedPassword: String

            switch self.verifyLogin(email: email, password: password) {
            case .success((let email, let password)):
                verifiedEmail = email
                verifiedPassword = password
            case .failure(let error):
                single(.failure(error))
                return Disposables.create()
            }

            Auth.auth().signIn(withEmail: verifiedEmail, password: verifiedPassword) { (user, error) in
                guard error == nil else {
                    return single(.failure(LoginError.invalidIdentifier))
                }

                if let user = user {
                    print("로그인 성공-----\(user.user)")
                }
                single(.success(()))
            }
            return Disposables.create()
        }
        .asObservable()
    }

    func membershipRegistration(
        email: String?,
        password: String?,
        passwordCheck: String?
    ) -> Observable<Void> {
        return Single.create { single in
            let verifiedEmail: String
            let verifiedPassword: String

            switch self.verifiMembershipRegistration(
                email: email,
                password: password,
                passwordCheck: passwordCheck
            ) {
            case .success((let email, let password)):
                verifiedEmail = email
                verifiedPassword = password
            case .failure(let error):
                single(.failure(error))
                return Disposables.create()
            }

            Auth.auth().createUser(withEmail: verifiedEmail, password: verifiedPassword) { (user, error) in
                guard error == nil else {
                    return single(.failure(LoginError.generateMembershipFail))
                }

                if let user = user {
                    print("로그인 성공-----\(user.user)")
                }
                single(.success(()))
            }
            return Disposables.create()
        }
        .asObservable()
    }

    private func verifyLogin(email: String?, password: String?) -> Result<(String, String), LoginError> {
        guard let email = email else {
            return .failure(LoginError.checkEmail)
        }

        guard let password = password else {
            return .failure(LoginError.checkPassword)
        }
        return .success((email, password))
    }

    private func verifiMembershipRegistration(
        email: String?,
        password: String?,
        passwordCheck: String?
    ) -> Result<(String, String), LoginError> {
        guard let email = email else {
            return .failure(LoginError.checkEmail)
        }

        guard let password = password else {
            return .failure(LoginError.checkPassword)
        }

        guard password == passwordCheck else {
            return .failure(LoginError.notEqualPassword)
        }
        return .success((email, password))
    }
}
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/06   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
글 보관함