Next.js
에서 prefetch
를 사용하면 미리 데이터가 로드되어 페이지 로드 시간이 단축된다는데 꼭 Next.js
의 Link
컴포넌트가 아니면 달성이 불가능한 것인가? SSR
인 경우는 어떻게 되는가? 미리 불러오면 안 될 텐데? 와 같은 호기심이 발생했습니다. 어떻게 동작하는지 확인해 봅시다!
개요
Next.js
에서는 큰 문제가 없는 이상 <a>
보다는 <Link>
Component를 사용하는 것이 더 나아 보입니다.
그런데 prefetch
에 대해서 아래의 의문이 생겼습니다.
Next.js
의Link
컴포넌트가 아니면 달성이 불가능한 것인가?SSR
인 경우는 어떻게 되는가? 미리 불러오면 안 될 텐데
궁금증을 해결하기 위해서 프로젝트를 만들어서 실험해 보았습니다.
실험한 프로젝트 코드는 parkgang/next.js-prefetch 에서 확인할 수 있습니다.
코드를 보고 실제로 어떻게 동작하는지, 여러 컨셉을 시도해볼 수 있습니다!
Insight
Prod
에서만 활성화 된다.
어쩐지 열심히 테스트해도 안되길래 뭐지 했는데 Prod
에서만 활성화된다고 합니다.
Link
컴포넌트 이외 router.prefetch
으로도 미리 로드할 수 있다
공식 문서 router.prefetch 에 작성되어 있습니다.
코드의 컨셉을 보면
로그인
하는 페이지에 들어왔을 때 미리Dashboard
경로의 정보를prefetch
하고로그인
이 완료되면 빠르게Dashboard
으로 넘어갈 수 있도록 하는 것입니다.
import { useCallback, useEffect } from "react";
import { useRouter } from "next/router";
export default function Login() {
const router = useRouter();
const handleSubmit = useCallback((e) => {
e.preventDefault();
fetch("/api/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
/* Form data */
}),
}).then((res) => {
// Do a fast client-side transition to the already prefetched dashboard page
if (res.ok) router.push("/dashboard");
});
}, []);
useEffect(() => {
// Prefetch the dashboard page
router.prefetch("/dashboard");
}, [router]);
return (
<form onSubmit={handleSubmit}>
{/* Form fields */}
<button type="submit">Login</button>
</form>
);
}
prefetch
라고 해서 SSR
이 미리 되는 것은 아니다. prefetch
는 정적 자료
만 미리 불러오는 것이다.
prefetch
는 정적 자료
만 미리 가져오며 prefetch
라고 해서 getServerSideProps
함수를 미리 수행하지 않는다고 합니다.
실험 결과 prefetch
시 PageComponent
에서 미리 사용할 수 있는 형태로 JS
을 가공해 놓는 것을 볼 수 있었습니다.
import SlowImages from "@/components/SlowImages";
import type { GetServerSideProps } from "next";
type PageProps = {
ssrFinalizedDisplayDate: string;
};
export const getServerSideProps: GetServerSideProps<PageProps> = async () => {
// prefetch과 관련 없이 SSR이 잘 이뤄지는지 보기위해서 의도적으로 기다립니다.
await new Promise((resolve) => {
setTimeout(() => {
resolve(null);
}, 3000);
});
return {
props: {
ssrFinalizedDisplayDate: new Date().toLocaleString("ko-KR"),
},
};
};
export default function SsrPage({
ssrFinalizedDisplayDate: nowDateIso,
}: PageProps) {
return (
<div>
<h1>SSR Page!</h1>
<p>
SSR이 완료된 시점은 <strong>{nowDateIso}</strong> 입니다.
</p>
<SlowImages />
</div>
);
}
Image
까지는 미리 불러오지 않는다.
실험 시 image
도 미리 불러오는지 궁금해서 확인해 보았는데 그렇지 않았습니다.
Next.js
측에서 Image
의 경우 Image
컴포넌트로 최적화하는 방법으로 사용하라는 것이면서도 사실 Image
는 미리 불러와서 이득이 없다고 판단한 거 같습니다.
페이지에 이미지가 몇 개일 지 모르는데 그걸 어떤 기준으로 모두 확보하느냐, 그래서 화면에 표시되는 이미지만 미리 처리한다 이런 컨셉 같습니다.
실험한 프로젝트에서 보면 Next.js
의 Image
컴포넌트를 사용하면 Image
를 불러오는 이미지 URL이 http://localhost:3000/_next/image?url=
형식으로 바뀌면서 알아서 캐시 되더군요.
prefetch
시 미리 불러오는 데이터 형식은?
아래와 같습니다.
SSG
는 아래와 같은 느낌으로 불러오더군요.
import SlowImages from "@/components/SlowImages";
export default function SsgPage() {
return (
<div>
<h1>SSG Page!</h1>
<p>ssg 페이지 입니다.</p>
<SlowImages />
</div>
);
}
결론
prefetch
으로 미리 불러오는 데이터는CSS
,JS
이다.image
의 경우 미리 불러오지 않는다.CSS
도 미리 불러오는지까지는 확인하지 못함
prefetch
되었다고 해서SSR
안 되는 것이 아니다.getServerSideProps
은prefetch
단계에서 수행되지 않는다.
마무리
이렇게 Next.js
의 prefetch
에서 헷갈릴 만한 것들을 알아보았습니다.
단순하게 미리 불러온다는 라는 개념보다 어떤 경우, 어떻게 불러오는지 알 수 있어 더 섬세하게 사용할 수 있을 거 같습니다.
읽어주셔서 감사합니다.