일기/개발일기

[241002] Next.js 미들웨어

표자 2024. 10. 2. 11:03

Next.js에서 middleware란?

 

Next.js에서 middleware.ts라는 파일을 프로젝트 루트 디렉토리에 생성하면 자동으로 미들웨어로 인식됩니다. 이 파일은 요청이 완료되기 전에 실행되며, 요청에 따라 응답을 수정하거나 리디렉션, 헤더 수정 등을 할 수 있습니다

 

문제발생

현재 그냥 api/auth를 사용하면서 middleware를 적용하면 에러발생

    if (!token) {
        console.log('No token found, redirecting to login');
        // if (
        //     request.nextUrl.pathname !== '/login' &&
        //     request.nextUrl.pathname !== '/'
        // ) {
        //     return NextResponse.redirect(new URL('/login', request.url));
        // }
    } else {
        console.log('Token found:', token);
    }

 

에러발생이유

미들웨어가 전역으로 진행중인데, 로그인화면에서 아이디와 비밀번호를 제출할땐, token이 생성되기 전이라서 if문의 기능을 하지 못함

 

문제해결

config에서 로그인과 관련된 /login /api 폴더를 제외함

export const config = {
    matcher: ['/((?!api|_next/static|_next/image|favicon.ico|.*\\\\.png$|login).*)'],
};

토큰이 없을때 리다이렉션하는 로직을 좀 더 세밀하게 조정

if (!token) {
    if (
        !request.nextUrl.pathname.startsWith('/api/auth') &&
        !request.nextUrl.pathname.startsWith('/login') &&
        request.nextUrl.pathname !== '/'
    ) {
        return NextResponse.redirect(new URL('/login', request.url));
    }
    console.log('No token found, but on an allowed path');
} else {
    console.log('Token found:', token);
}

 

전체코드

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { getToken } from 'next-auth/jwt';

export async function middleware(request: NextRequest) {
    console.log('Middleware is running');
    const token = await getToken({
        req: request,
        secret: process.env.NEXTAUTH_SECRET,
    });

    if (!token) {
        if (
            !request.nextUrl.pathname.startsWith('/api/auth') &&
            !request.nextUrl.pathname.startsWith('/login') &&
            request.nextUrl.pathname !== '/'
        ) {
            return NextResponse.redirect(new URL('/login', request.url));
        }
        console.log('No token found, but on an allowed path');
    } else {
        console.log('Token found:', token);
    }

    return NextResponse.next();
}

export const config = {
    matcher: [
        '/((?!api|_next/static|_next/image|favicon.ico|.*\\.png$|login).*)',
    ],
};
728x90