
유저의 상태에 따라 페이지를 분기적으로 라우팅해야 하기 때문에 유저의 상태를 전역적으로 관리할 필요가 있었다.(ex. 판매자와 구매자에 따라 보이는 화면이 다르다.)
처음에 복잡하게 생각했는데 알고보니 Firebase Authentication에서 유저의 현재 상태를 감지할 수 있는 onAuthStateChanged 함수가 있다는 것을 알고 이를 사용하기로 했다.
또한 Context API를 통해 이렇게 감지한 유저의 상태를 전역으로 관리하기로 했다.
context 폴더를 생성하고 폴더 안에 authContext.tsx 파일을 생성한다.
provider 폴더를 생성하고 폴더 안에 authProvider.tsx 파일을 생성한다.

authContext.tsx
import { createContext } from "react";
import { UserInfoType } from "@/types";
export const AuthContext = createContext<UserInfoType | null>(null);
authProvider.tsx 에서 firebaseAuth.onAuthStateChanged 함수를 통해 유저의 상태를 감지하여 이를 user에 저장한다.
그리고 AuthContext.Provider를 사용하여 자식 컴포넌트들에게 사용자 정보를 제공할 수 있도록 한다.
import { ReactNode, useEffect, useState } from "react";
import { AuthContext } from "../context/authContext";
import { firebaseAuth, getUser } from "@/services/firebase";
import { UserInfoType } from "@/types";
// provider/authProvider.tsx 에서 유저 정보를 내려줘야 한다.
// onAuthStateChanged를 실행하고 useEffect를 사용해 변경을 감지한다.
function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<UserInfoType | null>(null);
useEffect(() => {
return firebaseAuth.onAuthStateChanged(async (currentUser) => {
console.log("구독 시작: ", currentUser);
if (currentUser) {
await getUser(currentUser.uid).then((user) => {
if (user) {
setUser({
type: user.type,
name: user.name,
email: user.email,
});
}
});
} else {
setUser(null);
}
});
}, []);
return <AuthContext.Provider value={user}>{children}</AuthContext.Provider>;
}
export default AuthProvider;
최상단 파일(Main.tsx)에서 Provider로 감싸준다.
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<AuthProvider>
<App />
</AuthProvider>
</React.StrictMode>
);
그리고 App.tsx 파일 내부에서 useInfo라는 변수를 선언하여 AuthContext를 받아와, 이를 통해 유저 타입을 확인하여 분기적으로 라우팅을 수행한다.
const userInfo = useContext(AuthContext);
const isAdmin = userInfo?.type === "관리자" ? true : false;
isAdmin ? PrivateRoutes() : PublicRoute(userInfo),