이미지 성능

이미지는 대개 웹에서 가장 무겁고 가장 보편적인 리소스입니다. 따라서 이미지를 최적화하면 웹사이트 실적을 크게 개선할 수 있습니다. 대부분의 경우 이미지를 최적화하면 더 적은 바이트를 전송하여 네트워크 시간이 단축되지만, 사용자 기기에 적절한 크기의 이미지를 제공하여 사용자에게 전송되는 바이트 양을 최적화할 수도 있습니다.

이미지는 <img> 또는 <picture> 요소, 또는 CSS background-image 속성을 사용하여 페이지에 추가할 수 있습니다.

이미지 크기

이미지 리소스를 사용할 때 실행할 수 있는 첫 번째 최적화는 이미지를 올바른 크기로 표시하는 것입니다. 이 경우 크기라는 용어는 이미지의 크기를 나타냅니다. 다른 변수가 없다는 점을 고려하여 500x500픽셀 컨테이너에 표시되는 이미지는 500x500픽셀로 최적으로 조절됩니다. 예를 들어 1, 000픽셀의 정사각형 이미지를 사용하면 이미지가 필요한 만큼 두 배로 커집니다.

그러나 적절한 이미지 크기를 선택하는 데 많은 변수가 있으므로 모든 경우에 적절한 이미지 크기를 선택하는 작업이 상당히 복잡합니다. 2010년 iPhone 4가 출시되었을 때는 화면 해상도(640x960)가 iPhone 3 (320x480)의 두 배였습니다. 하지만 iPhone 4 화면의 실제 크기는 iPhone 3와 거의 동일하게 유지되었습니다.

모든 항목을 고해상도로 표시하면 텍스트와 이미지가 이전 크기의 절반으로 크게 줄어들었습니다. 1픽셀이 2개의 기기 픽셀이 됩니다. 이를 기기 픽셀 비율 (DPR)이라고 합니다. iPhone 4와 그 이후에 출시된 많은 iPhone 모델의 DPR은 2입니다.

이전 예를 다시 살펴보면 기기의 DPR이 2이고 이미지가 500x500픽셀 컨테이너에 표시되는 경우 이제 1,000픽셀의 정사각형 이미지(내장 크기라고 함)가 최적의 크기입니다. 마찬가지로 기기의 DPR이 3이면 정사각형 1,500픽셀 이미지가 최적의 크기가 됩니다.

srcset

<img> 요소는 브라우저에서 사용할 수 있는 이미지 소스의 목록을 지정할 수 있는 srcset 속성을 지원합니다. 지정된 각 이미지 소스에는 이미지 URL과 너비 또는 픽셀 밀도 설명자가 포함되어야 합니다.

<img
  alt="An image"
  width="500"
  height="500"
  src="/image-500.jpg"
  srcset="/image-500.jpg 1x, /image-1000.jpg 2x, /image-1500.jpg 3x"
>

위의 HTML 스니펫은 픽셀 밀도 설명어를 사용하여 DPR이 1인 기기에서는 image-500.png를 사용하고, DPR이 2인 기기에서는 image-1000.jpg을, DPR이 3인 기기에서는 image-1500.jpg를 사용하도록 브라우저에 힌트를 제공합니다.

이 모든 것이 잘리고 마른 것처럼 보일 수 있지만 화면의 DPR이 특정 페이지에 가장 적합한 이미지를 선택할 때 유일한 고려사항은 아닙니다. 페이지의 레이아웃은 또 다른 고려사항입니다.

sizes

이전 솔루션은 모든 표시 영역에서 동일한 CSS 픽셀 크기로 이미지를 표시하는 경우에만 작동합니다. 대부분의 경우 페이지의 레이아웃과 컨테이너의 크기는 사용자 기기에 따라 변경됩니다.

sizes 속성을 사용하면 소스 크기 집합을 지정할 수 있으며, 각 소스 크기는 미디어 조건과 값으로 구성됩니다. sizes 속성은 이미지에 의도한 표시 크기를 CSS 픽셀로 설명합니다. srcset 너비 설명어와 결합하면 브라우저에서 사용자 기기에 가장 적합한 이미지 소스를 선택할 수 있습니다.

