삐옹

React 접근제한 라우팅 만들기 본문

React

React 접근제한 라우팅 만들기

삐옹 2022. 7. 23. 22:55

상황

로그인을 하고나서 workspace 배열 내에 데이터 유무에 따라

처음 로그인한 사람(뉴비)과 기존 유저에게 다른 화면을 보여주어야 한다.


생각 할 것

앱의 상태에 따른 state 관리가 핵심이다.

  1. workspace 배열 내에 데이터 유무에 따라 유저의 상태를 어떻게 표현 할 것인지 명시한다.
    (앱의 상태를 나타내는 state를 만든다.)
  2. 로그인 일 때와 아닐 때를 구분한다
  3. 뉴비인지 아닌지 판단하는 상태를 만들기
  4. 로딩 중 일 떄와 아닐 때 를 구분하는 상태만들기.(스피너를 위함! 난 꼭 스피너를 넣어야겠음!)

    +) 로그인 상태 유지하기

순서대로 코드로 살펴보기

상황 별 유저의 상태

// App.js

// 정리해보면 유저의 상태는 3가지로 나뉜다
// 워크스페이가 있는지 없는지 판단 중일 떄 -> "모름"
// 워크스페이가 있을 떄 -> "워크스페이스가_없는_유저"
// 워크스페이가 없을 떄 -> "워크스페이스가_있는_유저"

const APP_USER_STATE = {
  UNKNOWN: "모름", // 모름 상태일 떄는 스피너가 돌 것 이다!
  NEWBIE: "워크스페이스가_없는_유저",
  USER: "워크스페이스가_있는_유저",
};

const App = () => { ...

}

 

앱의 상태를 나타내는 state를 만든다.

  const App = () => {
	const APP_USER_STATE = {
  		UNKNOWN: "모름", // 모름 상태일 떄는 뺑뻉이 스피너가 돌게한다
  		NEWBIE: "워크스페이스가_없는_유저",
  		USER: "워크스페이스가_있는_유저",
	};
    
    // 초깃값은 모름으로 해놓는다. 이때는 항상 스피너로 처리하면 될 듯
  	const [appState, setAppState] = useState(APP_USER_STATE.UNKNOWN);
    

  	// appState가 변경이 되면 loading 상태와 newbie인지 아닌지의 상태가 바뀐다
    	// appstate는 워크스페이스 리스트를 잘 받아온 뒤 NEWBIE or USER로 변경 예정
  	const isLoading = appState === APP_USER_STATE.UNKNOWN;
  	const isNewbieUser = appState === APP_USER_STATE.NEWBIE;  
  ...
  }

워크스페이스 리스트의 값에 변화가 생기면 2초 뒤 appState의 상태를 업데이트한다.

// App.js

const [appState, setAppState] = useState(APP_USER_STATE.UNKNOWN);
// ...
  useEffect(() => {
    setTimeout(() => {
      try {
        axios
          .get("https://0jun.shop/api/work-spaces/lists", {
            headers: {
              Authorization: `Bearer ${getItemFromLs("myToken")}`,
            },
          })
          .then((res) => {
            if (res.data.success) {
              const wsInfoList = res.data.includedList;
              const wsList = wsInfoList.map((ws) => ws.name);
             
              
            // 워크스페이스 리스트가 잘 받아와지면 appstate를 업데이트한다
            // ***이때 isLoading의 상태도 자동으로 업데이트 된다***
              setAppState(
                wsList.length !== 0
                  ? APP_USER_STATE.USER
                  : APP_USER_STATE.NEWBIE
              );
            }
          })
          .catch((error) => {
            console.log(error);
          });
      } catch {
        alert("데이터를 불러오는 도중 에러가 발생했습니다 :(");
      }
    }, 2000);
  }, []);

 

로딩상태라면 스피너를 보여주고 로딩상태가 아니라면 Main 화면을 보여준다

*뉴비인지 아닌지는 Main 컴포넌트에서 가리기 위해 props로 전달한다

<Routes>
   <Route path="/" element={<Login />} />
   <Route path="/signup" element={<Signup />} />
   
   // 로컬스토리지의 값에 따라 로그인이 됬으면 true 아니면 false를 반환하는 모듈을 만들었다
   {isLogin() ? (
     <Route
       path="/main"
       element={
         isLoading ? (
           <Spinner />
         ) : (
           <PrivateRoute
             isNewbieUser={isNewbieUser}
             component={<Main />}
           />
         )
       }
     />
   ) : (
     <Navigate to="/login" />
   )}
   
 </Routes>

워크스페이스 리스트에 변경이 일어나 appstate가 **변경된 후** isNewbieUser의 상태가 변경되었을 것이다.

워크스페이스가 없다면:

isNewbieUser = false 에서 isNewbieUser = true로 바뀌어서 props로 전달이 된다

워크스페이스가 있다면:

isNewbieUser = false 값 그대로 props로 전달이 된다

import React from "react";
import ScreenForNewbie from "./ScreenForNewbie";

const PrivateRoute = ({ isNewbieUser, component: Component }) => {

  return <> {!isNewbieUser ? Component : <ScreenForNewbie />}</>;
};

export default PrivateRoute;

팁))

만약 isLoading이라는 값이 변경되게끔 하는 로직이 없다면??

 <Route
   path="/main"
   element={
       <PrivateRoute
         isNewbieUser={isNewbieUser}
         component={<Main />}
       />
   }
 />

워크스페이스에 값이 들어오기 전의 isNewbieUser의 초깃값은 false이기 때문에(아래 코드 참고)

뉴비를 위한 화면이 잠깐 생겼다가 기존 유저를 위한 화면이 보이게 된다.

확실히 Loading상태가 끝나야만 뉴비화면 vs 기존유저 화면을 나눠주게끔 하는게 포인트였다.

export const APP_USER_STATE = {
  UNKNOWN: "모름",
  NEWBIE: "워크스페이스가_없는_유저",
  USER: "워크스페이스가_있는_유저",
};
------------------------

const [appState, setAppState] = useState(APP_USER_STATE.UNKNOWN);

------------------------

const isNewbieUser = appState === APP_USER_STATE.NEWBIE;

 

정리

상황에 따라 다른 화면을 보여주려면

결국엔 어떤 상태에서 어떤 컴포넌트를 보여줄 것인가가 핵심이다.

 

접속 할 사용자가 뉴비라고 가정하고 상태들의 흐름을 다시 한번 정리해보자

 

화면 첫 더링 시

appState = 모름

isLoading = true => spinner 돌아가는 중..

isNewbieUser = false 

 

useEffect 에서 워크스페이스 리스트 업데이트 후

appState = 워크 스페이스가 없는 유저

isLoading = false => Spinner 끝!

isNewbieUser = true => <ScreenForNewbie/> 렌더링

 

특정 경로로의 접근에 제한을 두어야 할 때

이렇게 상태들을 정의해두고 활용하는 방식은 두고두고 써먹기 좋은 것 같다