고미-인사이트 (3).png

Duration

2022.11.21 ~ 2023.07.02

Skill Set

React18 / Typescript / GraphQL / React API / tailwind / vite3 / yarn berry / Recoil

Goal

Features

Auth 관련 기능 / 페이지네이션 기능 / 디자인 시스템 도입 / 리포트 공유하기 기능 / amplitude 셋팅 및 이벤트 설치 / 서비스 소개 페이지 퍼블리싱

🔒 Auth 관련 기능

회원가입, 로그인, 비밀번호 재설정, 아이디/비밀번호 찾기와 같은 기능 설계 및 화면 구현했습니다.

1. 회원/비회원 권한 별 페이지 접근


기존에는 화면이 랜더링 후 useEffect로 권한 체크가 되어서, 사용자에게 화면이 보인 다음에 로그인 페이지로 이동하던 이슈 / 화면 튐 현상

page가 랜더링되기 전, router단에서 회원여부를 확인하여 접근 제어 (react-router, recoil, grahpql 사용)

스크린샷 2023-07-25 오후 8.59.53.png

// ## 1. Router - 회원정보 조회 ## //
//회원정보 전역상태 (recoil)
const [userInfo, setUserInfo] = useRecoilState(UserAtom); //✅
//cookie에 저장된 회원토큰
const storageToken = authTokenStorage.getToken();

const clearUserInfo = signInApi().clearUserInfo;
const clearAmplitude = signInApi().clearAmplitude;
const navigation = useNavigate();

//회원 정보 셋팅
const { data: userQueryData } = useMeQuery(
  { token: storageToken },
  {
		// query는 선언과 동시에 작동되기에 enabled,refetchOnWindowFocus로 작동을 제어한다.
    enabled: isFalsy(storageToken) === false, //✅
    refetchOnWindowFocus: false, //✅
    onSuccess: (res) => {
			 // 앰플리튜드에서 사용할 회원 정보 셋팅
      if (isFalsy(useCookieStorage.getCookie('AMPLITUDE_USER_ID'))) {
        _setUserId(res.me.id);
        useCookieStorage.setCookie('AMPLITUDE_USER_ID', 'true', 1);
      }
    },
    onError: (error) => {
			// 전역 상태 초기화
      clearUserInfo();
			// 앰플리튜드 초기화
      clearAmplitude();
      navigation(PATH.SIGN_IN);
    },
  },
);
// ## 4. PrivateRoute - 페이지 이동 ## //
export default function PrivateRoute() {
  const storageToken = authTokenStorage.getToken(); //✅
  const saveReturnUrl = authReturnUrl().saveReturnUrl;

  if (isFalsy(storageToken)) { //✅
		{/* 접근을 시도한 url 상태에 저장 */}
    saveReturnUrl(window.location.href); //✅
    return <Navigate to={PATH.SIGN_IN} />;
  } else {
    return <Outlet />; //✅
  }
}
// ## 2. Router - 회원정보 셋팅 ## //
//query가 실행되어 유저정보(userQueryData)가 변경된 경우, 전역상태 업데이트
useEffect(() => {
  if (userQueryData && isFalsy(userInfo)) {
    setUserInfo(userQueryData); //✅
  }
}, [userQueryData]);
// ## 3. Router - 페이지 이동 ## //
return (
  <Routes>
    {routeList.map((route) => {
		 {/* 인증을 반드시 해야지만 접속 가능한 페이지 정의 */}
      if (route.isPrivate) { //✅
        return (
          <Route key={route.path} element={<PrivateRoute />}> //✅
            <Route //✅
              key={route.path}
              path={route.path}
              element={createElement(route.component)}
            />
          </Route>
        );
      }

      return (
        <Route
          key={route.description}
          path={route.path}
          element={createElement(route.component)}
        />
      );
    })}
  </Routes>
);

✅ Result?

화면이 사용자에게 보이기 전 권한 체크가 진행되어 화면이 튀던 문제 개선됨


비회원이 회원만 접근할 수 있는 화면을 접근하려고 할 때, PrivateRouter로 인해 console.log가 출력된다.

비회원이 회원만 접근할 수 있는 화면을 접근하려고 할 때, PrivateRouter로 인해 console.log가 출력된다.