글 작성자: 택시 운전사
반응형

노마드 코더 트위터 클론 코딩

노마드 코더의 트위터 클론 코딩 강의를 듣고 정리한 강의노트입니다.


2.0 Using Firebase Auth / Firebase 인증 사용하기

특정 폴더 기준으로 상대 경로로 import 하는 방법

{
  "compilerOptions": {
    "baseUrl": "src"
  },
  "include": ["src"]
}

Firebase 설정 수정

인증 관련 값을 가져오기 위해 Firebase 설정 수정

⚠️ 강의 영상 이후로 firebase가 v9.0으로 업데이트하면서 기존 코드와 호환이 안되는 경우가 있어서 v9.0를 사용하는 경우 아래 코드로 진행

// Import the functions you need from the SDKs you need
import { initializeApp } from 'firebase/app'
import { getAuth } from 'firebase/auth'

// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries

// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: process.env.REACT_APP_API_KEY,
  authDomain: process.env.REACT_APP_AUTH_DOMAIN,
  databaseURL: process.env.REACT_APP_DATABASE_URL,
  projectId: process.env.REACT_APP_PROJECT_ID,
  storageBucket: process.env.REACT_APP_STORAGE_BUCKET,
  messagingSenderId: process.env.REACT_APP_MESSAGIN_ID,
  appId: process.env.REACT_APP_APP_ID,
}

// Initialize Firebase
const app = initializeApp(firebaseConfig)
export const authService = getAuth()

2.1 Login Form part One / 로그인 양식 첫번째

Firebase 인증에서 로그인 제공 업체를 다음과 같이 설정

Github의 경우 로그인 후 Developer settings에 들어가서 OAuth Application을 생성하여 client idsecret key를 넣어야 함

로그인 양식

하나의 onChange 이벤트 핸들러를 이용해서 emailpassword 입력을 다룰 수 있도록 코드를 구성

import React, { useState } from 'react'

const Auth = () => {
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')

  const handleOnChange = (e) => {
    const {
      target: { name, value },
    } = e

    console.log(name)

    if (name === 'email') {
      setEmail(value)
    } else if (name === 'password') {
      setPassword(value)
    }
  }

  const handleOnSubmit = (e) => {
    e.preventDefault();
  }

  return (
    <div>
      <form onSubmit={handleOnSubmit}>
        <input name="email" type="text" placeholder="Email" required value={email} onChange={handleOnChange} />
        <input
          name="password"
          type="password"
          placeholder="Password"
          required
          value={password}
          onChange={handleOnChange}
        />
        <input type="sumbit" valeu="Log In" />
      </form>
      <div>
        <button>Continue with Google</button>
        <button>Continue with Github</button>
      </div>
    </div>
  )
}

export default Auth

2.2 Recap / 복습하기

onSubmit에서 preventDefault를 하는 이유?

기본적으로 type=submitinput 요소는 클릭 시 값에 해당하는 쿼리 스트링을 만들어서 해당 URL로 이동하는 동작을 한다. 하지만, SPA의 작동 방식과는 어울리지 않아서 이러한 기본 동작을 막는 것이 필요한데 그 때 필요한 것이 preventDefault로 특정 이벤트의 기본 동작을 막아주는 역할을 한다.

2.3 Creating Account / 계정 생성하기

firebase.auth.EmailAuthProvider를 사용할 예정

⚠️ 강의 코드와 달리 v9.0 버전에 맞춰서 수정해야할 부분이 있습니다.

import { authService } from 'fbase'
import React, { useState } from 'react'
import { createUserWithEmailAndPassword, signInWithEmailAndPassword } from 'firebase/auth';

const Auth = () => {
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const [newAccount, setNewAccount] = useState(true)

  const handleOnChange = (e) => {
    const {
      target: { name, value },
    } = e

    if (name === 'email') {
      setEmail(value)
    } else if (name === 'password') {
      setPassword(value)
    }
  }

  const handleOnSubmit = async (e) => {
    e.preventDefault();
    try{
      let data;
      if(newAccount){
        data = await createUserWithEmailAndPassword(authService, email, password)
      } else {
        data = await signInWithEmailAndPassword(authService, email, password)
      }
      console.log(data);
    } catch(error){
      console.error(error)
    }
  }

  return (
    <div>
      <form onSubmit={handleOnSubmit}>
        <input name="email" type="text" placeholder="Email" required value={email} onChange={handleOnChange} />
        <input
          name="password"
          type="password"
          placeholder="Password"
          required
          value={password}
          onChange={handleOnChange}
        />
        <input type="submit" value={newAccount ? "Create Account" : "Log In"} />
      </form>
      <div>
        <button>Continue with Google</button>
        <button>Continue with Github</button>
      </div>
    </div>
  )
}

export default Auth

"Create Account"를 하게 되면, 계정이 생성되고 해당 계정으로 로그인 상태가 된다. (구글 크롬 > Application 탭 > IndexedDB > firebase~ 에서 확인 가능)

2.4 Log In / 로그인

현재 회원가입을 할 것인지 로그인을 할 것인지 토글하는 버튼 추가

2.5 Social Login / 소셜 로그인

⚠️ Firebase v9.0 코드

import { auth } from 'fbase'
import React, { useState } from 'react'
import {
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
  GoogleAuthProvider,
  GithubAuthProvider,
  signInWithPopup,
} from '@firebase/auth'

const Auth = () => {
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const [newAccount, setNewAccount] = useState(true)
  const [error, setError] = useState('')

  const handleOnChange = (e) => {
    const {
      target: { name, value },
    } = e

    if (name === 'email') {
      setEmail(value)
    } else if (name === 'password') {
      setPassword(value)
    }
  }

  const handleOnSubmit = async (e) => {
    e.preventDefault()
    try {
      let data
      if (newAccount) {
        data = await createUserWithEmailAndPassword(auth, email, password)
      } else {
        data = await signInWithEmailAndPassword(auth, email, password)
      }
      console.log(data)
    } catch (error) {
      setError(error.message)
    }
  }

  const toggleAccount = () => {
    setNewAccount((prev) => !prev)
  }

  const handleOnSocialClick = async (e) => {
    const {
      target: { name },
    } = e

    let provider
    if (name === 'google') {
      provider = new GoogleAuthProvider()
    } else if (name === 'github') {
      provider = new GithubAuthProvider()
    }
    const data = await signInWithPopup(auth, provider)
  }

  return (
    <div>
      <form onSubmit={handleOnSubmit}>
        <input name="email" type="text" placeholder="Email" required value={email} onChange={handleOnChange} />
        <input
          name="password"
          type="password"
          placeholder="Password"
          required
          value={password}
          onChange={handleOnChange}
        />
        <input type="submit" value={newAccount ? 'Create Account' : 'Sign In'} />
        {error}
      </form>
      <span onClick={toggleAccount}>{newAccount ? 'Sign In' : 'Create Account'}</span>
      <div>
        <button name="google" onClick={handleOnSocialClick}>
          Continue with Google
        </button>
        <button name="github" onClick={handleOnSocialClick}>
          Continue with Github
        </button>
      </div>
    </div>
  )
}

export default Auth

2.6 Log Out / 로그아웃

import { auth } from 'fbase'
import React from 'react'
import { useHistory } from 'react-router'

const Profile = () => {
  const history = useHistory()

  const handleOnLogOutClick = () => {
    auth.signOut()
    history.push('/')
  }

  return (
    <>
      <button onClick={handleOnLogOutClick}>Log Out</button>
    </>
  )
}
export default Profile
반응형