ReactJ를 사용하여 풀 스택 웹 앱을 구축하는 초보 시절에 저는 프런트엔드에서 인증을 처리하는 방법에 대해 혼란스러워했습니다. 즉, 백엔드에서 액세스 토큰을 받은 후 다음에 무엇을 해야 합니까? 로그인 상태를 어떻게 유지하나요?
대부분의 초보자는 "아, 그냥 토큰을 상태에 저장하세요"라고 가정합니다. 그러나 나는 이것이 최고의 솔루션이 아니었고 전혀 솔루션이 아니라는 것을 빨리 알게 되었습니다. 대부분의 숙련된 ReactJs 개발자가 알고 있듯이 상태는 페이지를 새로 고칠 때마다 지워지기 때문에 일시적이므로 우리는 확실히 할 수 있습니다. 새로 고칠 때마다 사용자가 로그인할 필요가 없습니다.
반응으로 풀 스택 앱을 구축하고 경험이 풍부한 개발자의 인증 접근 방식을 연구하고 다른 두 애플리케이션에서 프로세스를 복제하는 데 약간의 경험을 얻었으므로 가이드를 제공하고 싶습니다. 내가 현재 어떻게 처리하고 있는지. 어떤 사람들은 그것이 최선의 방법이라고 생각하지 않을 수도 있지만 나는 지금까지 그것을 내 방식으로 채택했고 다른 개발자들이 사용하는 다른 방법을 배우는 데 열려 있습니다.
인증 프로세스를 시작하기 위해 이메일과 비밀번호(기본 이메일 및 비밀번호 인증을 사용한다고 가정)를 백엔드에 제출했습니다. 이 문서에서는 인증을 프런트엔드에서만 처리하는 방법에 대해 다루기 때문에 백엔드에서 인증을 처리하는 방법에 대해서는 언급하지 않겠습니다. HTTP 응답에서 토큰을 받은 부분으로 건너뛰겠습니다. 다음은 이메일과 비밀번호를 서버에 제출하고 응답으로 토큰과 사용자 정보를 받는 간단한 로그인 양식 구성 요소의 코드 예제입니다. 이제 단순화를 위해 내 양식 값은 상태로 관리되므로 프로덕션 앱에는 formik과 같은 강력한 라이브러리를 사용하는 것이 훨씬 더 나을 것입니다.
import axios from 'axios' import { useState } from "react" export default function LoginForm() { const [email, setEmail] = useState("") const [password, setPassword] = useState("") const handleSubmit = async() => { try { const response = await axios.post("/api/auth/login", { email, password }) if (response?.status !== 200) { throw new Error("Failed login") } const token = response?.data?.token const userInfo = response?.data?.userInfo } catch (error) { throw error } } return() }
전체 애플리케이션을 래핑하거나 인증 컨텍스트 공급자의 인증 상태에 액세스해야 하는 부분만 래핑합니다. 이는 일반적으로 루트 App.jsx 파일에서 수행됩니다. context API가 무엇인지 모른다면 Reactjs 문서를 확인해 보세요. 아래 예에서는 생성된 AuthContext 공급자 구성 요소를 보여줍니다. 그런 다음 App.jsx로 가져오고 App 구성 요소에 반환된 RouterProvider를 래핑하는 데 사용되므로 애플리케이션의 어디에서나 인증 상태에 액세스할 수 있습니다.
import { createContext } from "react"; export const AuthContext = createContext(null) export default function AuthProvider({children}) { return({children} ) }
import React from "react"; import { createBrowserRouter, RouterProvider } from "react-router-dom"; import AuthProvider from "./AuthContext"; const router = createBrowserRouter([ // your routes here ]) function App() { return() } export default App
인증 컨텍스트에서는 "isLoggedIn" 및 "authenticatedUser"라는 두 가지 상태 변수를 초기화해야 합니다. 첫 번째 상태는 처음에 'false'로 설정되고 로그인이 확인되면 'true'로 업데이트되는 부울 유형입니다. 두 번째 상태 변수는 이름, 이메일 등과 같은 로그인된 사용자 정보를 저장하는 데 사용됩니다. 이러한 상태 변수는 조건부 렌더링을 위해 애플리케이션 전체에서 액세스할 수 있도록 컨텍스트 구성 요소에 반환된 공급자 값에 포함되어야 합니다. .
import { createContext, useState } from "react"; export const AuthContext = createContext(null) export default function AuthProvider({children}) { const [isLoggedIn, setIsLoggedIn] = useState(false) const [authenticatedUser, setAuthenticatedUser] = useState(null) const values = { isLoggedIn, authenticatedUser, setAuthenticatedUser } return({children} ) }
Nanostores는 Javascript 앱의 상태를 관리하기 위한 패키지입니다. 패키지는 별도의 파일에서 간단히 초기화하고 상태를 사용하거나 업데이트하려는 구성 요소로 가져오는 방식으로 여러 구성 요소의 상태 값을 관리하기 위한 간단한 API를 제공합니다. 그러나 1단계의 HTTP 응답에서 수신된 인증 토큰을 저장하기 위해 nanostores/persist를 사용하게 됩니다. 이 패키지는 상태를 localStorage에 저장하여 상태를 유지하므로 페이지를 새로 고칠 때 지워지지 않습니다. @nanostores/react는 nanostore에 대한 특정 반응 통합으로, nanostore 상태에서 값을 추출하기 위한 useStore 후크를 사용할 수 있게 합니다.
이제 다음과 같이 진행할 수 있습니다.
nanostores, @nanostores/percious 및 @nanostores/react 패키지를 설치합니다.
user.atom.js라는 별도의 파일 또는 원하는 이름으로 선택한 파일에서 nanostores/pertant를 사용하여 'authToken' 저장소와 '사용자' 저장소를 초기화합니다.
이를 로그인 양식 구성 요소 파일로 가져오고 로그인 응답에서 받은 토큰 및 사용자 데이터로 상태를 업데이트합니다.
npm i nanostores @nanostores/persistent @nanostores/react
import { persistentMap } from '@nanostores/persistent' export const authToken = persistentMap('token', null) export const user = persistentMap('user', null)
import { authToken, user } from './user.atom' const handleSubmit = async() => { try { const response = await axios.post("/api/auth/login", { email, password }) if (response?.status !== 200) { throw new Error("Failed login") } const token = response?.data?.token const userInfo = response?.data?.userInfo authToken.set(token) user.set(userInfo) } catch (error) { throw error } }
이제 앱을 래핑하는 인증 컨텍스트에서 토큰과 사용자 상태가 계속 업데이트되고 전체 앱에서 사용할 수 있는지 확인해야 합니다. 이를 달성하려면 다음을 수행해야 합니다.
'authToken' 및 '사용자' 스토어를 가져옵니다.
useEffect 후크를 후크 내부에서 초기화하고 토큰이 'authToken' 저장소에 있는지 확인하는 'checkLogin()' 함수를 생성합니다. 존재하는 경우 토큰이 있는지 확인하는 함수를 실행합니다. 만료되었습니다. 확인 결과에 따라 사용자를 로그인 페이지로 리디렉션하여 인증을 받거나… 'isLoggedIn' 상태를 true로 설정합니다. 이제 로그인 상태가 더 자주 추적되도록 하기 위해 현재 경로가 변경될 때마다 이 후크가 실행되도록 설정할 수 있습니다. 이렇게 하면 앱과 상호작용하는 동안 토큰이 만료되면 사용자가 쫓겨나거나 로그인 페이지로 리디렉션될 수 있습니다. .
앱이 로드되거나 새로 고쳐질 때마다 authToken 저장소의 토큰을 사용하여 백엔드에서 사용자 정보를 가져오는 기능이 포함된 또 다른 useEffect 후크를 초기화합니다. 성공적인 응답을 받으면 'isLoggedIn' 상태를 true로 설정하고 'authenticatedUser' 상태와 'user' 스토어를 응답에서 받은 사용자 정보로 업데이트하세요.
다음은 업데이트된 AuthProvider 구성 요소 파일입니다.
import { createContext, useState } from "react"; import { authToken, user } from './user.atom'; import { useStore } from "@nanostores/react"; import { useNavigate, useLocation } from "react-router-dom"; import axios from "axios"; export const AuthContext = createContext(null) export default function AuthProvider({children}) { const [isLoggedIn, setIsLoggedIn] = useState(false) const [authenticatedUser, setAuthenticatedUser] = useState(null) const token = useStore(authToken) const navigate = useNavigate() const { pathname } = useLocation() function isTokenExpired() { // verify token expiration and return true or false } // Hook to check if user is logged in useEffect(() => { async function checkLogin () { if (token) { const expiredToken = isTokenExpired(token); if (expiredToken) { // clear out expired token and user from store and navigate to login page authToken.set(null) user.set(null) setIsLoggedIn(false); navigate("/login"); return; } } }; checkLogin() }, [pathname]) // Hook to fetch current user info and update state useEffect(() => { async function fetchUser() { const response = await axios.get("/api/auth/user", { headers: { 'Authorization': `Bearer ${token}` } }) if(response?.status !== 200) { throw new Error("Failed to fetch user data") } setAuthenticatedUser(response?.data) setIsLoggedIn(true) } fetchUser() }, []) const values = { isLoggedIn, authenticatedUser, setAuthenticatedUser } return({children} ) }
이제 5단계에서 생성된 두 개의 useEffect 후크가 전체 앱의 인증 상태를 관리하는 역할을 담당합니다. 새로 고침을 수행할 때마다 로컬 저장소에서 토큰을 확인하고 백엔드에서 직접 최신 사용자 데이터를 검색하고 'isLoggedIn' 및 'authenticatedUser' 상태를 업데이트하기 위해 실행됩니다. React에서 'AuthContext' 및 'useContext' 후크를 가져오고 구성 요소 내에서 이를 호출하여 값에 액세스하고 일부 조건부 렌더링에 사용함으로써 모든 구성 요소 내에서 상태를 사용할 수 있습니다.
import { useContext } from "react"; import { AuthContext } from "./AuthContext"; export default function MyLoggedInComponent() { const { isLoggedIn, authenticatedUser } = useContext(AuthContext) return( { isLoggedIn ?Welcome {authenticatedUser?.name}
: } > ) }
로그아웃 시 'authToken' 및 'user' 저장소를 null로 설정하여 지워야 한다는 점을 기억하세요. 또한 'isLoggedIn'을 false로 설정하고 'authenticatedUser'를 null로 설정해야 합니다.
읽어주셔서 감사합니다!
부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.
Copyright© 2022 湘ICP备2022001581号-3