<img
  alt="An image"
  width="500"
  height="500"
  src="/image-500.jpg"
  srcset="/image-500.jpg 500w, /image-1000.jpg 1000w, /image-1500.jpg 1500w"
  sizes="(min-width: 768px) 500px, 100vw"
>

위의 HTML 스니펫에서 srcset 속성은 브라우저가 선택할 수 있는 이미지 후보 목록을 쉼표로 구분하여 지정합니다. 목록의 각 후보는 이미지 URL과 이미지의 고유 너비를 나타내는 문법으로 구성됩니다. 이미지의 기본 크기는 이미지의 크기입니다. 예를 들어 1000w의 설명어는 이미지의 고유 너비가 1, 000픽셀 너비임을 나타냅니다.

브라우저는 이 정보를 사용하여 sizes 속성의 미디어 조건을 평가하고 이 경우 기기의 표시 영역 너비가 768픽셀을 초과하면 이미지를 너비 500픽셀로 표시하라고 지시합니다. 더 작은 기기에서는 이미지가 100vw(또는 전체 표시 영역 너비)로 표시됩니다.

그러면 브라우저가 이 정보를 srcset 이미지 소스 목록과 결합하여 최적의 이미지를 찾을 수 있습니다. 예를 들어 사용자가 화면 너비가 320픽셀이고 DPR이 3인 휴대기기를 사용하는 경우 이미지는 320 CSS pixels x 3 DPR = 960 device pixels에 표시됩니다. 이 예에서 가장 가까운 크기의 이미지는 원래 너비가 1, 000픽셀 (1000w)인 image-1000.jpg입니다.

파일 형식

브라우저는 여러 다양한 이미지 파일 형식을 지원합니다. WebPAVIF와 같은 최신 이미지 형식은 PNG나 JPEG보다 압축률이 높아 이미지 파일 크기가 작아져 다운로드 시간이 덜 걸릴 수 있습니다. 최신 형식으로 이미지를 제공하면 리소스의 로드 시간을 단축할 수 있으며 이에 따라 최대 콘텐츠 렌더링 시간 (LCP)이 낮아질 수 있습니다.

WebP는 모든 최신 브라우저에서 작동하는 널리 지원되는 형식입니다. WebP는 JPEG, PNG, GIF보다 압축이 더 잘 되는 경우가 많으며 손실무손실 압축을 모두 제공합니다. 또한 WebP는 손실(lossy) 압축을 사용하는 경우에도 알파 채널 투명도를 지원합니다. 이는 JPEG 코덱에서 제공하지 않는 기능입니다.

AVIF는 최신 이미지 형식이며 WebP만큼 널리 지원되지는 않지만 여러 브라우저에서 적당한 지원을 제공합니다. AVIF는 손실(lossy) 압축과 무손실 압축을 모두 지원하며 테스트는 경우에 따라 JPEG와 비교하여 50% 이상 절약되는 것으로 나타났습니다. 또한 AVIF는 WCG (Wide Color Gamut)HDR (High Dynamic Range) 기능도 제공합니다.

압축

이미지와 관련하여 두 가지 유형의 압축이 있습니다.

  1. 손실 압축
  2. 무손실 압축

손실(lossy) 압축은 양자화를 통해 이미지 정확성을 떨어뜨리는 방식으로 작동하며, 추가 색상 정보는 크로마 서브샘플링을 사용하여 삭제될 수 있습니다. 손실 압축은 노이즈와 색상이 많은 고밀도 이미지(일반적으로 콘텐츠가 유사한 사진 또는 이미지)에서 가장 효과적입니다. 그 이유는 손실(lossy) 압축에 의해 생성되는 아티팩트가 이렇게 상세한 이미지에서 알아차릴 가능성이 훨씬 낮기 때문입니다. 하지만 라인 아트, 마찬가지로 확고한 디테일, 텍스트와 같이 선명한 가장자리가 포함된 이미지에서는 손실(lossy) 압축이 효과가 떨어질 수 있습니다. 손실(lossy) 압축은 JPEG, WebP, AVIF 이미지에 적용할 수 있습니다.

