2025-03-30
Next.js에서 클라이언트 사이드 라우팅을 사용할 때 prefetch, middleware, 그리고 router cache가 서로 충돌하면서 예상하지 못한 동작이 발생하는 경우가 있습니다. 이 글에서는 로그아웃 후 잘못된 페이지로 전환되는 사례를 중심으로 이 현상을 분석하고, 클라이언트 사이드 라우트 캐시를 어떻게 제어할 수 있는지에 대해 정리했습니다.
프로젝트에서 사용 중인 미들웨어 코드
// middleware.ts
import { NextRequest, NextResponse } from 'next/server';
import { cookies } from 'next/headers';
const AFTER_LOGIN_DOMAIN = ['/mydashboard', '/dashboard', '/mypage'] as const;
const BEFORE_LOGIN_DOMAIN = ['/faq', '/privacy', '/login', '/signup', '/'] as const;
export const middleware = async (request: NextRequest) => {
const cookieStore = await cookies();
const accessToken = cookieStore.get('accessToken');
const pathname = request.nextUrl.pathname;
if (!accessToken?.value) {
if (AFTER_LOGIN_DOMAIN.some((path) => pathname.startsWith(path))) {
return NextResponse.redirect(new URL('/login', request.url));
}
} else {
if (BEFORE_LOGIN_DOMAIN.includes(pathname)) {
return NextResponse.redirect(new URL('/mydashboard', request.url));
}
}
return NextResponse.next();
};
지금의 문제는 Client-side Router Cache가 남아있어서 생기는 문제로, 이 Cache를 무효화하는 방법은 없을까 해서 공식문서를 한번 찾아보면서 알게된 내용들을 정리해보았습니다.
서버 액션에서의 무효화
클라이언트에서의 무효화
Revalidating the Data Cache in a Route Handler will not immediately invalidate the Router Cache
On subsequent navigations or during prefetching, Next.js will check if the React Server Components Payload is stored in the Router Cache.If so, it will skip sending a new request to the server.
https://nextjs.org/docs/app/building-your-application/caching#5-subsequent-navigations
You can also bypass Middleware for certain requests by using the missing or has arrays, or a combination of both:
https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher
이렇게 공식문서를 하나씩 찾아보면서 prefetching, middleware, route cache의 기본적인 성질들을 이해하니, 셋 모두 자신들의 역할은 충실했고, 상호작용으로 인한 부작용을 이해하고, 적절히 제어해 주는 것이 저희가 해야 할 과제인 것을 알게 되었습니다.
client에서 router.refresh()를 호출하는 방법은 현재 라우트의 경로대한 캐시만 무효화하기 때문에, 지금 이 문제의 해결책이 될 수는 없었습니다.
라우트캐시를 무효화해야 하는 시점은 사용자가 로그인 또는 로그아웃을 하는, 정확히는 쿠키가 변동되는 시점입니다.
로그인, 로그아웃을 server action으로 전환 후에 해당 코드 내에서 revalidatePath 등을 사용하여 무효화하는 방법이 있었습니다.
하지만 로그인, 로그아웃을 server action 코드로 바꾸게 되면서, 부가적인 서버액션의 상태를 체크하기 위한 코드들이 생겨나야 해서 비합리적이라고 생각되었습니다.
그래서 저희 팀은 로그인, 로그아웃이 성공하면, 강제로 브라우저를 새 로고침하여 client router cahce를 초기화하는 방법으로 이 문제를 해결하였습니다.