관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 로그인 화면 전환 설계 방법 (자동 로그인, autoSignIn, Firebase Auth 로그인) 본문

iOS 응용 (swift)

[iOS - swift] 로그인 화면 전환 설계 방법 (자동 로그인, autoSignIn, Firebase Auth 로그인)

jake-kim 2021. 11. 18. 23:40

로그인 화면전환 플로우

  • AppController라는 모듈을 만들어서 사용
    • singleton으로 구현 
    • AppDelegate에서 호출
    • NotificationCenter로 auth 상태가 바뀐이벤트를 구독하고 있다가, auth 상태가 바뀌면 로그인이 되었는지 확인 후 rootViewController에 화면 입력
  • 로그인 상태가 바뀐 noti를 파악하기 위해 Notification.Name에 authStateDidChange 이름 추가
import Foundation

extension Notification.Name {
    static let authStateDidChange = NSNotification.Name("authStateDidChange")
}
  • AppController 구현
    • singleton
    • 초기화 시 NotificationCenter 구독
final class AppController {
    static let shared = AppController()
    private init() {
        registerAuthStateDidChangeEvent()
    }
    
    private func registerAuthStateDidChangeEvent() {
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(checkLoginIn),
                                               name: .authStateDidChange,
                                               object: nil)
    }
    
    @objc private func checkLoginIn() {
        let isSignIn = UserDefaults.standard.bool(forKey: "isSignIn") == true
        if isSignIn {
            setHome()
        } else {
            routeToLogin()
        }
    }
}
  • window와 rootViewController를 가지고 있어서, 화면전환을 바로할 수 있도록 설계
private var window: UIWindow!
private var rootViewController: UIViewController? {
    didSet {
        window.rootViewController = rootViewController
    }
}

private func setHome() {
    let homeVC = HomeVC()
    rootViewController = UINavigationController(rootViewController: homeVC)
}

private func routeToLogin() {
    rootViewController = UINavigationController(rootViewController: LoginVC())
}
  • AppController 전체 코드
final class AppController {
    static let shared = AppController()
    private init() {
        registerAuthStateDidChangeEvent()
    }
    
    private var window: UIWindow!
    private var rootViewController: UIViewController? {
        didSet {
            window.rootViewController = rootViewController
        }
    }
    
    func show(in window: UIWindow) {
        self.window = window
        window.backgroundColor = .systemBackground
        window.makeKeyAndVisible()
        
        checkLoginIn()
    }
    
    private func registerAuthStateDidChangeEvent() {
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(checkLoginIn),
                                               name: .authStateDidChange,
                                               object: nil)
    }
        
    @objc private func checkLoginIn() {
        let isSignIn = UserDefaults.standard.bool(forKey: "isSignIn") == true
        if isSignIn {
            setHome()
        } else {
            routeToLogin()
        }
    }
    
    private func setHome() {
        let homeVC = HomeVC()
        rootViewController = UINavigationController(rootViewController: homeVC)
    }

    private func routeToLogin() {
        rootViewController = UINavigationController(rootViewController: LoginVC())
    }
    
}
  • AppDelegate에서 show(in:) 메소드 호출
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        let window = UIWindow(frame: UIScreen.main.bounds)
        self.window = window
        AppController.shared.show(in: window) // <- 여기
        
        return true
    }
}

로그인하는 쪽 코드

  • NotificationCenter로 로그인되었음을 알림
@objc func didTapLoginButton() {
    UserDefaults.standard.set(true, forKey: "isSignIn")
    NotificationCenter.default.post(name: .authStateDidChange, object: nil)
}

Firebase Authentication에서의 로그인

  • Firebase의 Authentication에서도 원리는 똑같고, Notification.Name의 `AuthStateDidChnage`값으로 내부적으로 제공
  • Firebase SDK 다운 (SPM 사용)
https://github.com/firebase/firebase-ios-sdk.git
  • `FirebaseAuth` 체크

  • Firebase에 앱 추가 후 GoogleService-Info.plist 다운, 프로젝트에 추가

  • Firebase Authentication 선택 후 시작하기 클릭 (아래 화면은 시작하기 화면을 누른 후 로그인을 여러번 시도한 경우)

AppController에 Firebase auth 관련 코드 반영

  • Firebase 초기화 코드 추가
// AppController.swift

private init() {
    FirebaseApp.configure() // <- Fierbase 초기화
    registerAuthStateDidChangeEvent()
}
  • Firebase auth 변경 관련 이벤트 구독
    • .AuthStateDidChange: Firebase SDK 내부에서 제공
// AppController.swift

private func registerAuthStateDidChangeEvent() {
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(checkLoginIn),
                                           name: .AuthStateDidChange, // <- Firebase Auth 이벤트
                                           object: nil)
}
  • Firebase의 currentUser값을 가지고 자동로그인 판별
// AppController.swift

@objc private func checkLoginIn() {
    if let user = Auth.auth().currentUser { // <- Firebase Auth
        print("user = \(user)")
        setHome()
    } else {
        routeToLogin()
    }
}
  • 로그인화면에서 로그인 버튼을 클릭한 경우 Firebase를 통한 로그인 시도
@objc func didTapLoginButton() {
    Auth.auth().signInAnonymously()
}

* Firebase Auth 미포함 전체 소스 코드: https://github.com/JK0369/ExLoginFlow

* Firebase Auth 포함 전체 소스 코드: https://github.com/JK0369/ExLoginFlow/tree/Implement-Firebase

Comments