[TIL 10] Firebase 인증을 통한 로그인 기능 구현 (Feat. React)

로빈·2022년 8월 14일
0

Firebase

목록 보기
2/3
post-thumbnail
post-custom-banner

Firebase 연동하기

Firebase 홈페이지 로그인 & 프로젝트 만들기

  • Firebase 홈페이지에서 로그인을 합니다.
  • 로그인 후 프로젝트 만들기 버튼을 눌러 프로젝트를 생성합니다.

  • 프로젝트 이름을 작성하고, Google 애널리틱스 연동이 필요하다면 사용 버튼을 ON으로, 필요하지 않다면 OFF로 변경합니다.

  • 프로젝트 만들기 버튼을 눌러 프로젝트를 생성을 마무리합니다.

  • 프로젝트가 완성되면 Firebase 내부의 다양한 기능을 사용할 수 있습니다.

  • 앱(iOS, Android), 웹에 Firebase를 추가하여 시작할 수 있습니다.

앱 또는 웹에 Firebase 추가하기

  • 상단 앱에 Firebase를 추가하여 시작하기 아래에 Firebase 추가가 필요한 어플리케이션을 선택합니다.

  • 웹을 선택하여 Firebase 추가하였습니다.

  • firebaseConfig(SDK)를 저장해둡니다.

인증(Authentication) 서비스 시작하기

  • 그 중, 로그인 기능 및 회원 ID를 관리할 수 있는 Authentication(인증) 섹션을 클릭합니다.

  • 시작하기 버튼을 눌러 인증 기능을 활성화합니다.

  • Users : 회원들을 관리하는 섹션입니다.

  • Sign-in method : 로그인 방법을 관리합니다. 원하는 로그인 방식을 선택하여 연동할 수 있습니다. 연동 가능한 종류는 크게 기본 업체, 추가 업체, 커스텀 업체가 있습니다.
    • 기본: 이메일/비밀번호, 전화, 익명
    • 추가: Google, Facebook, Github, Twitter 등


- 원하는 로그인 방식을 추가합니다. 여러 개 설정도 가능합니다.

인증(Authentication) 연동 방법

React로 인증 구현하기(로그인/로그아웃)

Firebase 추가 방법 공식 문서 바로가기 >>

1. React Setup (create-react-app)

2. npm을 사용하여 Firebase를 설치합니다.

npm i firebase

3-1. 앱에서 Firebase를 초기화하고 Firebase 앱 객체를 만듭니다.

  • firebase 폴더에 fbInstance.js 파일을 만들어 그 안에 객체를 생성했습니다.
import { initializeApp } from 'firebase/app';

const firebaseConfig = {
  apiKey: 
  authDomain:
  projectId:
  storageBucket:
  messagingSenderId:
  appId:
};

const app = initializeApp(firebaseConfig);
  • 위에 저장해 둔 각각의 firebaseConfig를 추가합니다.

3-2. (선택) 보안을 위해 env 파일에 따로 저장합니다.

  • 외부에 파일을 공유할 때(Github 등) 개인 정보 보호를 위해 api key 등을 .env 파일에 따로 저장할 수 있습니다.
  • .env 파일은 반드시 src 파일 밖에 저장해야합니다. (root 경로)
// fbInstance.js 코드

import { initializeApp } from 'firebase/app';

const firebaseConfig = {
    apiKey: process.env.REACT_APP_API_KEY,
    authDomain: process.env.REACT_APP_AUTH_DOMAIN,
    projectId: process.env.REACT_APP_PROJECT_ID ,
    storageBucket: process.env.REACT_APP_STORAGE_BUCKET,
    messagingSenderId: process.env.REACT_APP_MESSAGING_SENDER_ID,
    appId: process.env.REACT_APP_APP_ID
  };

const app = initializeApp(firebaseConfig);
// .env 파일 코드

REACT_APP_API_KEY = apikey 입력
REACT_APP_AUTH_DOMAIN = authDomain 입력
REACT_APP_PROJECT_ID = projectId 입력
REACT_APP_STORAGE_BUCKET = storageBucket 입력
REACT_APP_MESSAGING_SENDER_ID = messagingSenderId 입력
REACT_APP_APP_ID = appId 입력

4. 어플리케이션에서 Firebase 액세스 → 인증 서비스

인증 서비스 공식 문서 바로가기 >>

  • 인증(Authentication) 서비스를 개별 하위 패키지 내에서 가져옵니다.
import { getAuth } from 'firebase/auth'
  • 이후 객체를 이용해 로그인 기능을 구현할 수 있도록 호출한 getAuth()export 합니다.
export const authService = getAuth();
  • fbInstance 코드 정리 ==
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth'

const firebaseConfig = {
    apiKey: process.env.REACT_APP_API_KEY,
    authDomain: process.env.REACT_APP_AUTH_DOMAIN,
    projectId: process.env.REACT_APP_PROJECT_ID ,
    storageBucket: process.env.REACT_APP_STORAGE_BUCKET,
    messagingSenderId: process.env.REACT_APP_MESSAGING_SENDER_ID,
    appId: process.env.REACT_APP_APP_ID
  };

const app = initializeApp(firebaseConfig);
export const authService = getAuth();

회원가입 & 로그인 기능 구현 방법

1-1. 회원가입 & 로그인 Setup

  • 회원가입을 하면 회원만 볼 수 있는 페이지로 넘어갈 수 있도록 페이지를 구성합니다.
  • React에서 여러 페이지를 구현할 수 있는 react-router 기능을 사용합니다.
  • React-Router 사용 방법 바로가기 >>

