이 가이드는 React 웹 애플리케이션으로 Firebase 인증을 설정하는 방법 에 대한 보충 자료입니다. 해당 가이드의 소개에서 Firebase는 기본 이메일/비밀번호 인증 이외의 다른 인증 체계를 제공한다는 점을 언급했습니다. 이러한 대안 중 하나는 비밀번호 없는 인증 입니다.
비밀번호 없는 인증은 애플리케이션을 구축할 때 매력적인 옵션입니다. 사용자가 비밀번호를 기억할 필요가 없고 비밀번호 분실에 대해 걱정할 필요도 없으므로 사용자 경험이 단순화됩니다. 또한 비밀번호 캡처나 관리 로직을 설계할 필요가 없기 때문에 개발 환경이 용이합니다.
이 가이드에서는 Firebase의 비밀번호 없는 인증을 구현하는 간단한 로그인/확인/프로필/로그아웃 워크플로를 구축합니다.
Google은 다양한 Firebase 인증 제한을 설정합니다. 무료 Spark 플랜을 사용하는 경우 로그인 링크 이메일은 하루에 5개로 제한 됩니다. 테스트 목적으로는 Spark 요금제로 충분할 수 있지만 이 한도를 초과하려면 종량제 Blaze 요금제로 업그레이드해야 합니다.
이 가이드 전반에 걸쳐 React 웹 애플리케이션으로 Firebase 인증을 설정하는 방법 가이드를 전제 조건 가이드 로, 관련 프로젝트를 전제 프로젝트 로 참조하겠습니다.
이 가이드를 완료하려면 다음이 필요합니다.
필수 구성 요소 가이드에서는 기본 이메일/비밀번호 인증을 위한 새 Firebase 프로젝트를 만들었습니다. 이제 비밀번호 없는 인증을 위해 동일한 프로젝트를 활성화하겠습니다. Firebase 계정 에 로그인하고 Go to Console 을 클릭하세요.
Firebase 프로젝트 대시보드에 나열된 인증 프로젝트를 클릭합니다. 이 가이드에서는 프로젝트 이름 my-auth-test
사용합니다.
왼쪽 패널 메뉴에서 인증을 클릭하세요.
메인 창에서 로그인 방법 탭을 클릭하세요.
필수 구성 요소 가이드의 작업에 따르면 로그인 공급자 테이블의 공급자 열 아래에 활성화 상태의 이메일/비밀번호가 이미 표시되어 있습니다. 연필 아이콘을 클릭하면 이메일/비밀번호 제공업체의 구성 패널이 열립니다.
이메일 링크(비밀번호 없이 로그인)를 활성화하려면 토글을 클릭하세요.
저장 을 클릭합니다.
이제 Firebase 프로젝트가 비밀번호 없는 인증을 지원하도록 구성되었습니다.
원하는 애플리케이션 이름을 사용하여 새 React 프로젝트를 만듭니다. 이 가이드에서는 passwordless-auth
사용합니다.
npx create-react-app passwordless-auth
이 가이드에는 3개의 Node.js 패키지를 설치해야 합니다.
npm
통해 위의 세 가지 패키지를 각각 설치합니다.
npm install firebase
npm install react-router-dom
npm install bootstrap
firebase.js
복사 필수 프로젝트에서 Firebase 프로젝트 구성 데이터를 사용하여 Firebase 인증 서비스 인스턴스를 만드는 firebase.js
파일을 만들었습니다. firebase.js
파일은 Firebase 프로젝트 구성 값과 함께 다음과 같은 구조를 가져야 합니다.
import { initializeApp } from "firebase/app"; import { getAuth } from "firebase/auth"; const firebaseConfig = { apiKey: "AIzaSyDiUlY68W9Li_0EIkmdGdzD7nvqCT9kHnY", authDomain: "my-auth-test-fbd48.firebaseapp.com", projectId: "my-auth-test-fbd48", storageBucket: "my-auth-test-fbd48.appspot.com", messagingSenderId: "1078604952662", appId: "1:1078604952662:web:5d0b908439cfb5684ab7f7" } const app = initializeApp(firebaseConfig); const auth = getAuth(app); export { auth }
firebase.js
새 React 프로젝트 폴더에 복사합니다.
Firebase 프로젝트 구성을 검토해야 하는 경우 왼쪽 패널 메뉴에서 프로젝트 개요 옆에 있는 톱니바퀴 아이콘을 클릭하세요. 일반 탭이 이미 선택되어 있어야 합니다. 웹 앱 패널이 포함된 앱 섹션까지 아래로 스크롤합니다. 웹 앱 패널 내의 npm 옵션이 이미 선택되어 있습니다. 프로젝트 구성 값은 표시된 코드 블록에 나열됩니다.
React 애플리케이션은 App
, Layout
, Login
, Confirm
, Profile
의 5가지 구성요소로 구성됩니다.
App
App
구성 요소는 라우팅을 포함한 전체 애플리케이션 구조를 정의합니다. Layout
Layout
구성 요소는 모든 경로에서 일관성을 유지하는 애플리케이션 마크업을 지정합니다. Login
Confirm
Confirm
페이지로 이동됩니다. Profile
Profile
페이지로 라우팅됩니다.Profile
페이지에서 로그아웃 버튼을 클릭하여 자신의 계정에서 로그아웃할 수 있습니다. 최종 src
디렉터리에는 다음 파일이 포함됩니다.
src |__ index.js |__ firebase.js // Copied from prerequisite project in Step 3. |__ App.js |__ Layout.jsx |__ Login.jsx |__ Confirm.jsx |__ Profile.jsx
reportWebVitals.js
setupTests.js
logo.svg
index.css
App.css
App.test.js
필수 프로젝트의 index.js
새 프로젝트 폴더로 복사합니다. 이 가이드에서는 동일한 파일을 사용합니다. index.js
다시 빌드해야 하는 경우 필수 구성 요소 가이드의 5b.2단계를 참조하거나 아래 코드 블록을 복사하세요.
필수 프로젝트의 Layout.jsx
새 프로젝트 폴더에 복사합니다. 이 가이드에서는 동일한 파일을 사용합니다. Layout.jsx
다시 빌드해야 하는 경우 필수 구성 요소 가이드의 5d단계를 참조하거나 아래 코드 블록을 복사하세요. 선택적으로 Layout.jsx
의 <p>
태그에 있는 프로젝트 텍스트를 React With Firebase Passwordless Authentication
또는 원하는 제목으로 업데이트할 수 있습니다.
index.js
및 Layout.jsx
파일은 다음과 같아야 합니다.
// index.js import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; import "bootstrap/dist/css/bootstrap.min.css"; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <App /> </React.StrictMode> );
// Layout.jsx import { Outlet } from "react-router-dom"; const Layout = () => { return( <div className = "container-fluid"> <div className = "row justify-content-center mt-3"> <div className = "col-md-4 text-center"> <p className = "lead">React With Firebase Passwordless Authentication</p> </div> <Outlet /> </div> </div> ) } export default Layout
App.js
구축 App.js
파일은 두 줄만 변경된 점을 제외하면 필수 프로젝트의 파일과 거의 동일합니다. 파일 빌드를 용이하게 하려면 필수 프로젝트의 App.js
새 프로젝트 폴더에 복사하세요.
파일에서 다음 import
줄을 삭제하고 아래와 같이 바꿉니다.
// Delete this line: import Signup from "./Signup";
// Replace it with: import Confirm from "./Confirm";
파일에서 다음 <Route>
삭제하고 아래와 같이 바꿉니다.
// Delete this line: <Route path = "/signup" element = { <Signup></Signup> } ></Route>
// Replace it with: <Route path = "/confirm" element = { <Confirm></Confirm> } ></Route>
App.js
저장합니다.
이제 전체 파일은 다음과 같습니다.
import Layout from "./Layout"; import Login from "./Login"; import Confirm from "./Confirm"; import Profile from "./Profile"; import { BrowserRouter, Routes, Route } from "react-router-dom"; const App = () => { return ( <BrowserRouter> <Routes> <Route path = "/" element = { <Layout></Layout> }> <Route index element = { <Login></Login> }></Route> <Route path = "/confirm" element = { <Confirm></Confirm> } ></Route> <Route path = "/profile" element = { <Profile></Profile> } ></Route> </Route> </Routes> </BrowserRouter> ) } export default App
필수 프로젝트와 마찬가지로 Login
구성 요소가 다시 한 번 애플리케이션의 홈 경로라는 점에 유의하세요.
Login.jsx
구축비밀번호 없는 인증의 경우 비밀번호 필드를 포함할 필요도 없고 비밀번호 입력 상태를 관리할 필요도 없습니다. 따라서 로그인 양식에서는 사용자의 이메일 주소만 캡처하면 됩니다.
src
디렉터리에 새 Login.jsx
파일을 만듭니다.
다음 코드를 추가하세요.
import { useState } from "react"; import { auth } from "./firebase"; import { sendSignInLinkToEmail } from "firebase/auth"; const Login = () => { const [email, setEmail] = useState(""); const [notice, setNotice] = useState(""); const actionCodeSettings = { url: "http://localhost:3000/confirm", handleCodeInApp: true } const callSendSignInLinkToEmail = (e) => { e.preventDefault(); sendSignInLinkToEmail(auth, email, actionCodeSettings) .then(() => { setNotice("An email was sent to your email address. Click the link in the email to login."); }) .catch((error) => { setNotice("An error occurred when sending a login link to your email address: ", error.name); }) } return( <div className = "container"> <div className = "row justify-content-center"> <form className = "col-md-4 mt-3 pt-3 pb-3"> { "" !== notice && <div className = "alert alert-warning" role = "alert"> { notice } </div> } <div className = "form-floating mb-3"> <input type = "email" className = "form-control" id = "exampleInputEmail" placeholder = "[email protected]" value = { email } onChange = { (e) => setEmail(e.target.value) }></input> <label htmlFor = "exampleInputEmail" className = "form-label">Email address</label> </div> <div className = "d-grid"> <button type = "submit" className = "btn btn-primary pt-3 pb-3" onClick = {(e) => callSendSignInLinkToEmail(e)}>Submit</button> </div> </form> </div> </div> ) }
Login.jsx
저장합니다.
사용자의 이메일 주소를 캡처하면 Login.jsx
양식은 Firebase의 sendSignInLinkToEmail
메소드를 통해 사용자의 주소로 로그인 링크가 포함된 이메일을 보냅니다. 성공하면 사용자에게 이메일이 전송되었다는 알림이 전송됩니다. actionCodeSettings
개체는 sendSignInLinkToEmail
메서드에 매개 변수로 전달되며 사용자가 이메일로 전송된 로그인 링크를 클릭할 때 이동되는 URL을 포함합니다. 이 경우 URL은 App.js
에 지정된 /confirm
경로에 매핑됩니다.
Confirm.jsx
구축 Firebase의 signInWithEmailLink
메소드는 로그인 링크를 클릭한 사용자를 로그인하는 데 사용됩니다. 잠시 후에 보게 되겠지만, 이 메소드는 email
매개변수를 취하고 email
의 값은 사용자가 로그인 양식을 통해 로그인할 때 사용한 이메일 주소와 일치해야 합니다. Confirm.jsx
사용자에게 이메일 주소를 확인하는 양식을 제시한 후 사용자 로그인을 시도합니다.
src
디렉터리에 새 Confirm.jsx
파일을 만듭니다.
다음 코드를 추가하세요.
import { useState } from "react"; import { auth } from "./firebase"; import { isSignInWithEmailLink, signInWithEmailLink } from "firebase/auth"; import { useNavigate } from "react-router-dom"; const Confirm = () => { const navigate = useNavigate(); const [email, setEmail] = useState(""); const [notice, setNotice] = useState(""); const callSignInWithEmailLink = (e) => { e.preventDefault(); if (isSignInWithEmailLink(auth, window.location.href)) { signInWithEmailLink(auth, email, window.location.href) .then(() => { navigate("/profile"); }) .catch((error) => { setNotice("An occurred during sign in: ", error.name); }) } } return( <div className = "container"> <div className = "row justify-content-center"> <form className = "col-md-4 mt-3 pt-3 pb-3"> { "" !== notice && <div className = "alert alert-warning" role = "alert"> { notice } </div> } <div className = "form-floating mb-3"> <input type = "email" className = "form-control" id = "exampleConfirmEmail" placeholder = "[email protected]" value = { email } onChange = { (e) => setEmail(e.target.value) }></input> <label htmlFor = "exampleConfirmEmail" className = "form-label">Please confirm your email address</label> </div> <div className = "d-grid"> <button type = "submit" className = "btn btn-primary pt-3 pb-3" onClick = {(e) => callSignInWithEmailLink(e)}>Confirm</button> </div> </form> </div> </div> ) } export default Confirm
Confirm.jsx
저장합니다.
isSignInWithEmailLink
메서드는 먼저 사용자가 사용 중인 로그인 링크가 유효한지 확인합니다. 그렇다면 사용자 로그인을 위해 signInWithEmailLink
메소드가 호출됩니다. 다시 한번 강조하자면, signInWithEmailLink
메소드에 전달된 email
값은 사용자가 로그인 양식에 사용한 이메일 주소와 일치해야 합니다. 사용자가 신규 사용자인 경우(즉, 처음 로그인하는 경우) Firebase는 Firebase 인증 저장소에 자동으로 사용자를 생성합니다. 이는 비밀번호 없는 인증이 제공하는 단순화된 경험의 또 다른 예입니다. 신규 사용자에 대한 계정 생성은 자동으로 처리됩니다.
Profile.jsx
구축 빌드할 최종 구성 요소는 Profile.jsx
입니다. 사용자가 Confirm.jsx
통해 성공적으로 로그인하면 이 구성 요소로 라우팅됩니다. 경로는 이메일 주소로 사용자를 환영하고 로그아웃 버튼을 제공합니다. 로그아웃하면 사용자는 Login
구성 요소로 다시 라우팅됩니다.
src
디렉터리에 새 Profile.jsx
파일을 만듭니다.
다음 코드를 추가하세요.
import { auth } from "./firebase"; import { signOut } from "firebase/auth"; import { useNavigate } from "react-router-dom"; const Profile = () => { const navigate = useNavigate(); const logoutUser = async (e) => { e.preventDefault(); await signOut(auth); navigate("/"); } return( <div className = "container"> <div className = "row justify-content-center"> <div className = "col-md-4 text-center"> <p>Welcome <em className = "text-decoration-underline">{ auth.currentUser.email }</em>. You are logged in!</p> <div className = "d-grid gap-2"> <button type = "submit" className = "btn btn-primary pt-3 pb-3" onClick = {(e) => logoutUser(e)}>Logout</button> </div> </div> </div> </div> ) } export default Profile
Profile.jsx
저장합니다.React 애플리케이션을 시작합니다.
npm start
locahost:3000
으로 이동하십시오. Login
양식이 표시됩니다.
로그인하는 데 사용할 이메일을 입력하고 제출 을 클릭하세요. 제출이 성공하면 로그인 링크가 포함된 이메일이 귀하의 이메일 주소로 전송되었다는 알림이 표시됩니다.
Sign in to project-1078604952662
와 유사해야 합니다. 여기서 13자리 숫자 시퀀스는 Firebase 프로젝트의 messagingSenderId
나타냅니다(이 가이드의 3단계 참조). 아래 선택 사항 섹션에서는 로그인 링크 이메일에 '사용자 친화적인' 이름을 표시하도록 Firebase 프로젝트 이름을 수정하는 방법을 설명하겠습니다. 지금은 로그인 링크 이메일을 열고 로그인 링크를 클릭하세요. Confirm
양식으로 이동됩니다.
Confirm
양식에 로그인할 때 사용한 이메일 주소를 입력하세요. 확인 을 클릭합니다. 확인이 성공하면 Profile
페이지로 이동됩니다.
로그아웃하려면 Profile
페이지에서 로그아웃 버튼을 클릭하세요. 로그아웃에 성공하면 Login
양식으로 다시 이동됩니다.
위의 단계에서는 애플리케이션의 워크플로를 캡처합니다.
Firebase에서 보낸 로그인 링크 이메일 project-1078604952662
대신 '사용자 친화적인' 이름이 표시되도록 프로젝트 이름을 변경할 수 있습니다. Firebase 계정 에 로그인하고 Go to Console 을 클릭하세요.
비밀번호 없는 인증은 애플리케이션 개발자들 사이에서 점점 인기를 얻고 있는 것으로 보이며, 당연히 그렇습니다. 비밀번호를 관리할 필요가 없다는 명백한 이점 외에도 로그인 링크를 보내는 프로세스 자체가 확인이므로 이메일 확인이 필요하지 않습니다.
전제조건 프로젝트와 마찬가지로 여기서의 구현은 기본입니다. 다음과 같은 간단한 개선 사항을 고려할 수 있습니다.
특정 이메일 주소 도메인(예: 일반적인 스팸 이메일 도메인)을 차단/블랙리스트에 추가합니다.
Login
페이지에서 사용자가 입력한 이메일 주소를 로컬에 저장하고 Confirm
페이지에서 이메일 주소가 있는지 확인합니다. 이 접근 방식을 사용하면 사용자가 Login
페이지에 액세스했던 동일한 장치에서 로그인 링크를 클릭하면 이메일 주소가 복구되므로 Confirm
페이지에 다시 입력할 필요가 없습니다. 로컬 저장소에서. 이는 더욱 마찰 없는 사용자 경험을 제공합니다.
공식 문서를 통해 Firebase 비밀번호 없는 인증에 대해 자세히 알아볼 수 있습니다.