iOS Swift/Library, Framework 연동

[iOS/Swift] ios 파이어베이스 회원가입 Firebase Auth (2)

주니어코더 2023. 6. 28. 17:44

 

 

 

 

 

 

 iOS에서 파이어베이스 회원가입 구현 

 

Swift로 Firebase Auth 회원정보 구현 2탄

"파이어베이스 회원가입"

 

 

 

 

 

 

🛑 이글에서는 파이어베이스 Auth를 이용한 회원가입만 다룬다 🛑 
Xcode와 Firebase 연동 방법은 아래 글에서 참조 

 

 


iOS와 Firebase 연동 1탄

2023.06.20 - [iOS Swift/Firebase 연동] - [ios/Swift] iOS 파이어베이스 연동 Firebase Auth (1)

 

[ios/Swift] iOS 파이어베이스 연동 Firebase Auth (1)

iOS 와 파이어베이스 연동하기 Swift로 Firebase Auth 회원정보 구현 1탄 "파이어베이스 연동" Chap1. 파이어베이스 프로젝트 생성 파이어베이스 콘솔 사이트에서 프로젝트를 생성 아래 파이어베이스 콘

ohwhatisthis.tistory.com

 

 

 

 

 

Chap1.  파이어베이스 프로젝트 Authentication 설정


 

파이어베이스 콘솔 사이트에서 프로젝트에 사용자 인증 및 관리 설정

 

 

 

1.  파이어베이스 콘솔 사이트에서 로그인 

 

파이어베이스 콘솔 사이트

 

https://firebase.google.com/?hl=ko

 

Firebase

Firebase is an app development platform that helps you build and grow apps and games users love. Backed by Google and trusted by millions of businesses around the world.

firebase.google.com

 

 

 

2. 해당 프로젝트 클릭 → Authentication 선택

 

 

 

 

 

3. sign-in method → 로그인 제공 업체 → 이메일/비밀번호 선택

 

 

 

 

 

4. 이메일/비밀번호 사용설정 On 선택 저장

 

 

 

 

 

5. Firebase Authentication 설정 완료

 

 

 

 

 

 

 

Chap2.  회원가입 뷰 생성


 

파이어베이스를 적용할 회원가입 뷰를 생성한다

 

 

emailTf, pwTf라는 Textfield에 입력 후 joinBtn 클릭 시 회원가입

Programatically 방식으로 코드만 사용해서 뷰 생성

 

import UIKit

class JoinViewController: UIViewController {
    
    lazy var baseView: UIView = {
        var view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
        
    lazy var stackView: UIStackView = {
        var view = UIStackView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.axis = .vertical
        view.distribution = .fillEqually
        view.alignment = .fill
        view.spacing = 12
        return view
    }()
    
    lazy var titleLb: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "회원가입"
        label.textAlignment = .center
        return label
    }()
    
    lazy var emailTf: UITextField = {
        var view = UITextField()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.placeholder = "이메일을 입력해주세요"
        view.borderStyle = .roundedRect
        return view
    }()
    
    lazy var pwTf: UITextField = {
        var view = UITextField()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.placeholder = "비밀번호를 입력해주세요"
        view.borderStyle = .roundedRect
        return view
    }()
    
    lazy var joinBtn: UIButton = {
        let button = UIButton(type: .system)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitle("회원가입", for: .normal)
        button.backgroundColor = .systemBlue
        button.setTitleColor(.white, for: .normal)
        button.layer.cornerRadius = 6
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "회원가입"
        view.backgroundColor = .white
        addViews()
        applyConstraints()
        addTarget()
    }

    fileprivate func addViews() {
        view.addSubview(baseView)
        baseView.addSubview(stackView)
        stackView.addArrangedSubview(titleLb)
        stackView.addArrangedSubview(emailTf)
        stackView.addArrangedSubview(pwTf)
        stackView.addArrangedSubview(joinBtn)
    }
    
    fileprivate func applyConstraints() {
        let baseViewConstraints = [
            baseView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            baseView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            baseView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            baseView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
        ]
    
        let stackViewConstraints = [
            stackView.topAnchor.constraint(equalTo: baseView.topAnchor, constant: 30),
            stackView.leadingAnchor.constraint(equalTo: baseView.leadingAnchor, constant: 30),
            stackView.trailingAnchor.constraint(equalTo: baseView.trailingAnchor, constant: -30),
        ]
        
        let emailTfConstraints = [
            emailTf.heightAnchor.constraint(equalToConstant: 50)
        ]
        NSLayoutConstraint.activate(baseViewConstraints)
        NSLayoutConstraint.activate(stackViewConstraints)
        NSLayoutConstraint.activate(emailTfConstraints)
    }
        
    fileprivate func addTarget() {
        joinBtn.addTarget(self, action: #selector(didTapJoinButton(_:)), for: .touchUpInside)
    }
        
    @objc func didTapJoinButton(_ sender: UIButton) {
        print("회원가입 버튼 클릭")
        
        if let email = emailTf.text {
            print(email)
        }
        
        if let pw = pwTf.text {
            print(pw)
        }
        
    }
    
}

 

 

 

 

 

💫  회원가입 View 완성  💫

 

 

 

 

 

 

Chap3.  이메일 비밀번호 유효성 검사


 

먼저 iOS에서 이메일/비밀번호 유효성 검사 진행

 

 

 

1.  이메일/비밀번호 정규식 추가

 

 

