리소스 로딩 최적화: prefetch 와 preload

오다혜·2024년 3월 3일
0

들어가기 전에 앞서 prefetch 와 preload 의 차이에 대해 알아보자.

💡 prefetch vs preload
  • prefetch: resource is probably needed for some navigation in the future
  • preload: resource will also be needed during the current navigation

차이점

  • A preloaded chunk starts loading in parallel to the parent chunk. A prefetched chunk starts after the parent chunk finishes loading.
  • A preloaded chunk has medium priority and is instantly downloaded. A prefetched chunk is downloaded while the browser is idle.
  • A preloaded chunk should be instantly requested by the parent chunk. A prefetched chunk can be used anytime in the future.
  • Browser support is different.

표로 보는 prefetch 와 preload 의 차이점

번들 필요한 시점부모 청크와의 관계다운로드 시점
prefetch미래의 언젠가부모 청크가 다 로딩된 이후에 로딩 시작브라우저가 idle 상태일 때
preload현재 위치부모 청크와 병렬로 불러와짐요청 즉시

preload

Preload (<link rel="preload">) is a browser optimization that allows critical resources (that may be discovered late) to be requested earlier.

브라우저 최적화 과정 중 하나로, 중요한 리소스를 빠르게 요청하는 방법이다.

  • TTI(Time To Interactive) 나 FID(First Input Delay) 를 개선하기 위해서 필요한 번들의 우선순위를 높일 수 있다.
  • 이로 인해 FCP 또는 LCP 가 낮아지지 않도록 조심해야 한다.
    불필요한 파일의 우선순위를 높여서 필수적인 폰트나 이미지가 불러와지는 시간이 늦어지면 FCP, LCP 가 나빠질 수 있다.
  • 브라우저의 환경(지금 충분한 대역폭을 가지고 있는지 등)에 관계없이 무조건 fetch 한다.

구현 방법

  1. <link rel="preload">

  2. <script defer>

    javascript 불러올 때 사용

필요한 상황

  • app 에서 사용하고 있는 폰트
  • 유저가 바로 봐야하는 이미지 등의 리소스
  • 그 외에 필수적으로 빨리 불러와야 하는 리소스

webpack

const EmojiPicker = import(/* webpackPreload: true */ "./EmojiPicker");

주의할 점

preload 하는 파일 때문에 초기 로딩 속도(FCP)가 증가하게 된다. 따라서 initial loading 이후 1초 이내에 보여야 하는 번들에 대해서만 preload 를 사용해야 한다.

chrome

  • Putting it in HTTP headers will jump ahead of everything else HTTP header 에 추가하면 다른 어떤 것보다도 우선순위가 높아진다.
  • Generally, preloads will load in the order the parser gets to them for anything >= Medium so be careful putting preloads at the beginning of the HTML. 우선순위가 Medium 보다 높아지므로 주의해서 사용해야 한다.
  • Font preloads are probably best towards the end of the head or beginning of the body 폰트 preload는 head 최하단이나 body 최상단에 작성하는 것이 좋다.
  • Import preloads should be done after the script tag that needs the import (so the actual script gets loaded/parsed first) 특정 번들을 사용하는 부모 번들보다 먼저 preload 하면 안 된다.
  • Image preloads will have a low priority and should be ordered relative to async scripts and other low/lowest priority tags 이미지 preload 는 우선순위가 낮다.

prefetch

Prefetch (<link rel="prefetch">) is a browser optimization which allows us to fetch resources that may be needed for subsequent routes or pages before they are needed.

브라우저 최적화 과정 중 하나로, 다른 경로나 페이지에 필요한 리소스를 필요한 시점 이전에 fetch 하는 것

구현 방법

  1. HTML

    <link rel="prefetch" href="/pages/next-page.html" />
    <link rel="prefetch" href="/js/emoji-picker.js" />
  2. HTTP Header

    Link: </js/chat-widget.js>; rel=prefetch
  3. Service Worker

  4. Webpack 과 같은 도구들

장점

필요한 시점에 fetch 하는 것이 아니라 미리 cache 에 저장해놓고 불러오기 때문에 chunk 를 훨씬 빠르게 보여줄 수 있다.

단점

꼭 필요하지 않은 모듈에 prefetch 를 적용하는 경우 불필요하게 리소스를 로드하게 되어 불필요한 메모리를 사용하고 앱을 느리게 할 수 있다.


vite에서는?

preload

vite 에서는 내부적으로 direct import 하는 청크(번들)에 대해 알아서 preload 를 하도록 기능을 제공해주고 있다.
다만, dynamic import 하는 파일을 preload 하는 방법은 공식문서에 나와있지 않다.
안 써봤지만, preload 를 제공해주는 rollup 플러그인이 있긴 하다.

prefetch

preload 와 마찬가지로 공식적으로는 지원하지 않는 거 같다. (공식 문서에서 해당 기능을 찾을 수 없다..)

아래와 같은 플러그인이 존재하기는 한다..

https://github.com/vikerman/rollup-plugin-hoist-import-deps
https://github.com/songzhj/vite-plugin-prefetch-module?tab=readme-ov-file

webpack 에서는 magic-comment 라는 이름으로 손쉽게 preload, prefetch 기능을 사용할 수 있는 반면에 vite 는 번들에 대한 섬세한 설정을 하려면 추가 설정을 많이 해주어야 해서 좀 아쉽다고 느꼈다.

출처

https://www.patterns.dev/vanilla/preload
https://www.patterns.dev/vanilla/prefetch

profile
프론트엔드에 백엔드 한 스푼 🥄

0개의 댓글