-
[NEXT] HOC를 이용하여 next.js router guard 만들기Next.js 2022. 9. 4. 15:07
vue를 사용할 때는 vue-router에서 제공하는 navigation guard 기능이 있었기 때문에,
각 페이지에 접근을 할 때 guard 처리해주기가 수월했다.
하지만, next.js에서는 그러한 기능이 따로 없기 때문에 직접 만들어야 했다.
그래서, hoc를 통해 next.js router guard(navigation guard)를 만들어보고자 한다.
1) 목적
각 페이지에 접근을 할 때, 각 페이지별 접근을 할 수 있는 유저가 있고, 접근이 불가능한 유저가 있을 것이다.
예를 들어, 로그인 페이지 같은 경우 로그인을 안한 유저는 접근이 가능하지만, 이미 로그인 한 유저라면 접근이 불가능하게 만들어야 한다.
이러한 접근에 대한 검사를 매 페이지마다 이루어져야 하는데, 각 페이지 컴포넌트에 이 설정을 셋팅을 하는 것은 번거로운 일이다.
그래서, hoc를 이용하여 페이지 컴포넌트를 보여주기 전, 유저에 대한 접근 권한을 판별하는 전용하는 hoc를 만들어 보고자 한다.
2) 간략 요약
- hoc 컴포넌트를 통해, 유저의 권한 판별
- 각 페이지의 컴포넌트에 hoc 감싸주기
3) 구체적인 과정
[0] 사전 지식
- hoc
혹시 hoc에 대한 개념이 부족하다면, 아래 글을 참조 부탁드립니다.
https://uni-s-code.tistory.com/24
- firebase를 통한 authentication 구현(추후 블로그에 작성하겠다.)
[1] hoc 폴더 안에 guard 파일 생성
hoc 컴포넌트를 만들때에는 with~ 컴포넌트 네이밍을 지키도록 하자.
[2] hoc 컴포넌트 코드
import Router from 'next/router'; import { useEffect, useState } from 'react'; import { NO_USER_GUARD, USER_GUARD, PUBLIC_GUARD } from 'data/guardTypes'; import { getAuth, onAuthStateChanged } from 'firebase/auth'; const withAuth = (WrappedComponent, guard, redirect = null) => { const RouteGuard = (props) => { const [authLoading, setAuthLoading] = useState(true); const [authUser, setAuthUser] = useState(null); useEffect(() => { if (user?.userId) { console.log(user); setRoleLoading(false); } }, [user]); useEffect(() => { const auth = getAuth(); onAuthStateChanged(auth, async (user) => { setAuthUser(user); setAuthLoading(false); }); }, []); const checkVerification = (guard, authUser) => { switch (guard) { case NO_USER_GUARD: return !authUser; case USER_GUARD: return authUser; case PUBLIC_GUARD: return true; default: return true; } }; if (typeof window == 'undefined') { return null; } if(authLoading){ if (checkVerification(guard, authUser)) { console.log(`route - ${guard}: pass`); return <WrappedComponent {...props} />; } else { console.log(`route - ${guard}: not pass`); { redirect ? Router.push(redirect) : Router.push('/'); } } } }; RouteGuard.displayName = 'routeGuard'; return RouteGuard; }; export default withAuth;
[3] guard type 정의
원하는 위치에 guard에 대한 type을 정의하자.
export const NO_USER_GUARD = 'noUserGuard'; export const USER_GUARD = 'userGuard'; export const PUBLIC_GUARD = 'publicGuard';
[4] 페이지별 hoc 적용
✅ user만 들어올 수 있는 페이지 (ex- 마이페이지, 프로필)
import type { NextPage } from "next"; import withAuth from 'hoc/withRouteGuard'; // HOC import import { USER_GUARD } from 'data/guardTypes'; // guard type import const OnlyUser: NextPage = () => { return <div>this is only user page</div>; }; export default withAuth(OnlyUser, USER_GUARD);
✅ user가 아닌 사람만 들어올 수 있는 페이지 (ex-회원가입, 로그인)
import type { NextPage } from "next"; import withAuth from 'hoc/withRouteGuard'; // HOC import import { NO_USER_GUARD } from 'data/guardTypes'; // guard type import const NoUser: NextPage = () => { return <div>this is no user page</div>; }; export default withAuth(NoUser, NO_USER_GUARD);
참조 자료
https://github.com/vercel/next.js/discussions/11822
https://dev.to/shubhamverma/implement-protected-routes-in-nextjs-37ml
'Next.js' 카테고리의 다른 글
[Next.js] next.js 에서 meta tag 손쉽게 적용하기 (feat. next-seo) (0) 2023.03.16 [Next] i18n 자동화 프로세스 도입 - (3) : key upload, download (0) 2022.12.11 [Next] production 배포 환경에서, console log 숨기기 (0) 2022.12.04 [Next] i18n 자동화 프로세스 도입 - (1) : i18next-scanner를 통해 코드에서 key 값 추출하기 (1) 2022.11.27 [Next] i18n 사용법 with next-i18next (0) 2022.11.13