    let emailPattern = "^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*\\.[a-zA-Z]{2,3}$"
    let pwPattern = "^.*(?=^.{8,16}$)(?=.*\\d)(?=.*[a-zA-Z])(?=.*[!@#$%^&+=]).*$"

 

 

✔️ emailPattern : 이메일 정규식으로, 알파벳과 숫자 중간에 @가 포함되며 끝 2-3자리 앞에. 이 포함
✔️ pwPattern : 비밀번호 정규식으로, 8-16자리 알파벳, 영어, 특수문자가 포함


 

 

 

2. textfield의 input 변경에 따라 유효성 검사

 

📝 코드 설명

 

(1) emailTf, pwTf가 editingChanged 될 때마다 "textFieldDidChange" 메서드 호출

 

(2) isValid 메서드에서 유효성검사 통과 →  emailValid, pwValid = true

(3) emailValid && pwValid == true allValid = true로 변경

(4) allValid == true  회원가입 버튼 활성화

 

 

 

    var emailValid = false
    var pwValid = false
    var allValid = false
       
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "회원가입"
        view.backgroundColor = .white
        addViews()
        applyConstraints()
        addTarget()
    }
   
   fileprivate func addTarget() {
        joinBtn.addTarget(self, action: #selector(didTapJoinButton(_:)), for: .touchUpInside)
        
        emailTf.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged)
        pwTf.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged)
    }
    
    fileprivate func isValid(text: String, pattern: String) -> Bool {
        let pred = NSPredicate(format: "SELF MATCHES %@", pattern)
        return pred.evaluate(with: text)
    }
    
    fileprivate func checkEmail() {
        if isValid(text: emailTf.text!, pattern: emailPattern) {
            emailValid = true
        } else {
            emailValid = false
        }
    }
    
    fileprivate func checkPw() {
        if isValid(text: pwTf.text!, pattern: pwPattern) {
            pwValid = true
        } else {
            pwValid = false
        }
    }
    
    fileprivate func checkAll() {
        if emailValid && pwValid {
            print("email, pw Valid Success")
            allValid = true
        } else {
            print("email, pw Valid Fail")
            allValid = false
        }
    }
    
    @objc func textFieldDidChange(_ sender: UITextField) -> Bool {
        switch sender {
        case emailTf:
            checkEmail()
        case pwTf:
            checkPw()
        default:
            break
        }
        checkAll()
        return true
    }
    
    @objc func didTapJoinButton(_ sender: UIButton) {
        print("회원가입 버튼 클릭")
        
        if let email = emailTf.text {
            print(email)
        }
        
        if let pw = pwTf.text {
            print(pw)
        }
        
        if allValid {
            print("allValid", allValid)
        }           
}

 

 

 

 

 

 

Chap4.  Firebase 라이브러리 import


 

파이어베이스 사용하려는 ViewController에 Firebase 라이브러리 import 한다

 

 

import FirebaseAuth
import FirebaseCore

 

 

 

 

 

Chap5.  Firebase 회원가입 메서드 추가


 

파이어베이스 Auth에서는 신규 사용자 가입 함수 "createUser"를 제공

 

 

 

파이어베이스 콘솔 인증 가이드 참조

 

https://firebase.google.com/docs/auth/ios/start?hl=ko 

 

Apple 플랫폼에서 Firebase 인증 시작하기  |  Firebase Authentication

Google I/O 2023에서 Firebase의 주요 소식을 확인하세요. 자세히 알아보기 의견 보내기 Apple 플랫폼에서 Firebase 인증 시작하기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고

firebase.google.com

 

 


신규 사용자가 자신의 이메일 주소와 비밀번호를 사용해 앱에 가입할 수 있는 양식을 만듭니다.

사용자가 양식을 작성하면 사용자가 입력한 이메일 주소와 비밀번호의 유효성을 검사한 후 createUser 메서드에 전달합니다.

 

 

 
 @objc func didTapJoinButton(_ sender: UIButton) {
        print("회원가입 버튼 클릭")
        
        if let email = emailTf.text {
            print("Email : ",email)
        }
        
        if let pw = pwTf.text {
            print("Password : ",pw)
        }
        
        if allValid {
            createUser()
        }
    }
    
    fileprivate func createUser() {
        guard let email = emailTf.text else { return }
        guard let pw = pwTf.text else { return }
        
        Auth.auth().createUser(withEmail: email, password: pw) {result,error in
            if let error = error {
                print(error)
            }
            
            if let result = result {
                print(result)
            }
        }
    }
 

 

회원가입 버튼 클릭 시 email, pw 텍스트의 유효성검사를 통과하였다면,
Firebase에 이메일과 비밀번호를 보낸다

 

 

 

 

 