무손실 압축은 데이터 손실 없이 이미지를 압축하여 파일 크기를 줄입니다. 무손실 압축은 인접 픽셀과의 차이를 기반으로 픽셀을 설명합니다. 무손실 압축은 GIF, PNG, WebP, AVIF 이미지 형식에 사용됩니다.

Squoosh, ImageOptim 또는 이미지 최적화 서비스를 사용하여 이미지를 압축할 수 있습니다. 압축할 때 모든 사례에 적합한 범용 설정은 없습니다. 이미지 품질과 파일 크기 간의 적절한 절충안을 찾을 때까지 다양한 압축 수준을 실험해 보는 것이 좋습니다. 일부 고급 이미지 최적화 서비스는 이 작업을 자동으로 수행할 수 있지만 모든 사용자에게 재정적으로 실행 가능하지는 않을 수 있습니다.

<picture> 요소

<picture> 요소를 사용하면 여러 이미지 후보를 더 유연하게 지정할 수 있습니다.

<picture>
  <source type="image/avif" srcset="image.avif">
  <source type="image/webp" srcset="image.webp">
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image.jpg"
  >
</picture>

<picture> 요소 내에서 <source> 요소를 사용하는 경우 AVIF 및 WebP 이미지 지원을 추가할 수 있지만 브라우저에서 최신 형식을 지원하지 않으면 더 호환되는 기존 이미지 형식으로 대체됩니다. 이 방법을 사용하면 브라우저가 일치하는 첫 번째 <source> 요소를 선택합니다. 이 형식으로 이미지를 렌더링할 수 있는 경우 그 이미지를 사용합니다. 그러지 않으면 브라우저가 다음 지정된 <source> 요소로 이동합니다. 위의 HTML 스니펫에서 AVIF 형식은 WebP 형식보다 우선순위가 높으며, AVIF 또는 WebP가 모두 지원되지 않으면 JPEG 형식으로 대체됩니다.

<picture> 요소에는 내부에 중첩된 <img> 요소가 필요합니다. alt, width, height 속성은 <img>에서 정의되며 선택된 <source>과 관계없이 사용됩니다.

<source> 요소는 media, srcset, sizes 속성도 지원합니다. 앞의 <img> 예와 마찬가지로 이는 다른 표시 영역에서 어떤 이미지를 선택할지 브라우저에 나타냅니다.

<picture>
  <source
    media="(min-resolution: 1.5x)"
    srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

media 속성은 미디어 조건을 취합니다. 이전 예에서는 기기의 DPR이 미디어 조건으로 사용됩니다. DPR이 1.5 이상인 기기는 첫 번째 <source> 요소를 사용합니다. <source> 요소는 표시 영역이 768픽셀보다 넓은 기기에서 선택된 이미지 후보가 너비가 500픽셀로 표시된다는 것을 브라우저에 알립니다. 더 작은 기기에서는 전체 표시 영역 너비를 차지합니다. media 속성과 srcset 속성을 결합하면 사용할 이미지를 더 세밀하게 제어할 수 있습니다.

이 내용은 다음 표에 나와 있습니다. 여기서 여러 표시 영역 너비와 기기 픽셀 비율이 평가되었습니다.

표시 영역 너비 (픽셀) 1 DPR 1.5 DPR 2 DPR 3 DPR
320 500.jpg 500.jpg 500.jpg 1000.jpg
480 500.jpg 500.jpg 1000.jpg 1500.jpg
560 500.jpg 1000.jpg 1000.jpg 1500.jpg
1024 500.jpg 1000.jpg 1000.jpg 1500.jpg
1920 500.jpg 1000.jpg 1000.jpg 1500.jpg

DPR이 1인 기기는 이미지를 너비가 500픽셀인 외부 크기로 보는 대부분의 데스크톱 사용자를 포함하여 image-500.jpg 이미지를 다운로드합니다. 반면 DPR이 3인 모바일 사용자는 더 큰 image-1500.jpg(DPR이 3인 데스크톱 기기에서 사용되는 것과 동일한 이미지)을 다운로드할 수 있습니다.

<picture>
  <source
    media="(min-width: 560px) and (min-resolution: 1.5x)"
    srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <source
    media="(max-width: 560px) and (min-resolution: 1.5x)"
    srcset="/image-1000-sm.jpg 1000w, /image-1500-sm.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

