Chapter 3

홈페이지 최적화

  • 3.1 이미지 지연 로딩
  • 3.2 이미지 사이즈 최적화 — WebP
  • 3.3 동영상 최적화
  • 3.4 폰트 최적화
  • 3.5 캐시 최적화
  • 3.6 불필요한 CSS 제거

웹 성능 최적화에 만능 해결책은 없어. 리소스 종류마다 최적화 방법이 다르거든.

이미지부터 보자. 홈페이지에 이미지가 잔뜩 있는데 스크롤하지도 않은 아래쪽 이미지까지 전부 한꺼번에 로드하는 건 낭비야. Intersection Observer API를 쓰면 요소가 뷰포트에 들어왔는지 감지할 수 있어. <img> 태그의 src에는 작은 placeholder를 넣어두고, 실제 이미지 URL은 data-src에 저장해뒀다가, 스크롤해서 뷰포트에 들어오면 그때 src를 교체하는 방식이지. 이전에는 scroll 이벤트에 리스너를 달아서 getBoundingClientRect()로 위치를 계산했는데, 매 스크롤마다 리플로우를 일으켜서 성능이 안 좋았거든. Intersection Observer는 브라우저가 비동기적으로 감지해주니까 메인 스레드에 부담이 없어.

이미지 포맷 자체를 바꾸는 것도 효과가 커. WebP는 Google이 만든 포맷으로 JPG 대비 25~35% 더 작은 용량에 품질은 비슷해. 구형 브라우저 대응은 <picture> 태그로 하면 돼. 브라우저가 WebP를 지원하면 WebP를 쓰고, 안 되면 JPG로 폴백하는 식이야.

<picture>
  <source srcset="image.webp" type="image/webp" />
  <img src="image.jpg" alt="fallback" />
</picture>

동영상은 이미지보다 훨씬 크니까 최적화 효과도 크지. 배경 동영상인데 4K일 필요 없잖아. 720p면 충분한 경우가 많고, MP4 대비 용량이 줄어드는 WebM으로 변환하는 것도 방법이야. 자동 재생 시 autoplay muted 안 하면 브라우저가 자동재생 자체를 차단하니까 주의해야 해.

웹 폰트 로드할 때는 두 가지 문제가 생겨. **FOUT(Flash of Unstyled Text)**는 시스템 폰트로 먼저 보이다가 웹 폰트 로드되면 갑자기 바뀌는 거고, **FOIT(Flash of Invisible Text)**는 웹 폰트 로드될 때까지 텍스트가 아예 안 보이는 거야. font-display CSS 속성으로 이 동작을 제어할 수 있어. swap은 시스템 폰트로 바로 보여주고 나중에 교체하는 거고, optional은 100ms 안에 로드 안 되면 시스템 폰트로 확정하는 방식이지. 폰트 파일 자체를 줄이려면 서브셋 폰트(자주 쓰는 글자만 포함)와 WOFF2 포맷(TTF 대비 30~50% 더 작음)을 쓰면 돼.

HTTP 캐시도 중요해. **강력 캐시(Cache-Control)**는 지정한 시간 동안 서버에 요청 자체를 안 보내서 가장 빠르고, **조건부 캐시(ETag)**는 서버에 "이 파일 바뀌었어?"라고 물어보는 방식이야. 실전에서는 리소스 유형에 따라 조합해서 써. HTML은 no-cache로 매번 확인하고, JS/CSS는 파일명에 해시를 붙여서(main.abc123.js) max-age=31536000으로 1년 캐싱하는 거지. 파일명이 바뀌니까 캐시 무효화가 자동으로 돼. webpack이 빌드할 때 파일명에 해시를 붙이는 이유가 바로 이 캐시 관리를 위한 거야.

마지막으로 불필요한 CSS. CSS 프레임워크를 쓰면 전체 CSS를 다 가져오는데 실제로 사용하는 클래스는 일부분이거든. Chrome DevTools의 Coverage 탭으로 사용 비율을 확인하고, PurgeCSS 같은 도구로 실제 쓰는 클래스만 남기면 돼. Tailwind CSS가 내부적으로 이걸 쓰고 있어.


정리

3장 읽고 기억할 거 세 가지:

  1. 리소스 종류별로 최적화 방법이 다르다. 이미지는 포맷과 지연 로딩, 폰트는 서브셋과 font-display, 캐시는 리소스 유형별 전략. 만능 해결책은 없음
  2. Intersection Observer가 만능키. 이미지 지연 로딩, 동영상 재생 제어, 무한 스크롤 — 뷰포트 기반 최적화는 전부 이걸로 해결
  3. 캐시 전략은 배포 전략과 함께 설계해야 한다. 파일명 해싱 없이 강력 캐시를 쓰면 업데이트가 반영 안 되는 사고가 터진다