
문제 상황
해당 페이지에는 접근이 가능한데(예를 들면 버튼을 클릭해서 이동하는 경우 페이지에 접근 가능) 주소창에 URL을 직접 입력하거나 페이지를 새로고침하면 'No routes matched location" 이라는 에러가 발생했다.
그 이유는 App 컴포넌트에서 useContext를 통해 유저 정보를 확인해서 분기적으로 라우팅을 수행하는 과정에서 문제가 있었기 때문이다.
authProvider.tsx 에서는 다음과 같이 setUser를 수행한다.
onAuthStateChanged 이벤트 핸들러 내부의 코드는 비동기적으로 실행되기 때문에 유저 정보를 저장하고 이를 App.tsx에서 확인하는 과정에서 유저의 타입이 제대로 확인되지 않고 있었던 것이다.
useEffect(() => {
return firebaseAuth.onAuthStateChanged(async (currentUser) => {
if (currentUser) {
await getUser(currentUser.uid).then((user) => {
if (user) {
setUser({
type: user.type,
name: user.name,
email: user.email,
});
}
});
}
});
}, []);
export default function App() {
const userInfo = useContext(AuthContext);
const isAdmin = userInfo?.type === "관리자" ? true : false;
}
문제 해결
분기 라우팅은 유저의 현재 상태에 따라 바로 진행되어야 하기 때문에 localStorage에 유저의 타입을 넣어주어 이를 확인하는 방식으로 해결했다.
useEffect(() => {
return firebaseAuth.onAuthStateChanged(async (currentUser) => {
if (currentUser) {
await getUser(currentUser.uid).then((user) => {
if (user) {
setUser({
type: user.type,
name: user.name,
email: user.email,
});
// localStorage에 유저 타입 저장
localStorage.setItem("user type", userInfo.type);
}
});
}
});
}, []);
export default function App() {
const isAdmin = localStorage.getItem("user type") === "관리자";
}
localStorage에 저장된 데이터는 사용자의 로컬 브라우저에 저장되므로 보안에 취약하기에 노출되어도 괜찮은 user type만을 넣어주는 방식으로 적용하였다.
그런데 만약 임의의 유저가 localStorage의 user type값을 조작한다면 사용자가 일반 회원이더라도 관리자의 페이지를 볼 수 있지 않을까 하는 생각이 들었다.
실제로 localStoragef의 user type 값을 바꿔보니 그런 일은 일어나지 않았다.
왜냐하면 사용자가 user type값을 임의로 변경하더라도 페이지가 새로고침되면서 useEffect의 onAuthStateChanged를 통해 새로운 유저의 정보를 받아와 다시 localStorage에 저장되기 때문이다.