React에서 Firebase를 이용하여 로그인, 소셜 로그인 인증 구현하기 (Auth)
Firebase
와 React
를 이용해서, 회원가입
, 로그인
, 인증메일 발송
, 소셜 로그인
, 로그아웃
, 인증상태 추적
기능을 구현하는 방법입니다.
1. firebase console에서 로그인 허용
Authentication
-> Sign-in method
로 들어가서 허용할 인증 방법을 선택합니다.
(이 글에서는 Email/Password
인증과 , Google
의 소셜 인증에 대해서만 작성하였습니다. 다른 인증 방법도 아래와 동일한 방법으로 진행할 수 있습니다.)
2. firebase 설치 및 config 설정
npm으로 firebase를 설치해줍니다.
npm install firebase
Firebase Console
-> Project settings
-> General
에서 config
정보를 가져오기 (디렉토리 경로와 파일 이름은 바뀌어도 상관 없음)
// Import the functions you need from the SDKs you need
import { initializeApp } from 'firebase/app';
import { getAnalytics } from 'firebase/analytics';
import { getFirestore } from 'firebase/firestore';
import { getStorage } from 'firebase/storage';
import { getMessaging } from 'firebase/messaging';
// 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: '',
authDomain: '',
projectId: '',
storageBucket: '',
messagingSenderId: '',
appId: '',
measurementId: '',
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
3. firebase config 적용
index.js 파일 상단에 firebase-config 파일을 불러옵니다.
import { db } from '../../firebase-config';
4. 네이티브 회원가입 기능 구현
소셜 로그인은 회원가입이 필요 없지만, 네이티브 로그인을 이용하기 위해서는 사전에 회원가입 진행하여야 합니다.
import { useState } from 'react';
import { getAuth, createUserWithEmailAndPassword } from 'firebase/auth';
export default function Register() {
const auth = getAuth();
const [user, setUser] = useState({
email: null,
password: null,
});
const handleRegister = (email, password) => {
createUserWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed up
const user = userCredential.user;
console.log(user);
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
console.log(errorCode, errorMessage);
});
};
return (
<>
<input
onChange={(e) => {
setUser({ ...user, email: e.target.value });
}}
/>
<input
onChange={(e) => {
setUser({ ...user, password: e.target.value });
}}
/>
<button onClick={() => handleRegister(user.email, user.password)}>
회원가입
</button>
</>
);
}
5. 인증 메일 발송 기능 구현
인증 메일은 여러번 발송이 가능합니다.
import { useState } from 'react';
import { getAuth, sendEmailVerification } from 'firebase/auth';
export default function Register() {
const auth = getAuth();
const handleSendEmail = () => {
sendEmailVerification(auth.currentUser).then(() => {
console.log('인증 메일 발송 완료');
});
};
return (
<>
<button onClick={handleSendEmail}>인증메일 발송</button>
</>
);
}
6. 로그인 기능 구현
회원가입한 이메일로 로그인 하거나, 소셜 로그인을 이용해서 로그인 기능을 구현할 수 있습니다.
네이티브 이메일/패스워드를 사용한 로그인
import { useState } from 'react';
import { getAuth, signInWithEmailAndPassword } from 'firebase/auth';
export default function Login() {
const auth = getAuth();
const [user, setUser] = useState({
email: null,
password: null,
});
const handleLogin = (email, password) => {
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
console.log(user);
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
console.log(errorCode, errorMessage);
});
};
return (
<>
<input
onChange={(e) => {
setUser({ ...user, email: e.target.value });
}}
/>
<input
onChange={(e) => {
setUser({ ...user, password: e.target.value });
}}
/>
<button onClick={() => handleLogin(user.email, user.password)}>
로그인
</button>
</>
);
}
소셜 로그인 (ex. 구글 로그인)
소셜 로그인은 아이디 패스워드 필요 없이 버튼 하나로 구현할 수 있으며, 팝업창을 통해서 인증이 진행됩니다.
아래 코드에서 GoogleAuthProvider
를 FacebookAuthProvider
, TwitterAuthProvider
, GithubAuthProvider
로 변경하면 다른 써드파티 소셜 로그인도 사용할 수 있습니다.
import { getAuth, GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
export default function GoogleLogin() {
const auth = getAuth();
const handleGoogleLogin = () => {
const provider = new GoogleAuthProvider();
signInWithPopup(auth, provider)
.then((result) => {
const credential = GoogleAuthProvider.credentialFromResult(result);
const token = credential.accessToken;
const user = result.user;
console.log(user);
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
const email = error.customData.email;
const credential = GoogleAuthProvider.credentialFromError(error);
console.log(errorCode, errorMessage);
});
};
return (
<>
<button onClick={handleGoogleLogin}>구글 로그인</button>
</>
);
}
7. 로그아웃 기능 구현
어느 페이지든 상관없이 로그아웃 기능이 실행되면 로그아웃이 진행됩니다.
import { getAuth, signOut } from 'firebase/auth';
export default function Logout() {
const auth = getAuth();
const handleLogout = () => {
signOut(auth)
.then(() => {
console.log('로그아웃 성공');
})
.catch((error) => {
console.log('로그아웃 실패', error);
});
};
return (
<>
<button onClick={handleLogout}>로그아웃</button>
</>
);
}
8. 인증상태 추적
observer를 추가하여 인증 상태를 추적할 수 있습니다.
유저의 로그인 여부와 유저 정보를 변경될 때마다 확인할 수 있습니다. useEffect에 초기에 1번만 호출하면 계속 작동됩니다.
import { useEffect } from 'react';
import { getAuth, onAuthStateChanged } from 'firebase/auth';
export default function Whatever() {
const auth = getAuth();
useEffect(() => {
onAuthStateChanged(auth, (user) => {
if (user) {
const uid = user.uid;
console.log(uid);
} else {
console.log('로그아웃 상태');
}
});
}, []);
return <></>;
}
참고자료
- https://firebase.google.com/docs/auth/web/google-signin?hl=ko#web-modular-api_4
- https://firebase.google.com/docs/auth/web/start#web-modular-api_1
- https://www.inflearn.com/questions/160617/firebase-auth-onauthstatechanged-%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C-%EC%A7%88%EB%AC%B8%ED%95%A9%EB%8B%88%EB%8B%A4