본문으로 건너뛰기
개발 머꼬
개발 노트HTML
hohyeon.dev21

preload를 늘렸는데 첫 화면이 오히려 느려진 이유

  • #Engineering Note
  • #HTML
  • #Performance

문제 발생

성능을 올리려고 <head>에 힌트를 잔뜩 넣었습니다.

<link rel="preload" href="/hero.avif" as="image" />
<link rel="preload" href="/about.js" as="script" />
<link rel="preload" href="/fonts/pretendard.woff2" as="font" />
<link rel="preconnect" href="https://a.example" />
<link rel="preconnect" href="https://b.example" />
<!-- ... 이런 줄이 열 개 넘게 -->

LCP가 오히려 나빠졌고, 콘솔에는 preload한 자원이 사용되지 않았다는 경고가 떴습니다. 폰트는 두 번 받아왔습니다.

원인 분석

preload는 "빨리 만들기"가 아니라 "먼저 줄 세우기"입니다. MDN은 preload현재 페이지에서 높은 우선순위인 자원을 브라우저가 <head><link>를 보는 즉시 내려받게 하는 힌트로 설명하고, 곧바로 경고합니다 — 모든 것을 preload하지 마십시오. 그러면 이득을 볼 수 없습니다.

이유는 대역폭이 유한하기 때문입니다. 열 개를 동시에 당기면 그중 진짜 중요한 하나가 나머지와 경쟁합니다. 게다가 문서는 결과가 문서별 메모리 캐시에 보관되며, 현재 페이지가 하위 자원으로 쓰지 않는 것을 preload하면 일반적으로 자원 낭비라고 못박습니다. 다음 페이지에서 쓸 /about.js가 정확히 그 경우였습니다.

폰트가 두 번 받아진 것은 CORS 때문입니다. 문서는 CORS로 가져오는 자원(fetch, XHR, 폰트)을 preload할 때 <link>crossorigin 속성을 설정하는 데 각별히 주의해야 한다고 안내합니다. 속성이 없으면 preload한 응답과 실제 폰트 요청이 서로 다른 것으로 취급됩니다.

preconnect도 많을수록 좋은 게 아닙니다 — 문서는 여러 서드파티 도메인에 연결이 필요한 페이지에서 전부 preconnect하면 역효과일 수 있으며, 가장 중요한 연결에만 쓰는 것이 가장 좋다고 적습니다.

해결 방안

  1. preload는 "이 페이지가 확실히 쓰는데 늦게 발견되는 것"으로 좁힙니다. 대표적으로 CSS 안에서 참조되는 히어로 이미지와 본문 폰트입니다. as는 필수이며 우선순위와 Accept 헤더가 여기서 결정됩니다.

  2. 폰트에는 crossorigin을 함께 줍니다.

<link rel="preload" href="/fonts/pretendard.woff2" as="font" type="font/woff2" crossorigin />
  1. 다음 페이지용은 prefetch입니다. 문서 설명대로 prefetch는 미래의 내비게이션에 필요할 자원을 대상으로 합니다. 다만 캐시 파티셔닝 때문에 교차 사이트 자원에는 효과가 없을 수 있다는 경고도 함께 있습니다.

  2. 연결만 미리 여는 것과 자원을 받는 것을 구분합니다. preconnect는 DNS·TCP·TLS 핸드셰이크를 미리 하고, dns-prefetch는 DNS만 합니다. 문서는 dns-prefetch를 모든 교차 출처 연결에 써도 되는 작은 개선으로, preconnect를 가장 중요한 연결에만으로 구분합니다.

  3. 바꾼 뒤에는 반드시 측정합니다. 이 힌트들은 전부 "브라우저의 판단을 사람이 덮어쓰는" 도구입니다. 지표가 나아지지 않으면 지우는 게 맞습니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.