✨ Firebase 결과 확인 ✨

 

 

 
 
 
 
 

전체 소스 코드


 

import UIKit
import FirebaseAuth
import FirebaseCore

class JoinViewController: UIViewController {
    
    lazy var baseView: UIView = {
        var view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
        
    lazy var stackView: UIStackView = {
        var view = UIStackView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.axis = .vertical
        view.distribution = .fillEqually
        view.alignment = .fill
        view.spacing = 12
        return view
    }()
    
    lazy var titleLb: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "회원가입"
        label.textAlignment = .center
        return label
    }()
    
    lazy var emailTf: UITextField = {
        var view = UITextField()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.placeholder = "이메일을 입력해주세요"
        view.borderStyle = .roundedRect
        return view
    }()
    
    lazy var pwTf: UITextField = {
        var view = UITextField()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.placeholder = "비밀번호를 입력해주세요"
        view.borderStyle = .roundedRect
        return view
    }()
    
    lazy var joinBtn: UIButton = {
        let button = UIButton(type: .system)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitle("회원가입", for: .normal)
        button.backgroundColor = .systemBlue
        button.setTitleColor(.white, for: .normal)
        button.layer.cornerRadius = 6
        return button
    }()
    
    let emailPattern = "^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*\\.[a-zA-Z]{2,3}$"
    let pwPattern = "^.*(?=^.{8,16}$)(?=.*\\d)(?=.*[a-zA-Z])(?=.*[!@#$%^&+=]).*$"
    var emailValid = false
    var pwValid = false
    var allValid = false
    
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "회원가입"
        view.backgroundColor = .white
        addViews()
        applyConstraints()
        addTarget()
    }

    fileprivate func addViews() {
        view.addSubview(baseView)
        baseView.addSubview(stackView)
        stackView.addArrangedSubview(titleLb)
        stackView.addArrangedSubview(emailTf)
        stackView.addArrangedSubview(pwTf)
        stackView.addArrangedSubview(joinBtn)
    }
    
    fileprivate func applyConstraints() {
        let baseViewConstraints = [
            baseView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            baseView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            baseView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            baseView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
        ]
    
        let stackViewConstraints = [
            stackView.topAnchor.constraint(equalTo: baseView.topAnchor, constant: 30),
            stackView.leadingAnchor.constraint(equalTo: baseView.leadingAnchor, constant: 30),
            stackView.trailingAnchor.constraint(equalTo: baseView.trailingAnchor, constant: -30),
        ]
        
        let emailTfConstraints = [
            emailTf.heightAnchor.constraint(equalToConstant: 50)
        ]
        NSLayoutConstraint.activate(baseViewConstraints)
        NSLayoutConstraint.activate(stackViewConstraints)
        NSLayoutConstraint.activate(emailTfConstraints)
    }
        
    fileprivate func addTarget() {
        joinBtn.addTarget(self, action: #selector(didTapJoinButton(_:)), for: .touchUpInside)
        
        emailTf.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged)
        pwTf.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged)
    }
    
    fileprivate func isValid(text: String, pattern: String) -> Bool {
        let pred = NSPredicate(format: "SELF MATCHES %@", pattern)
        return pred.evaluate(with: text)
    }
    
    fileprivate func checkEmail() {
        if isValid(text: emailTf.text!, pattern: emailPattern) {
            emailValid = true
        } else {
            emailValid = false
        }
    }
    
    fileprivate func checkPw() {
        if isValid(text: pwTf.text!, pattern: pwPattern) {
            pwValid = true
        } else {
            pwValid = false
        }
    }
    
    fileprivate func checkAll() {
        if emailValid && pwValid {
            print("email, pw Valid Success")
            allValid = true
        } else {
            print("email, pw Valid Fail")
            allValid = false
        }
    }
    
    @objc func textFieldDidChange(_ sender: UITextField) -> Bool {
        switch sender {
        case emailTf:
            checkEmail()
        case pwTf:
            checkPw()
        default:
            break
        }
        checkAll()
        return true
    }
    
    @objc func didTapJoinButton(_ sender: UIButton) {
        print("회원가입 버튼 클릭")
        
        if let email = emailTf.text {
            print("Email : ",email)
        }
        
        if let pw = pwTf.text {
            print("Password : ",pw)
        }
        
        if allValid {
            createUser()
        }
    }
    
    fileprivate func createUser() {
        guard let email = emailTf.text else { return }
        guard let pw = pwTf.text else { return }
        
        Auth.auth().createUser(withEmail: email, password: pw) {result,error in
            if let error = error {
                print(error)
            }
            
            if let result = result {
                print(result)
            }
        }
    }
}
 

 

 

 

 

 

 

 

 

👇 전체 소스코드 Github에서 확인하기 👇

https://github.com/hyeebin/ex-firebase-ios

 

GitHub - hyeebin/ex-firebase-ios: iOS와 Firebase 연동하여 회원정보 관리

iOS와 Firebase 연동하여 회원정보 관리 . Contribute to hyeebin/ex-firebase-ios development by creating an account on GitHub.

github.com

 

 

 

반응형