preload를 늘렸는데 첫 화면이 오히려 느려진 이유
문제 발생
성능을 올리려고 <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하면 역효과일 수 있으며, 가장 중요한 연결에만 쓰는 것이 가장 좋다고 적습니다.
해결 방안
-
preload는 "이 페이지가 확실히 쓰는데 늦게 발견되는 것"으로 좁힙니다. 대표적으로 CSS 안에서 참조되는 히어로 이미지와 본문 폰트입니다.
as는 필수이며 우선순위와 Accept 헤더가 여기서 결정됩니다. -
폰트에는
crossorigin을 함께 줍니다.
<link rel="preload" href="/fonts/pretendard.woff2" as="font" type="font/woff2" crossorigin />-
다음 페이지용은
prefetch입니다. 문서 설명대로 prefetch는 미래의 내비게이션에 필요할 자원을 대상으로 합니다. 다만 캐시 파티셔닝 때문에 교차 사이트 자원에는 효과가 없을 수 있다는 경고도 함께 있습니다. -
연결만 미리 여는 것과 자원을 받는 것을 구분합니다.
preconnect는 DNS·TCP·TLS 핸드셰이크를 미리 하고,dns-prefetch는 DNS만 합니다. 문서는 dns-prefetch를 모든 교차 출처 연결에 써도 되는 작은 개선으로, preconnect를 가장 중요한 연결에만으로 구분합니다. -
바꾼 뒤에는 반드시 측정합니다. 이 힌트들은 전부 "브라우저의 판단을 사람이 덮어쓰는" 도구입니다. 지표가 나아지지 않으면 지우는 게 맞습니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.