Next.js
Next.js Link prefetch 때문에 요청이 너무 많아 보였던 착각
Next.js 화면에서 네트워크 요청이 갑자기 늘어난 것처럼 보였을 때 Link prefetch와 실제 사용자 요청을 나눠 본 경험입니다.
처음 본 현상
글 목록 페이지를 열었는데 브라우저 네트워크 탭에 상세 페이지 관련 요청이 여러 개 보였다. 아직 아무 글도 누르지 않았는데 요청이 나가니 API가 중복 호출되는 줄 알았다. 목록 컴포넌트의 map 안에서 실수로 fetch를 실행했나 싶어서 한참을 찾았다.
나중에 보니 일부 요청은 Next.js의 Link prefetch 때문에 생긴 것이었다. 화면에 링크가 보이면 다음 이동을 빠르게 하려고 필요한 리소스를 미리 가져올 수 있다.
제가 잘못 판단한 부분
네트워크 탭에 보인 요청을 모두 사용자가 클릭해서 발생한 요청처럼 해석했다. 그래서 실제 문제인지 확인하기 전에 코드를 먼저 바꾸려 했다.
확인 순서를 바꾸니 금방 구분됐다.
<Link href={`/posts/${post.slug}`}>{post.title}</Link>
이 상태에서 뷰포트 안에 링크가 많이 보이면 프리페치가 동작할 수 있다. 개발 환경과 프로덕션 환경에서 보이는 양상도 다를 수 있어서, 로컬 dev 서버의 느낌만으로 결론 내리면 안 됐다.
임시로 prefetch를 꺼서 비교했다
원인을 좁히려고 목록의 일부 링크에만 prefetch={false}를 붙여 봤다.
<Link href={`/posts/${post.slug}`} prefetch={false}>
{post.title}
</Link>
그리고 같은 화면에서 네트워크 탭을 비우고 새로고침했다. 요청 수가 줄어들면 프리페치 영향이 맞다. 이 작업은 성능 최적화를 없애자는 뜻이 아니라, 요청의 성격을 분리해서 보기 위한 실험이었다.
API 중복 호출과 구분한 기준
제가 정한 기준은 이렇다.
- 클릭 전에도 생기지만 페이지 데이터가 미리 로드되는 요청이면 프리페치 가능성을 본다.
- 같은 API가 짧은 시간에 같은 파라미터로 반복되면 컴포넌트 렌더링 구조를 본다.
- 서버 로그에서 실제 처리 비용이 큰 요청인지 확인한다.
- 프로덕션 빌드에서도 재현되는지 본다.
서버 로그는 아래처럼 시간과 경로를 같이 봤다.
sudo journalctl -u app.service --since "10 minutes ago"
브라우저에서 많아 보이는 것과 서버가 실제로 부담을 느끼는 것은 다를 수 있었다.
결론 대신 남긴 규칙
Next.js가 대신 해 주는 최적화가 있을 때는 네트워크 탭을 그대로 버그 목록으로 옮기지 않기로 했다. 먼저 요청이 사용자 행동, 프리페치, 개발 모드 동작 중 어디에 가까운지 나눈다. 그래야 필요 없는 수정으로 성능 기능을 꺼 버리지 않는다.