이전 포스팅에서 next-auth config 설정과 작동원리를 알아보았다.
저번 포스팅에서는 내가 생각해 낼 수 있는 조건부 라우팅에 대해 알아봤었다.
useEffect
, HOC Pattern
등...
Next.js middleware는 서버 측에서 요청을 처리하기 전에 로직을 실행할 수 있는 기능이다.
이 미들웨어를 통해 조건부 라우팅을 하려고 생각이 들었을 때,
가장 먼저 떠오르는 것은 미들웨어가 라우팅 전에 일어나는 것인가? 아니면 이후에 일어나는 건지를 생각해야 했다.
그리고 Next.js에서는 다음과 같은 순서대로 실행이 됨을 알았다.
next.config.js
에서 설정된 headers
next.config.js
에서 설정된 redirects
middleware
: 페이지 rewrite
, redirect
등을 수행next.config.js
에서 설정된 beforeFiles
(페이지 rewrite)public/
, _next/static/
, pages/
, app/
등next.config.js
에서 설정된 afterFiles
(페이지 rewrite)/blog/[slug]
next.config.js
에서 설정된 fallback
(페이지 rewrite)이렇게 middleware
가 파일 시스템 기반 라우팅 이전에 실행 되므로, middleware를 통해 조건부 라우팅을 할 수 있음을 확신시 했다.
추가적으로 middleware.ts
파일안에, config matcher
를 사용하여 원하는 url경로만을 지정할 수 도 있다.
import { getToken } from 'next-auth/jwt';
import { NextRequest } from 'next/server';
const ROOT = '/';
const RESTRIC_ROUTE = ['/calendar', '/gallery/add', '/profile'];
const DEFAULT_REDIRECT = '/auth/login';
export default async function middleware(req: NextRequest) {
const { nextUrl } = req;
const token = await getToken({ req }); // client:X, Server:O // getToken의 token 값으로 조건부 처리를 해준다.
const isAuthenticated = !!token;
const isPublicRoute = RESTRIC_ROUTE.includes(nextUrl.pathname);
console.log('🚀 ~ middleware ~ isPublicRoute:', isPublicRoute);
// 로그인시 auth/login으로 넘어가지 않게 하기
if (isAuthenticated && !isPublicRoute) return Response.redirect(new URL(ROOT, req.url));
if (!isAuthenticated && isPublicRoute) return Response.redirect(new URL(DEFAULT_REDIRECT, req.url));
}
export const config = {
matcher: ['/auth/login', '/calendar', '/gallery/add', '/profile'],
};
위의 코드는 프로젝트에서 사용한 코드이다.
config matcher를 사용하여
/calendar
, /gallery/add
, /profile
] 은 보호하고, [/auth/login
]은 허용하기/auth/login
] 은 보호하고 나머지는 허용이렇게 로직을 짰다.
next-auth에서도 미들웨어를 지원한다.
지금 작성한 코드를 봐도 딱히, 위에서 사용한 로직을 해도 될것 같지만,
나만의 목표가 있기에, 고민하고, 작동원리를 확인하고, 적용했다.
- 라이브러리의 전반적인 사용에 있어서, 확장성을 가지는 것이 목표이다.
- 요번 프로젝트는 많은 것을 알아가고, 최대한 사용하는 라이브러리의 기능들의 작동원리와 사용법을 익히는 것이다.
그래서 만들어 봤다.
// 내가 따로 공모전 블로그에 포스팅 하기 위해서, 따로 프로젝트 하나를 팠다.
// 조건부 라우팅이 위에 것과 다르다.
import { NextRequestWithAuth, withAuth } from "next-auth/middleware";
const RESTRIC_ROUTE = ["/zod", "/cookie", "/redirect"];
const AUTH_PAGE = "/auth-nextAuth";
const HOME_PAGE = "/";
export default withAuth(
async function middleware(req: NextRequestWithAuth) {
const { token } = req.nextauth;
if (req.nextUrl.pathname === AUTH_PAGE && token) {
//return Response.redirect(req.url);// 이렇게 하면 무한 redirection된다.
return Response.redirect(new URL(HOME_PAGE, req.url));
}
},
{
secret: process.env.NEXTAUTH_SECRET,
callbacks: {
authorized({ req, token }) {
const { nextUrl } = req;
const isAuthenticated = !!token;
const isPublicRoute = RESTRIC_ROUTE.includes(nextUrl.pathname);
// 로그인 후 RESTRIC_ROUTE 진입 가능
if (isAuthenticated && !isPublicRoute) return true;
// 로그인 전 RESTRIC_ROUTE 진입 불가
if (!isAuthenticated && isPublicRoute) return false;
// 그외 라우팅 처리 및, middleware에서 설정할 것 있으면 넘기기
return true;
},
},
}
);
export const config = {
matcher: [...RESTRIC_ROUTE, "/auth-nextAuth"],
};
// 로그인 전, 로그인page O, restricRoute X
// 로그인 후, 로그인 page X , restricRoute O
next-auth에서 작동하는 미들웨어의 작동원리는 먼저
withAuth(middleware,options)
에서 options의 callbacks의authorized
부터 작동 후에,middleware
가 작동한다 .
그렇기에
이 함수는 return 하는 값이 boolean이다.
false면 내가 authOptions
에서 custom한 로그인 페이지로 간다.
true면 사용자가 지정한 url로 페이지가 라우팅된다.
// 로그인 후 RESTRIC_ROUTE 진입 가능
if (isAuthenticated && !isPublicRoute) return true;
// 로그인 전 RESTRIC_ROUTE 진입 불가
if (!isAuthenticated && isPublicRoute) return false;
// 그외 라우팅 처리 및, middleware에서 설정할 것 있으면 넘기기
return true;
따라서 ,이 곳에서는 2가지의 조건부 라우팅을 했다.
그리고 나서 return true를 해줬다. true해준 것은 authorized
의 eslint 타입때문이기도 하며, 2가지 조건부 라우팅 외에는 middleware
에서 처리 하기 위함이다.
export interface NextRequestWithAuth extends NextRequest {
nextauth: { token: JWT | null }
}
function middleware(req:NextRequestWithAuth){...}
특별한 점은 withAuth안의 미들웨어의 인자값인데 타입을 보면 알겠지만, nextauth
가 있다.
따라서, 미들웨어안에서도 따로 getSession
과 같은 메소드 호출 없이!! 조건부로 라우팅을 해줄 수가 있다.
const {token} = req.nextauth;
if (req.nextUrl.pathname === AUTH_PAGE && token) {
//return Response.redirect(req.url);// 이렇게 하면 무한 redirection된다.
return Response.redirect(new URL(HOME_PAGE, req.url));
}
프로젝트에서 사용한 것은 Next.js에서 제공한 middleware안에서 라우팅 처리를 하였지만, 이렇게 블로그 작성하면서 한단계 더 develop해서 라이브러리 사용법을 확장하여 조건부 라우팅을 공부하고 알아간 것이 무척이나 뿌듯하다.
이제 슬슬 프로젝트 블로그도 마무리가 되간다.
다음번에는 node에서 file처리, SSR처리 이 2가지를 작성하면 완성된다.
길고도 긴 시간이다.