1-2. 회원가입 form 작성 (Auth.js)

  • form 태그와 input 태그로 회원가입 form을 작성합니다.
    • 아이디로 받을 email 과 비밀번호 password를 담을 input을 각각 작성합니다.
    • 각 input을 구분하기 위해 name 값으로 email 과 password을 넣습니다.
  • onChange 메소드로 input의 text의 내용의 변화가 일어났는지 탐지하고 반영합니다.
    • email input과 password input 각각의 onChange 메소드를 구현하지 않고, 비구조화 할당을 통해 하나의 메소드 안에서 구분할 수 있도록 코드를 구현합니다.
const onChange = (e) => {
        const { target: { name, value } } = e;
        if (name === "email") setEmail(value);
        else if (name === "password") setPassword(value);
}

import React, { useState } from 'react'

const Auth = () => {

    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');

    const onChange = (e) => {
        const { target: { name, value } } = e;
        if (name === "email") setEmail(value);
        else if (name === "password") setPassword(value);
    }

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

    return (
        <div>
            <form onSubmit={onSubmit}>
                <input
                    name="email"
                    type="text"
                    placeholder='Email'
                    required
                    value={email}
                    onChange={onChange} />
                <input
                    name="password"
                    type="password"
                    placeholder="Password"
                    required
                    value={password}
                    onChange={onChange} />
                <input
                    type="submit"
                    value="Create Account"/>
            </form>
            <div>
                <button name="Google">Google 로그인</button>
                <button name="Github">GitHub 로그인</button>
            </div>
        </div>
    )
}

export default Auth

2. 신규 사용자 가입 (회원가입) 기능 구현

  • 신규 사용자가 자신의 이메일 주소와 비밀번호를 사용해 앱에 가입할 수 있는 양식을 만듭니다.
  • 사용자가 양식을 작성하면 사용자가 입력한 이메일 주소와 비밀번호의 유효성을 검사한 후 createUserWithEmailAndPassword 메서드에 전달합니다.
// orginal 코드

import { getAuth, createUserWithEmailAndPassword } from "firebase/auth";

const auth = getAuth();
createUserWithEmailAndPassword(auth, email, password)
  .then((userCredential) => {
    // Signed in
    const user = userCredential.user;
    // ...
  })
  .catch((error) => {
    const errorCode = error.code;
    const errorMessage = error.message;
    // ..
  });
  • firebase는 기본적으로 비동기적으로 동작합니다.
    • createUserWithEmailAndPassword API 가 동작할 때까지 기다리기 위해 async/await로 비동기처리를 합니다.
  • fbInstance에서 미리 만든 authService를 불러옵니다.
    • authService는 createUserWithEmailAndPassword API의 매개변수로 담습니다.
// 수정한 코드
import { createUserWithEmailAndPassword, signInWithEmailAndPassword } from "firebase/auth";
import { authService } from '../firebase/fbInstance';

const Auth = () => {
		const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [error, setError] = useState('');
    
    const onSubmit = async (e) => {
        e.preventDefault();
        let data ;
        try {
            data = await createUserWithEmailAndPassword(authService, email, password)
        } catch (error) {
            setError(error.message);
        }
    }
	...
}

3. 기존 사용자 로그인 기능 구현

  • 기존 사용자가 자신의 이메일 주소와 비밀번호를 사용해 로그인할 수 있는 양식을 만듭니다.
  • 사용자가 양식을 작성하면 signInWithEmailAndPassword 메서드를 호출합니다.
// orginal 코드

import { getAuth, signInWithEmailAndPassword } from "firebase/auth";

const auth = getAuth();
signInWithEmailAndPassword(auth, email, password)
  .then((userCredential) => {
    // Signed in
    const user = userCredential.user;
    // ...
  })
  .catch((error) => {
    const errorCode = error.code;
    const errorMessage = error.message;
  });
// 수정한 코드
import { createUserWithEmailAndPassword, signInWithEmailAndPassword } from "firebase/auth";
import { authService } from '../firebase/fbInstance';

const Auth = () => {
		const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [newAccount, setNewAccount] = useState(true);
    const [error, setError] = useState('');
    
		const onSubmit = async (e) => {
        e.preventDefault();
        let data ;
        try {
            if(newAccount) data = await createUserWithEmailAndPassword(authService, email, password);
            else data = await signInWithEmailAndPassword(authService, email, password);
        } catch (error) {
            setError(error.message);
        }
    }
	...
}
// 전체 코드

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

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

    const toggleAccount = () => setNewAccount((prev) => !prev)
    const onChange = (e) => {
        const { target: { name, value } } = e;
        if (name === "email") setEmail(value);
        else if (name === "password") setPassword(value);
    }

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

    return (
        <div>
            <form onSubmit={onSubmit}>
                <input
                    name="email"
                    type="text"
                    placeholder='Email'
                    required
                    value={email}
                    onChange={onChange} />
                <input
                    name="password"
                    type="password"
                    placeholder="Password"
                    required
                    value={password}
                    onChange={onChange} />
                <input
                    type="submit"
                    value={newAccount? "회원가입" : "로그인"} />
            </form>
            <span onClick={toggleAccount}>{newAccount? "회원가입" : "로그인"}</span>
            <div>
                <button name="Google">Google 로그인</button>
                <button name="Github">GitHub 로그인</button>
            </div>
        </div>
    )
}

export default Auth
profile
나의 과정들
post-custom-banner

1개의 댓글

comment-user-thumbnail
2024년 7월 2일

글 너무 잘 읽었습니다. 직접 실습을 하려는데 혹시 깃허브에 전체코드가 있으시다면 깃헙 주소 공유 해주실 수 있으실까요?

답글 달기