NextJs - 프리페칭

김명원·2025년 2월 17일

learnNextjs

목록 보기
5/24

프리페칭

프리페칭은 전 포스트에서 다뤘던 네비게이팅과 연관이 있는 기능입니다.

우선 프리페칭(Pre-Fetching)이란? 사전의 미리 불러오는 뜻을 가지며, 페이지를 사전에 불러온다는 뜻입니다.

링크들을 통해서 이동할 수 있는 모든 페이지들을 사전에 미리 다 불러와 놓는 기능을 의미합니다.
즉, 사용자가 이동할 수 있는 페이지들을 사전에 미리 다 불러놓는 기능인 것입니다.

Next.js가 기본적인 프리페칭을 제공하는 이유는 사용자들이 다른 페이지로 이동하기 위해서 웹페이지 내부의 링크를 클릭하기 전에 현재 페이지에서 이동이 가능한 모든 페이지들에 필요한 데이터를 미리 다 불러와 놓음으로써 페이지 이동을 매우 빠른 속도로 지체 없이 처리해주기 위함입니다.

Next.js의 의문점

Next.js는 이미 초기에 접속 요청이 완료가 되면 페이지가 렌더링이 되는데, 왜 그런 상태에서 다른 페이지로 이동하기 위해 추가적은 데이터를 왜 또 불러와야 할까요??
Next.js는 작성한 모든 자바스크립트, 리액트 컴포넌트들을 자동으로 페이지별로 스플리팅해서 저장을 미리 해두기 때문입니다.

스플리팅이란? 페이지별로 분리하는 뜻입니다.


따라서 JS Bundle을 전달할 때 모든 페이지에 필요한 자바스크립트 코드가 전달되는 것이 아닌, 현재 페이지에 해당하는 자바스크립트 코드들만 전달이 됩니다.

왜 이렇게 하는 것일까요?
JS Bundle 과정에서 전달되는 자바스크립트 코드의 양을 줄이기 위함입니다.
만약, 항상 초기 접속 요청이 있을 때마다 모든 페이지에 해당하는 자바스크립트 코드들을 매번 번들링해서 전달하게 되면 한 방에 전달되는 파일의 용량이 매우 커져 속도도 느려지며, Html과 연결하는 수화(Hydration)과정도 오래 걸리며, 앱에 상호작용할 수 있게 되는 시간인 TTI가 늦어지게 되는 문제가 발생하기 때문입니다.

하지만 다시 페이지를 이동하려고 하면 이동하려는 페이지에 필요한 자바스크립트 코드를 추가로 또 불러와야 되는 과정이 필요하게 됩니다.

이러한 방식이면 페이지 이동이 느려지고 비효율적이기 발생하는 것을 막고자 프리페칭 이라는 기능이 추가로 작용하는 것입니다.

결국 프리페칭이 발생하면 추가적인 데이터를 서버에게 요청할 필요가 없어져서 기존 처럼 클라이언트 사이드 렌더링 방식의 장점대로 굉장히 바른 속도로 페이지를 이동시킬 수 있게 됩니다.


프리페칭의 동작

Next.js에서 프리페칭은 기본적인 npm run dev에서 작동하지 않습니다.
그렇기에 Next.js에서 프리페칭의 기술을 사용하려녀 npm 모드가 아닌 build에서 사용하는 production 모드로 싱행을 시켜줘야 합니다.
npm run build로 프로젝트를 빌드해 주면 됩니다.

그러면 build 결과가 나오게 됩니다.

각각 페이지별 자바스크립트 번들의 용량까지 함께 출력이 됩니다.

그 다음 build를 확인하기 위해서 npm run start로 Next.js 앱을 production 모드로 실행시켜 주면 됩니다.

그다음 Loacl 주소로 접속해주고 개발자 도구에서 Network를 살펴보면 굉장히 많은 네트워크 요청이 이루어진 것을 확인할 수 있습니다.
그 중 search-...를 들어가 보면

search 페이지에 필요한 자바스크립트 코드를 미리 프리패칭해서 불러와 놓는것을 볼 수 있습니다.

그렇기에 search 페이지로 이동한다고 해도 개발자 Network 탭에서는 아무런 요청도 추가적으로 발생하지 않는 것 또한 확인할 수 있습니다.

캐시가 만료가 되면 다시 불러옵니다.

하지만 /test 페이지로 이동버튼을 클릭하고 Network 탭을 확인하면

자바스크립트 번들을 추가로 불러오는 것을 확인할 수 있습니다.
이것은 프리페칭이 이루어지지 않았다는 것입니다.
그 이유는 Link를 사용한 것이 아닌 프로그래매틱하게 이루어진 것입니다.

즉, 링크 컴퍼넌트로 명시된 경로가 아니라면 프리패칭이 이루어지지 않습다
그런데 똑같이 test 페이지에도 프리페칭을 시켜주고 싶다면
pages/_app.tsx

import "@/styles/globals.css";
import type { AppProps } from "next/app";
import Link from "next/link";
import { useRouter } from "next/router";

export default function App({ Component, pageProps }: AppProps) {
  const router = useRouter();

  const onClickButton = () => {
    router.push("/test");
  };
  return (
    <>
      <header>
        <Link href={"/"}>index</Link>
        &nbsp;
        <Link href={"/search"}>search</Link>
        &nbsp;
        <Link href={"/book/1"}>book/1</Link>
        <div>
          <button onClick={onClickButton}>/test 페이지로 이동</button>
        </div>
      </header>
      <Component {...pageProps} />
    </>
  );
}

router 객체의 특정 메서드를 통해서 프로그래메틱하게 테스트 페이지를 프리페칭 하도록 작성해주면 됩니다.

마운트 되었을 때 실행할 동작 정의

  useEffect(()=>{
    router.prefetch('/test')
  }, [])

마운트 되었을 때 실행할 동작을 정의해줘야 하기 때문에 useEffect를 사용해줍니다.
마운트 되었을 때 한 번만 실행시킬 거니깐 의존성 배열 depth를 빈 배열로 전달해 줍니다.
그 다음 callback 함수 안에서 router의 객체의 prefetch 메서드를 호출하고 인수로 어떤 페이지를 프리페칭 할 것인지 넣어주면 됩니다.

다시 build 후 start를 하면 새로고침을 눌러보면 test 필요한 페이지도 미리 프리페칭 되는것을 확인할 수 있습니다.

자동으로 진행되는 링크 컴퍼넌트의 프리패칭 강제 해제

만약에 잘 접속하지 않는 페이지가 있어서 프리페칭을 굳이 필요없는 상황이 있을 수도 있습니다.

그러면 페이지로 이동하는 lINK 컴포넌트에 Prefetch={False}로 전달해주면 됩니다.
그러면 Link에 해당하는 페이지는 프리패칭이 안됩니다.

<Link href={"/search"} prefetch={false}>search</Link>
profile
개발자가 되고 싶은 정치학도생의 기술 블로그

0개의 댓글