이 예에서는 DPR이 높은 넓은 기기에 다른 이미지를 사용하기 위해 추가 <source> 요소를 포함하도록 <picture> 요소를 조정합니다.

표시 영역 너비 (픽셀) 1 DPR 1.5 DPR 2 DPR 3 DPR
320 500.jpg 500.jpg 500.jpg 1000-sm.jpg
480 500.jpg 500.jpg 1000-sm.jpg 1500-sm.jpg
560 500.jpg 1000-sm.jpg 1000-sm.jpg 1500-sm.jpg
1024 500.jpg 1000.jpg 1000.jpg 1500.jpg
1920 500.jpg 1000.jpg 1000.jpg 1500.jpg

이 추가 쿼리를 사용하면 image-1000-sm.jpgimage-1500-sm.jpg가 작은 표시 영역에 표시되는 것을 확인할 수 있습니다. 이 추가 정보를 사용하면 압축 아티팩트가 해당 크기와 밀도에서 잘 보이지 않고 데스크톱 기기에서 이미지 품질을 손상시키지 않으므로 이미지를 추가로 압축할 수 있습니다.

또는 srcsetmedia 속성을 조정하여 작은 표시 영역에 큰 이미지를 제공하지 않을 수도 있습니다.

<picture>
  <source
    media="(min-width: 560px)"
    srcset="/image-500.jpg, /image-1000.jpg 2x, /image-1500.jpg 3x"
  >
  <source
    media="(max-width: 560px)"
    srcset="/image-500.jpg 1x, /image-1000.jpg 2x"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

위의 HTML 스니펫에서는 너비 설명어를 삭제하고 기기 픽셀 비율 설명어로 대체했습니다. 휴대기기에 게재되는 이미지는 DPR이 3인 기기에서도 /image-500.jpg 또는 /image-1000.jpg로 제한됩니다.

복잡성 관리 방법

반응형 이미지를 사용할 때는 각 이미지의 다양한 크기 변형과 형식을 사용할 수 있습니다. 앞의 예에서는 각 크기의 변형이 사용되지만 AVIF 및 WebP는 제외됩니다. 변형이 몇 개 있어야 하나요? 많은 엔지니어링 문제와 마찬가지로 답은 '종속 항목'입니다.

가장 적합한 버전을 제공하기 위해 변형을 최대한 많이 포함하고 싶을 수도 있지만, 이미지 변형이 추가될 때마다 비용이 발생하고 브라우저 캐시의 효율성이 떨어집니다. 변형을 하나만 사용하면 모든 사용자가 동일한 이미지를 수신하므로 매우 효율적으로 캐시할 수 있습니다.

반면 변형이 많다면 각 변형에는 다른 캐시 항목이 필요합니다. 서버 비용이 증가하거나 변형의 캐시 항목이 만료되어 원본 서버에서 이미지를 다시 가져와야 하는 경우 성능이 저하될 수 있습니다.

또한, HTML 문서 크기는 변형마다 커집니다. 각 이미지에 몇 킬로바이트의 HTML을 배송해야 할 수도 있습니다.

Accept 요청 헤더를 기반으로 이미지 제공

Accept HTTP 요청 헤더는 사용자의 브라우저가 이해하는 콘텐츠 유형을 서버에 알립니다. 서버는 이 정보를 사용하여 HTML 응답에 추가 바이트를 추가하지 않고도 최적의 이미지 형식을 제공할 수 있습니다.

if (request.headers.accept) {
  if (request.headers.accept.includes('image/avif')) {
    return reply.from('image.avif');
  } else if (request.headers.accept.includes('image/webp')) {
    return reply.from('image.webp');
  }
}

return reply.from('image.jpg');

위의 HTML 스니펫은 서버의 자바스크립트 백엔드에 추가하여 최적의 이미지 형식을 선택하고 제공할 수 있는 간단한 버전의 코드입니다. 요청 Accept 헤더에 image/avif가 포함되어 있으면 AVIF 이미지가 제공됩니다. 그렇지 않고 Accept 헤더에 image/webp가 포함되어 있으면 WebP 이미지가 제공됩니다. 이러한 조건이 모두 참이면 JPEG 이미지가 제공됩니다.

