Firebase(파이어베이스)를 이용한 iOS 로그인 구현 방법입니다.

이 예제에서는 이메일을 아이디로 사용합니다. 먼저 Firebase 웹 콘솔에서 인증 메뉴를 활성화한 다음, Xcode에서 로그인 관련 내용을 구현합니다.

 

파이어베이스 프로젝트에서 Authentification 생성

1. 파이어베이스 콘솔에서 프로젝트를 생성한 후, 빌드 > Authentification 메뉴를 클릭합니다.

2. 시작하기 버튼을 클릭합니다.

 

3. 그러면 아래와 같이 로그인 제공업체라는 페이지가 뜨게 되는데 여기서 이메일/비밀번호 옆의 연필 모양의 버튼을 클릭합니다.

만약 메뉴가 뜨지 않는다면 Sign-in method 탭을 클릭하면 됩니다.

 

4. 사용 설정 스위치를 활성화시키고, 저장 버튼을 클릭합니다.

 

5. 회원이 로그인을 하려면 먼저 회원 가입 과정이 필요하지만, 편의상 콘솔에서 사용자를 생성 후 로그인/로그아웃이 먼저 구현되도록 하겠습니다.

Users 탭에서 사용자 추가 버튼을 클릭합니다.

 

6. 임의의 이메일 주소, 비밀번호를 입력한 후 사용자 추가 버튼을 클릭합니다.

사용자가 추가되었습니다.

 

프로젝트에 Firebase CocoaPods 설치

Firebase는 CocoaPods라는 디펜던시 관리자를 이용해 프로젝트 내에 설치해야 합니다.

 

1. CocoaPods가 설치되지 않았다면 터미널 실행 후 아래 커맨드를 이용해 설치합니다.

$ sudo gem install cocoapods

 

2. 터미널을 실행한 뒤, Xcode 프로젝트의 루트 폴더로 이동한 다음, CocoaPods 초기화를 진행합니다.

$ pod init

 

3. 초기화가 완료되면, 프로젝트 루트 폴더에 Podfile이라는 파일이 생성됩니다. 텍스트 편집기로 해당 파일을 연 뒤, 아래 하이라이트 부분을 추가합니다.

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'ExampleProject' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for ExampleProject
  # add the Firebase pod for Google Analytics
  pod 'Firebase/Analytics'
  # or pod ‘Firebase/AnalyticsWithoutAdIdSupport’
  # for Analytics without IDFA collection capability

  # add pods for any other desired Firebase products
  # https://firebase.google.com/docs/ios/setup#available-pods

  # Add the pods for any other Firebase products you want to use in your app
  # For example, to use Firebase Authentication and Cloud Firestore
  pod 'Firebase/Auth'
  pod 'Firebase/Firestore'
  pod 'Firebase/Database'


  target 'ExampleProjectTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'ExampleProjectUITests' do
    # Pods for testing
  end

end

 

4. 터미널로 돌아간 뒤, 프로젝트 루트 위치에서 아래 명령을 실행합니다.

$ pod install

 

5. 설치가 완료되면 프로젝트 루트 폴더에 [프로젝트명].xcworkspace 라는 파일이 생성됩니다. 이후 프로젝트의 모든 작업은 워크스페이스를 통해 진행해야 합니다.

 

6. 프로젝트의 AppDelegate.swift 파일에서 아래 하이라이트 부분을 추가합니다.

import UIKit
import Firebase

@main
class AppDelegate: UIResponder, UIApplicationDelegate {



    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        FirebaseApp.configure()
        return true
    }

 

로그인/로그아웃 구현 (Swift, Storyboard)

1. 스토리보드에서 이메일과 패스워드 입력을 받는 간단한 로그인 폼을 구현합니다.

아래 뷰 컨트롤러에서 회색 배경의 두 하위 UIView가 있습니다. 로그인이 되지 않은 상태라면 위의 로그인 폼(viewSignInForm)만 보여주고, 로그인이 되었다면 아래 사용자 정보 뷰(viewUserInfo)만 보여줍니다.

오브젝트 배치 및 @IBOutlet, @IBAction 연결에 대한 내용은 너무 길어 생략합니다.

 

2. 뷰 컨트롤러에 Firebaseimport 합니다.

import Firebase

 

3. 이메일과 비밀번호를 입력 후 로그인 버튼을 누르면 로그인 작업을 실행하는 코드를 작성합니다.

@IBAction func btnActSubmit(_ sender: UIButton) {
    guard let userEmail = txtUserEmail.text else { return }
    guard let userPassword = txtUserPassword.text else  { return }
    
    Auth.auth().signIn(withEmail: userEmail, password: userPassword) { [weak self] authResult, error in
        guard self != nil else { return }
        
        if authResult != nil {
            print("로그인 되었습니다")
        } else {
            print("로그인되지 않았습니다.", error?.localizedDescription ?? "")
        }
    }
}
  • userEmail, userPassword – 텍스트 필드에서 이메일 주소, 비밀번호를 가져옵니다.
  • Auth.auth().signIn – 이메일과 비밀번호를 받은 뒤, 트레일링 클로저에서 로그인 완료 시 실행할 내용을 작성합니다.
  • authResult, error – 로그인이 정상적으로 진행되었다면 authResultnil이 아니며, 로그인이 실패한 경우 authResultnil이 됩니다. 로그인이 되지 않은 이유를 error?.localizedDescription를 통해 알 수 있습니다.

 

