Next.js의 미들웨어는 페이지를 렌더링하기 전 서버에서 실행되는 함수입니다. 미들웨어는 Request 객체와 Response 객체에 접근하여 인증이나 요청 확인하고 요청에 대한 응답을 변환하거나 에러를 처리할 수 있습니다.
이번 프로젝트에서는 로그인 여부에 따른 페이지 리다이렉션을 위해 미들웨어를 사용했습니다.
useEffect(() => {
const state = store.getState();
const token = state.user.accessToken;
if (router.pathname.startsWith('/mypage') && !token) {
router.push('/');
}
}, []);
기존 로그인 담당자분은 _app.tsx에서 토큰이 없는 유저가 로그인 후 이용 가능한 서비스 페이지(/mypage)에 접근할 경우, 메인 페이지(/)로 이동하는 코드를 작성했습니다. 하지만 이 코드는 서비스 페이지로 이동한 뒤에 리다이렉트 되거나, 리다이렉트가 일어나지 않는 이슈가 있었습니다. 따라서 미들웨어를 연동해 리다이렉션을 설정했습니다.
middleware.ts
import type { NextRequest, NextFetchEvent } from "next/server";
export function middleware(request: NextRequest, event: NextFetchEvent) {
console.log("전역 미들웨어입니다.");
if (request.nextUrl.pathname.startsWith('/about')) {
return NextResponse.rewrite(new URL('/about-2', request.url))
}
}
src 최상위 middleware.ts파일 내에서 middleware 함수를 생성합니다. 이렇게 생성된 함수는 전역으로 설정된 상태이며 유저가 페이지를 이동할 때마다 실행됩니다.
export const config = {
matcher: ['/about', '/dashboard/:path*'],
}
특정 경로에서만 미들웨어를 실행하고 싶은 경우 matcher를 사용해 미들웨어를 필터링할 수 있습니다.
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';
export function middleware(request: NextRequest) {
const refreshToken = request.cookies.get('refreshToken')?.value;
const pathname = request.nextUrl.pathname;
if (!refreshToken && pathname.startsWith('/mypage')) {
return NextResponse.redirect(
new URL('/?alert=로그인 후 이용 가능한 서비스입니다.', request.url),
);
}
}
미들웨어는 쿠키에 저장된 토큰으로 로그인 유무를 판단해 ‘로그인 후 이용 가능한 서비스입니다.’ alert창을 띄우고 페이지를 이동하도록 수정했습니다.
const router = useRouter();
useEffect(() => {
if (router.query.alert) {
alert(router.query.alert);
router.push(router.pathname);
}
}, [router]);
미들웨어는 서버에서 실행되는 함수기 때문에 redirect url 쿼리에 alert창에 띄울 메시지를 넘겨준 뒤 메인 페이지에서 useRouter를 이용해 메시지를 보여줬습니다.