거의 모든 유형의 웹 서버에서 Accept 요청 헤더의 콘텐츠를 기반으로 응답을 수정할 수 있습니다. 예를 들어 mod_rewrite를 사용하여 Accept 헤더를 기반으로 Apache 서버에서 이미지 요청을 재작성할 수 있습니다.

이는 이미지 콘텐츠 전송 네트워크(CDN)에서 볼 수 있는 동작과 다릅니다. 이미지 CDN은 사용자의 기기와 브라우저에 따라 이미지를 최적화하고 최적의 형식을 전송하는 탁월한 솔루션입니다.

핵심은 균형을 찾고, 적절한 수의 이미지 후보를 생성하며, 사용자 환경에 미치는 영향을 측정하는 것입니다. 이미지가 다르면 결과가 달라질 수 있으며 각 이미지에 적용되는 최적화는 페이지 내 이미지 크기 및 사용자가 사용하는 기기에 따라 다릅니다. 예를 들어 전체 너비 히어로 이미지는 전자상거래 제품 등록정보 페이지의 썸네일 이미지보다 더 많은 변형이 필요할 수 있습니다.

지연 로드

loading 속성을 사용하여 이미지가 표시 영역에 나타날 때 이미지가 지연 로드되도록 브라우저에 지시할 수 있습니다. 속성 값 lazy는 이미지가 표시 영역에 있거나 근처에 있을 때까지 이미지를 다운로드하지 않도록 브라우저에 지시합니다. 이렇게 하면 대역폭이 절약되므로 브라우저가 이미 표시 영역에 있는 중요한 콘텐츠를 렌더링하는 데 필요한 리소스의 우선순위를 지정할 수 있습니다.

decoding

decoding 속성은 이미지를 디코딩하는 방법을 브라우저에 알립니다. async 값은 이미지를 비동기식으로 디코딩할 수 있음을 브라우저에 알려 다른 콘텐츠를 렌더링하는 데 걸리는 시간을 개선할 수 있습니다. 값 sync은 이미지가 다른 콘텐츠와 동시에 표시되어야 함을 브라우저에 알립니다. 기본값 auto를 사용하면 브라우저에서 사용자에게 가장 적합한 값을 결정할 수 있습니다.

이미지 데모

학습한 내용 테스트

무손실 압축을 지원하는 이미지 형식은 무엇인가요?

GIF
정답입니다.
JPEG.
다시 시도해 보세요.
PNG
정답입니다.
WebP
정답입니다.
AVIF를 사용합니다.
정답입니다.

손실 압축을 지원하는 이미지 형식은 무엇인가요?

GIF
다시 시도해 보세요. GIF 형식은 256가지 색상의 제한된 팔레트만 지원하지만, GIF로 변환하기 전에 손실 있는 인코딩을 완료해야 합니다.
JPEG.
정답입니다.
PNG
다시 시도해 보세요.
WebP
정답입니다.
AVIF를 사용합니다.
정답입니다.

너비 설명어 (예: 1000w)는 srcset 속성에 지정된 이미지 후보에 관해 브라우저에 알리는 것은 무엇인가요?

이미지의 외부 너비(즉, 스타일이 페이지에 적용된 후 레이아웃에서 이미지의 크기)
다시 시도해 보세요.
이미지의 내장 너비(즉, 이미지 자체의 크기)
정답입니다.

sizes 속성이 적용되는 <img> 요소에 관해 브라우저에 알리는 것은 무엇인가요?

사용자의 현재 표시 영역 크기를 고려하여 로드해야 하는 <img> 요소의 srcset에 지정된 후보를 표현하는 로직.
정답입니다.
<img> 요소의 srcset 속성에서 로드할 이미지의 내장 너비.
다시 시도해 보세요.

다음 동영상: 동영상 실적

이미지는 웹에서 사용되는 가장 일반적인 미디어 유형이지만 성능 측면에서 유일하게 유념해야 하는 것은 아닙니다. 동영상은 웹에서 사용되는 또 다른 일반적인 미디어 유형이며 동영상 자체의 성능 고려사항이 있습니다. 이 과정의 다음 모듈에서는 동영상을 최적화하고 효율적으로 로드하는 방법을 알아봅니다.