앱을 빌드-실행한 뒤 위에서 생성했던 유저 정보를 이용해 로그인을 진행합니다. 로그인 성공 또는 실패시 해당 메시지가 표시됩니다.

 

4. viewWillAppear(_:)에 인증 상태 리스너 작성

인증 상태 리스너는 로그인/로그아웃이 되었을 때 즉시 반응해서 클로저의 내용을 실행합니다.

먼저 하위 뷰 2개를 모두 isHidden 처리하여 숨깁니다.

viewSignUpForm.isHidden = true
viewUserInfo.isHidden = true

 

뷰 컨트롤러의 멤버 변수 handle을 생성합니다.

var handle: AuthStateDidChangeListenerHandle!

 

다음 viewWillAppear(_:) 에 인증 상태 리스너를 작성합니다.

override func viewWillAppear(_ animated: Bool) {
    handle = Auth.auth().addStateDidChangeListener { auth, user in
        if let user = user {
            self.viewUserInfo.isHidden = false
            self.viewSignUpForm.isHidden = true
            self.lblUserEmail.text = user.email
        } else {
            self.viewUserInfo.isHidden = true
            self.viewSignUpForm.isHidden = false
            self.lblUserEmail.text = ""
        }
    }
}
  • usernil이 아니면 로그인이 된 상태이고, nil이라면 로그인이 되지 않은 상태입니다.
  • 로그인이 된 경우 이메일을 가져와 레이블에 기록하고, 로그인창은 숨기고, 사용자 정보 창은 보여줍니다.
  • 로그인이 되지 않은 경우 이메일 레이블을 초기화하고, 로그인창을 표시하고, 사용자 정보 창은 숨깁니다.

 

 

뷰가 사라질 때에는 인증 상태 리스너를 해지해야 합니다. viewWillDisappear(_:) 을 아래와 같이 작성합니다.

override func viewWillDisappear(_ animated: Bool) {
    Auth.auth().removeStateDidChangeListener(handle!)
}

 

 

5. 로그아웃 버튼에 로그아웃 이벤트를 작성합니다.

@IBAction func btnActSignOut(_ sender: UIButton) {
    do {
        try Auth.auth().signOut()
    } catch {
        print(error.localizedDescription)
    }
}

로그아웃이 완료되면 위의 인증 상태 리스너에 의해 사용자 정보 창이 가려지고 로그인 폼이 다시 나타나게 됩니다.


참고로 한 번 로그인이 되면 앱을 삭제하기 전까지는 계속 로그인 상태가 유지됩니다.

 

전체 코드

import UIKit
import Firebase

class ViewController: UIViewController {
    
    @IBOutlet weak var txtUserEmail: UITextField!
    @IBOutlet weak var txtUserPassword: UITextField!
    
    @IBOutlet weak var lblUserEmail: UILabel!
    
    @IBOutlet weak var viewSignUpForm: UIView!
    @IBOutlet weak var viewUserInfo: UIView!
    
    var handle: AuthStateDidChangeListenerHandle!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        viewSignUpForm.isHidden = true
        viewUserInfo.isHidden = true
    }
    
    override func viewWillAppear(_ animated: Bool) {
        handle = Auth.auth().addStateDidChangeListener { auth, user in
            if let user = user {
                self.viewUserInfo.isHidden = false
                self.viewSignUpForm.isHidden = true
                self.lblUserEmail.text = user.email
            } else {
                self.viewUserInfo.isHidden = true
                self.viewSignUpForm.isHidden = false
                self.lblUserEmail.text = ""
            }
        }
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        Auth.auth().removeStateDidChangeListener(handle!)
    }
    
    @IBAction func btnActSubmit(_ sender: UIButton) {
        guard let userEmail = txtUserEmail.text else { return }
        guard let userPassword = txtUserPassword.text else  { return }
        
        Auth.auth().signIn(withEmail: userEmail, password: userPassword) { [weak self] authResult, error in
            guard self != nil else { return }
            
            if authResult != nil {
                print("로그인 되었습니다")
            } else {
                print("로그인되지 않았습니다.", error?.localizedDescription ?? "")
            }
        }
    }
    
    @IBAction func btnActSignOut(_ sender: UIButton) {
        do {
            try Auth.auth().signOut()
        } catch {
            print(error.localizedDescription)
        }
    }
    
}

문의 | 코멘트 또는 yoonbumtae@gmail.com  donaricano-btn

카테고리: Swift

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다