Next.js Prefetch 및 RSC Payload 관련 트러블 슈팅

도균(ToKyun)·2025년 4월 1일
0

트러블 슈팅

목록 보기
2/3

Next.js 공식 문서 기반으로 작성한 글입니다. middleware와 httpOnly 쿠키를 사용하면서 겪은 이슈입니다.

서론

  • 서버액션이나 로그인 route handler를 통해 쿠키의 추가, 삭제를 구현했고, middleware를 통해 해당 쿠키가 존재하면 리다이렉트 시키는 로직을 구성했었다.
  • 랜딩페이지의 프로필 아이콘을 클릭하면 middleware를 통해 다음과 같이 이동한다.
    • 쿠키가 존재한다면 /mypage로 이동시킨다.
    • 쿠키가 존재하지 않는다면 /mypage에서 /login으로 리다이렉트 시킨다.
  • 하지만 로그인이 된 후 useRouter로 랜딩 페이지를 이동시키면 쿠키가 있음에도 불구하고 /login 페이지로 이동하게 된다.

총 시뮬레이션 과정은 다음과 같다.
랜딩페이지(/) 접속 → 프로필 아이콘 클릭 → 마이 페이지 요청 → 로그인 페이지 리다이렉트 → 로그인 폼 제출 → useRouter로 랜딩페이지 라우팅 → 프로필 아이콘 클릭 → 예상과 달리 다시 마이페이지가 아닌 로그인 페이지로 이동

본론

  • 리다이렉트가 되지 않는 이유는 바로 middleware가 실행되지 않기 때문이다.
  • 이런 현상이 일어나는 원인 서술 전 프리페칭이 무엇인지 정확하게 이해해야 한다.
    • 프리페칭은 사용자가 특정 링크(Link 컴포넌트의 경우 default가 true이다.)로 이동 가능한 경로이거나 프로그래머틱하게 이동 가능한 경로(router의 경우 default가 false이다.)를 이동하기 전에 해당 경로에 필요한 RSC Payload(서버 컴포넌트의 직렬화 된 데이터)를 미리 가져오는 것이다.
    • 이 프리페칭 된 RSC Payload는 클라이언트 캐시(Router Cache)에 저장된다.

next.js 캐시 흐름

[이미지 출처] : https://nextjs.org/docs/app/building-your-application/caching#5-subsequent-navigations

  • 그럼 왜 프리페칭이 문제가 되는가 하면, 로그인이 안되어있는 상태에서 랜딩페이지에 접속하게 되면 프리페칭이 실행되면서 middleware를 실행하게 되는데, 로그인이 되어있지 않기 때문에 RSC Payload는 redirect되어서 /login에 관련된 payload가 되어 클라이언트 캐시에 남게 된다.
    • 쉽게 말해서 href로 연결한 payload가 로그인이 안되어있으면 mypage의 payload가 아닌 login의 payload로 매핑되는 것이기 때문이다.

RSC Payload

  • 위 이미지를 보면 rsc payload가 redirect 된 것을 확인할 수 있다.
  • 또한 이 라우터 캐시(RSC Payload)가 존재하면 굳이 서버에 데이터를 요청하지 않아도 화면을 렌더링할 수 있기 때문에 서버 요청 없이 페이지 이동이 처리된다.
  • 이러한 캐시가 존재하기 때문에 다시 서버 요청이 없기 때문에 당연히 middleware는 실행되지 않는다.

해결

  • 라우터 캐시가 있기에 서버 요청을 하지 않는 것이 주요 원인이라고 볼 수 있다.
  • 때문에, 라우터 캐시를 강제로 비워주는 revalidatePath 등을(route handler는 서버액션과 달리 특정 라우트에 종속되지 않아서 캐시가 남아있을 수 있다.) 활용하여 로그인 버튼이나 로그아웃 버튼을 눌렀을 때 캐시를 한 번 비워주면 해결이 가능하지만, 굳이 서버액션을 추가시켜줘야 하는 단점도 있다.
  • 가장 손 쉬운 해결 책은 라우터 캐시는 기본적으로 브라우저 탭이 꺼지거나 reload되면 사라지기 때문에, useRouter로 이동하던 로직을 window.location.href로 이동시키거나, window.reload로 브라우저가 새로고침 되도록 유도하면 된다.
profile
기하급수적 성장

0개의 댓글