Protected Routes & useRouter exception
1. Protected Routes 설정
보통 토큰값을 쿠키에 저장할텐데 해당 쿠키값이 없을 경우 다른 페이지로 이동하게 하고싶으면 어떻게 할까요?
단순한 방법으론 페이지의 useEffect안에 쿠키값이 있는지 확인하고 redirect하면 될 것 같습니다.
정말 간단하지만 해당 방법으론 매 페이지마다 해당 로직을 적어야 하며 소스가 더러워 질 것입니다.
Nextjs에선 middleware를 통해 이를 해결할 수 있습니다.
깃헙 링크 공유드립니다: https://github.com/biglol10/tistory_source/tree/main/route-example
우선 프로젝트 루트 폴더에 middleware.js를 생성해줍니다.
- middleware.js 파일 소스
import { NextResponse } from "next/server";
const middleware = (request) => {
const cookieValue = request.cookies.get("token");
const pagePath = request.nextUrl.pathname;
// Protected routes 목록
const protectedRoutesArray = ["/protected", "/dashboard"];
// Proctected routes로 진입하는지 확인
const isWithProtectedRoutes = () => {
return protectedRoutesArray.some((route) => pagePath.startsWith(route));
};
// 쿠키값이 없으며 protected routes로 진입할 경우 로그인 페이지로 이동
if (!cookieValue && isWithProtectedRoutes()) {
return NextResponse.redirect(
`http://localhost:3000/${
process.env.NODE_ENV === "development" ? "develop" : "production"
}/login`
);
}
};
export default middleware;
매 페이지 진입 시 middleware를 거치게 되며 해당 middleware에선 쿠키값이 있는지 확인 후 로그인 페이지로 이동시킬지 아니면 사용자가 원하는 페이지에 진입시킬지 결정합니다.
샘플 프로젝트를 살펴보겠습니다.
![]() |
![]() |
쿠키값이 없는데 [Go to Protected page] 버튼을 클릭하면 로그인 페이지로 이동합니다.
![]() |
![]() |
임의로 쿠키값을 생성 후 버튼을 클릭하면 원하는 페이지로 이동되는 것을 확인할 수 있습니다.
2. useRouter 관련 이상한 점 (Nextjs 12)
http://localhost:3000/dev/page/myvariable 에서 myvariable값을 가져오고 싶은 경우처럼 url에서 path variable을 가져와 로직을 작성해야 하는 경우가 있을겁니다.
일반적으로 useRouter을 이용해 router.query로 값을 가져올 수 있습니다.
다만 Next 12의 경우 특정 상황에선 이 값을 못가져오는 경우가 있습니다.
확인해보니 Next 13에선 잘 가져옵니다!!
그 특정 상황은 바로 next.config.js에서 basePath를 설정했을 때입니다.
- next.config.js 파일 소스
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
};
module.exports = {
...nextConfig,
basePath: process.env.NODE_ENV === "development" ? "/develop" : "/production",
async redirects() {
return [
{
source: "/",
destination: `/${
process.env.NODE_ENV === "development" ? "develop" : "production"
}`,
basePath: false,
permanent: false,
},
];
},
};
이처럼 개발모드면 develop를 운영모드면 production을 url에 붙힙니다.
이후 샘플 페이지 하나 생성합니다.
- routerCareful/[value].jsx
import { useRouter } from "next/router";
import { Layout1 } from "@components/index";
import { useEffect } from "react";
const RouterCareful = ({ queryObj = {} }) => {
const router = useRouter();
const { value } = router.query;
useEffect(() => {
console.log(`useRouter value is ${value}`);
console.log(`getServerSideProps value is ${queryObj.value}`);
}, []);
return (
<>
<div style={{ borderColor: "red" }}>
This is the value from dynamic route = {value}
</div>
<br />
<div style={{ borderColor: "blue" }}>
This is the value from ServerSideRendering = {queryObj.value}
</div>
</>
);
};
RouterCareful.Layout = Layout1;
export const getServerSideProps = async (context) => {
return { props: { queryObj: context.query } };
};
export default RouterCareful;
![]() |
![]() |
위의 사진처럼 input에 qwer을 입력 후 [Go to dynamic route page]버튼을 클릭 시 useRouter로 path variable을 못 가져오고 undefined가 뜨는 것을 확인할 수 있습니다.
새로고침하면 나오지만 페이지에서 api request를 날리고 다른 작업을 하는 것이 있을 경우 네트워크 요청도 이뤄지고 전역상태관리에 대한 신경도 써야 한다는 단점이 있습니다.
Nextjs docs를 보시면
서버사이드 랜더링을 사용하지 않을 시 {} 값으로 된다고 되어있는데 basePath를 추가했다고 server-side rendering을 비활성화 시키는 것이 아니기에 그리고 Next 13에선 고쳐진 것을 보아 일종의 버그였던 것으로 보입니다.
Chatgpt의 답변
Pre-rendering(Next.js 가 각 페이지에 대한 HTML 을 생성하는 것)할 때 query라는 객체는 아무런 값이 없는 상태로 client에 전달될 것이라 값은 가져올 수 없는 상태입니다. CSR상태일 땐 query 객체에 값이 있어 이를 이용할 수 있습니다.
따라서 Next 12에서 해당 query객체를 다룰 때 소스에 적혀있는 것처럼 getServerSideProps를 이용해 router.query값을 가져와야 합니다.