0️⃣ Next.js의 Middleware
Next.js의 middleware는 라우트가 렌더링 되기 전에 서버에서 코드를 실행할 때 사용됩니다.
들어오는 요청에 따라 응답을 재작성하거나 redirect, 헤더 수정 등의 작업을 할 수 있습니다.
이 middleware를 사용해서 사용자가 로그인된 상태인지 판단하고, 로그인되지 않은 상태라면 로그인 페이지로 이동하는 기능을 구현해보도록 하겠습니다.
1️⃣ Middleware 구현하기
src 디렉토리 하위에 middleware.ts 파일을 생성하는 것으로 미들웨어를 정의할 수 있습니다.
const middleware = (request: NextRequest) => {};
export default middleware;미들웨어를 정의할 때 NextRequest 타입의 매개변수를 받아 사용할 수 있습니다.
이 매개변수를 통해 HTTP 요청을 나타내는 객체입니다.
쿠키에 저장된 토큰을 사용해서 로그인 여부를 확인하는 방법을 사용하도록 하겠습니다.
const middleware = (request: NextRequest) => {
const token = request.cookies.get('accessToken')?.value;
const requestedPage = request.nextUrl.pathname;
if (!token) {
if (requestedPage === '/login' || requestedPage === '/signup') {
return NextResponse.next();
}
const url = request.nextUrl.clone();
url.pathname = '/login';
url.searchParams.set('redirect', requestedPage);
return NextResponse.redirect(url);
}
};token: accessToken 이름의 쿠키 값requestedPage: 요청된 페이지의 경로를 나타내는 문자열
토큰이 없을 때(로그인 상태가 아닐 때)
if (requestedPage === '/login' || requestedPage === '/signup') 구문으로
로그인, 회원가입 페이지 이동 요청은 허용합니다.
그 외의 요청은 복사한 request.nextUrl을 사용하여 로그인 페이지로 이동하도록 경로를 변경합니다.
url.searchParams.set()을 사용하여 redirect 쿼리스트링으로 이전에 요청한 페이지 경로를 설정합니다.
그 후 NextResponse.redirect(url)을 리턴하여 로그인 페이지로 redirect 합니다.
로그인 페이지에서 로그인이 성공할 경우 redirect 쿼리스트링 값을 사용해 next의 redirect() 함수로 이전에 요청한 페이지 경로로 이동하게 됩니다.
// mypage로의 요청이 있을 때
const requestedPage = request.nextUrl.pathname // '/mypage';
const url = { href: 'http://localhost:3000/mypage', origin: ... }; // request 객체
url.pathname = '/login'
// { href: 'http://localhost:3000/login', ...}
url.searchParams.set('redirect', requestedPage);
// { href: 'http://localhost:3000/login?redirect=/mypage', ...}
// login.ts
const redirectUrl = formData.get("redirect") || "/";
redirect(redirectUrl);이제 토큰이 있을 경우를 처리해주는 코드를 작성하겠습니다.
if (requestedPage === '/login' || requestedPage === '/signup') {
return NextResponse.redirect(new URL('/myprofile', request.url));
}토큰이 있을 때(로그인 상태일 때) 로그인, 회원가입 페이지 이동 요청이 있다면 /myprofile 페이지로 이동시킵니다.
2️⃣ config 설정하기
middleware.ts 파일에서 config 객체를 생성해서 내보낼 수 있습니다.
해당 객체는 미들웨어가 적용될 경로를 지정할 수 있습니다.
export const config = {
matcher: [
'/myprofile',
'/wine/:path*',
'/register/:path*',
'/review/:path*',
'/login',
'/signup',
],
};단일 경로의 경우에는 문자열 하나만 작성하면 되지만 여러 경로를 포함하고 싶을 땐 matcher 속성에 배열로 경로를 선언해줍니다.
/:path*는 모든 해당 경로로부터 다른 모든 경로를 포함합니다.
전체 코드
import { NextRequest, NextResponse } from 'next/server';
const middleware = (request: NextRequest) => {
const token = request.cookies.get('accessToken')?.value;
const requestedPage = request.nextUrl.pathname;
if (!token) {
if (requestedPage === '/login' || requestedPage === '/signup') {
return NextResponse.next();
}
const url = request.nextUrl.clone();
url.pathname = '/login';
url.searchParams.set('redirect', requestedPage);
return NextResponse.redirect(url);
}
if (requestedPage === '/login' || requestedPage === '/signup') {
return NextResponse.redirect(new URL('/myprofile', request.url));
}
return NextResponse.next();
};
export const config = {
matcher: [
'/myprofile',
'/wine/:path*',
'/register/:path*',
'/review/:path*',
'/login',
'/signup',
],
};
export default middleware;