로그인 기능을 구현하기에 앞서, 프로젝트는 Firebase라는 앱 개발 플랫폼을 이용한다. 우리가 주로 쓰게 될 기능은 작성한 다이어리와 이미지 데이터베이스에 저장, Firebase 로그인 기능이다. 내가 맡게 된 역할은 로그인 기능을 담당하는 것이다.
Firebase는 친절하게 회원가입 기능과 로그인 기능을 각각의 언어들로 문서화 해놨고, 사실 구현하는 과정은 그리 어렵지 않았다. 여러 정보를 얻던 와중에 깨달은 것 중 하나는 굳이 Firebase 내에서 따로 사용자의 ID, PW를 관리할 필요없이 전적으로 소셜로그인에 맡겨도 잘 돌아간다는 것이다. 사용자 관점에서 보자면, 새로운 아이디를 파서 쓰는 것에 대해 그리 환호하지는 못할 것 같다. 나만 하더라도, 회원가입 기능과 소셜로그인 이용하는 기능 두 가지를 선택할 수 있다면, 소셜로그인을 선택하기 때문이다. 여러 기업에게 내 개인정보를 받치는 게 그리 달갑지는 않기 때문이다.
따라서, 자체적인 아이디 관리를 배제하고, 소셜로그인 기능만을 구현하기로 했다. 우선, 가장 사람들에게 대중적인 Google 계정을 이용한 로그인 기능을 구현했다.
import FirebaseCore
import FirebaseAuth
import GoogleSignIn
GoogleService-Info.plist
파일에 들어있는 REVERSED_CLIENT_ID
값을 복사한다. 그리고 URL Scheme 칸에 붙여넣는다. 이 URL은 Google 소셜로그인 버튼을 클릭할 시, 로그인 페이지로 연결하는 역할을 해준다.// appDelegate 에서
func application(_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
return GIDSignIn.sharedInstance.handle(url)
}
handleURL 메서드를 호출하여 인증 프로세스가 끝날 때 app이 수신하는 URL을 처리한다.
4. 로그인 기능을 구현할 VC에서 구글 로그인 이후에 반환되는 Google 인증 토큰으로 Firebase 사용자 정보를 만든다.
// LoginVC 에서
private func handleGIDSignIn() {
// 버튼 클릭 시, 인증
guard let clientID = FirebaseApp.app()?.options.clientID else { return }
// Create Google Sign In configuration object.
let config = GIDConfiguration(clientID: clientID)
GIDSignIn.sharedInstance.configuration = config
GIDSignIn.sharedInstance.signIn(withPresenting: self) { signInResult, error in
guard error == nil else { return }
// 인증을 해도 계정 등록 절차가 필요하다
// 구글 인증 토큰 받고 -> 사용자 정보 토큰 생성
guard let user = signInResult?.user,
let idToken = user.idToken?.tokenString
else { return }
let email = user.profile?.email
let fullName = user.profile?.name
let credential = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: user.accessToken.tokenString)
// 사용자 정보 토큰 -> Firebase에 로그인 프로세스
Auth.auth().signIn(with: credential) { result, error in
if let error = error {
print(error.localizedDescription)
return
}
print("Firebase login 성공 \(String(describing: email)),\(String(describing: fullName))")
self.dismiss(animated: true, completion: nil)
}
}
}
// LoginVC 에서
private lazy var signGoogleButton : UIButton = {
let signGoogleButton = UIButton()
signGoogleButton.setImage(.signInGoogle, for: .normal)
signGoogleButton.addTarget(self, action: #selector(tapGoogleLoginButton), for: .touchUpInside)
return signGoogleButton
@objc func tapGoogleLoginButton() {
handleGIDSignIn()
}
UIButton 말고, GoogleSigninButton으로 라이브러리에서 직접 지원해주는 포맷이 있다. 다만, 버튼의 이미지 프리셋이 지정되어있고, 지정된 프리셋 외의 커스텀을 원한다면, 직접 UIButton으로 커스텀하는게 좋다.
6. 로그아웃 기능 구현
//사용자 로그아웃 기능
private func signOut() {
let firebaseAuth = Auth.auth()
do {
try firebaseAuth.signOut()
if Auth.auth().currentUser == nil {
print("로그아웃 성공!")
} else {
print("로그아웃 실패!")
}
} catch let signOutError as NSError {
print("Error Signing out: %@", signOutError)
}
}