티스토리 뷰

반응형

웹 사이트와 애플리케이션에서 이미지는 사용자 경험(UX)에 큰 영향을 미칩니다. 이미지와 원활한 로딩 속도는 사용자의 만족도를 높이고, 결과적으로 전환율과 사용자 참여도를 향상시킵니다.

 

계속 올라가는 이미지 크기

 

최근 초고속 인터넷 시대에 접어들면서 사용자는 더 좋은 화질을 원하고 자연스럽게 이미지 크기는 점점 더 커지고 있습니다.  하지만, 고화질 이미지는 용량이 크고 로딩 속도가 느려질 수 있으며, 이는 사용자 경험에 부정적인 영향을 줄 수 있습니다. 따라서 이미지 최적화는 프론트엔드 성능 향상에 핵심적인 역할을 합니다. 

 

콘텐츠 유형 및 파일 형식

이미지 파일은 웹 사이트에서 가장 많은 용량을 차지하는 콘텐츠이기도 합니다. 2022년 HTTP 아카이브 연구에 따르면, 페이지 용량에 가장 큰 영향을 주는 리소스 콘텐츠 유형의 중앙값을 확인했을 때, 이미지가 데스크탑 페이지에서 1,026KB로 가장 큰 비중을 차지하고 있음을 알 수 있습니다(모바일에서는 811KB).

 

 


이미지 종류

웹 사이트와 애플리케이션에서 사용되는 이미지에는 여러 종류가 있습니다. 일반적으로 사용되는 이미지 형식으로는 JPEG, PNG, GIF, SVG, WebP 등이 있습니다. 각 형식은 서로 다른 용도와 특성을 가지고 있으며, 웹 개발자는 상황에 맞는 적절한 이미지 형식을 선택해야 합니다.

 

JPEG (Joint Photographic Experts Group): JPEG는 손실 압축 방식의 이미지 포맷으로, 사진이나 그림과 같은 복잡한 그래픽을 효율적으로 저장할 수 있습니다. JPEG는 압축률을 조절하여 이미지 품질과 파일 크기 사이의 균형을 찾을 수 있습니다. 일반적으로 웹에서 사용되는 사진이나 배경 이미지에 주로 사용됩니다.

PNG (Portable Network Graphics): PNG는 무손실 압축 방식의 이미지 포맷으로, 투명도(알파 채널)를 지원합니다. 디지털 아트, 아이콘, 로고 등의 이미지에 적합하며, 선명한 텍스트나 선 그림을 포함한 이미지에 유용합니다. 하지만 파일 크기가 큰 편입니다.

GIF (Graphics Interchange Format): GIF는 무손실 압축 방식의 이미지 포맷으로, 256색까지만 지원하는 제한된 색상 팔레트를 가집니다. 이러한 제한 때문에 사진 등의 고화질 이미지에는 적합하지 않지만, 간단한 애니메이션을 만드는 데 주로 사용됩니다.

SVG (Scalable Vector Graphics): SVG는 벡터 그래픽을 표현하기 위한 XML 기반의 이미지 포맷입니다. 벡터 이미지는 확대/축소 시 품질이 손상되지 않아, 아이콘, 로고, 일러스트 등의 웹 요소에 적합합니다. 또한, 스타일 및 애니메이션을 CSS와 JavaScript를 통해 조작할 수 있습니다.

WebP: WebP는 Google이 개발한 이미지 포맷으로, 손실 압축과 무손실 압축 두 가지 방식을 모두 지원합니다. 높은 압축률을 유지하면서도 이미지 품질을 유지할 수 있어, 웹 성능 최적화에 유용합니다. 하지만 아직 모든 브라우저에서 지원되지는 않습니다.

AVIF (AV1 Image File Format): AVIF는 Alliance for Open Media가 개발한 이미지 포맷으로, AV1 비디오 코덱을 기반으로 합니다. 손실 압축을 사용하며, WebP와 비교하여 더 높은 압축률과 이미지 품질을 제공합니다. 최신 브라우저에서 점차 지원되고 있으나, 일부 브라우저에서 지원되지 않을 수도 있습니다.

이러한 이미지 포맷들은 각각의 특성과 용도에 따라 웹 개발에서 적절하게 사용되어야 합니다. 그런데 위 설명에서 소개된 손실 압축과 무손실 압축은 무엇일까요?

 


이미지 변환 기법: 무손실 압축과 손실 압축

이미지 최적화에는 무손실 압축과 손실 압축 두 가지 기법이 사용됩니다. 무손실 압축은 이미지 품질을 손상시키지 않고 파일 크기를 줄이는 방법이며, 손실 압축은 이미지 품질을 손상시켜도 파일 크기를 더욱 줄일 수 있는 방법입니다.

 

이미지 손실 압축 (Lossy Compression):

손실 압축은 원본 이미지의 일부 정보를 버림으로써 이미지의 크기를 줄입니다. *손실 압축 알고리즘은 이미지의 눈에 띄지 않거나 덜 중요한 부분에 대해 데이터를 제거함으로써 압축을 수행합니다. 손실 압축은 일반적으로 높은 압축률을 제공하지만, 원본 이미지와의 완전한 복원은 불가능합니다. JPEG는 손실 압축 방식으로 널리 사용되는 이미지 포맷입니다. JPEG 압축은 DCT (Discrete Cosine Transform) 기반의 알고리즘을 사용합니다.

 

*JPEG 압축 - DCT (Discrete Cosine Transform) 기반의 알고리즘:

DCT는 이미지를 주파수 도메인으로 변환하고, 고주파 영역의 정보를 삭제하여 이미지 크기를 줄입니다. JPEG 압축률을 조절할 수 있어, 원하는 품질과 파일 크기 간의 균형을 맞출 수 있습니다.

 

  • 이미지를 8x8 픽셀 블록으로 나눕니다.
  • 각 블록의 픽셀 값을 0-255 범위에서 -128~127 범위로 조정합니다. - 데이터 정규화
  • DCT를 사용하여 각 블록을 주파수 도메인으로 변환합니다. - 이산코사인변환
  • 양자화 과정을 통해 고주파 계수를 삭제하고 압축률을 조절합니다.
  • 남은 계수를 엔트로피 코딩을 사용하여 더욱 압축합니다.

 

손실 압축 이미지 종류

  • JPEG
  • JPEG 2000
  • WebP
  • AVIF 등

 

무손실 압축 알고리즘 (Lossless Compression Algorithm):

무손실 압축 알고리즘은 원본 데이터를 정확하게 복원할 수 있는 방식으로 데이터 크기를 줄입니다. 이 방식은 이미지 데이터의 패턴과 반복을 인식하고, 이를 효율적으로 표현하여 압축을 수행합니다. PNG는 무손실 압축 이미지 포맷입니다. PNG 압축은 DEFLATE 알고리즘을 사용하여 이미지 데이터를 압축합니다. DEFLATE는 LZ77 및 허프만 코딩(Huffman coding)을 결합한 알고리즘으로, LZ77은 이미지 데이터의 반복 패턴을 인식하고, 허프만 코딩은 데이터의 빈도에 따라 코딩을 최적화합니다.

전공자라면 매우 익숙한 ... 그 이름, 허프만.
허프만 코드(Huffman's Code)는 허프만 알고리즘에 의해 생성된 최적 이진코드를 말한다.

 

무손실 압축 이미지 종류

  • PNG
  • GIF
  • WebP 등

용량을 상대적으로 많이 줄여주는 손실 압축 이미지를 활용하여 로딩 속도를 개선하면 좋을까요? 이미지 용량을 줄이려면 손실을 시켜야하고 손실을 아무런 기준없이 진행하면 위험합니다. 사용자 경험과 이어지기 때문입니다.

 

사람은 명암 차이에는 민감한 반면, 채색 차이에는 크게 민감하지 않아 이미지 색이 비슷한 부분을 하나로 통일하여도 일반적으로 사용자는 눈치채기 어렵습니다. 또한 약간의 화질 차이에도 그렇게 민감하지 않습니다. 이러한 부분들을 위에서 소개드린 알고리즘을 통해 손실시켜 이미지 용량을 줄이면서 사용자 경험을 향상시키면 보다 효율적인 웹사이트를 만들 수 있습니다. 

 

그러면 의문점
몇퍼센트나 손실시켜야할까? 기준이 있을까?

 

https://github.com/rflynn/imgmin

Imagin 프로젝트의 연구조사에 의하면 75% 손실까지는 품질 차이가 거의 없다고 합니다.

For an average JPEG there is a very minor, mostly insignificant change in apparent quality from 100-75, but a significant filesize difference for each step down. This means that many images look good to the casual viewer at quality 75, but are half as large than they would be at quality 95. As quality drops below 75 there are larger apparent visual changes and reduced savings in filesize. - Imagin progject

75% 이하로 내려가는 순간 사용자가 시각적 반응에 민감해진다고 하니, 연구조사 결과를 통해 75%까지 손실 기준을 잡을 수 있을 것 같습니다.

 

 


 

지금까지 현대 웹 생태계에서 이미지의 중요성을 살펴보았고, 다양한 이미지 종류와 손실 압축 알고리즘, 무손실 압축 알고리즘에 대해 알아보았습니다. 또한, 얼마나 손실이 발생해도 사용자가 허용 가능한지에 대한 연구 결과를 살펴보았습니다. 지금부터 이미지 최적화를 어떻게 실제로 적용할지에 대해 알아보겠습니다.

우리는 이미지를 가볍게 만드는 방법에 대해 이해했습니다.

그렇지만 이미지를 가볍게 만들었다고 해도, 최근에는 다양한 디바이스로 인해 화면 크기가 다양하기 때문에 각 상황에 맞는 적절한 이미지를 브라우저에 로딩하는 것이 중요합니다. 모바일 화면(382 x 466)에서 4K 화면(3,840 X 2,160)에서 사용될 이미지를 다운로드 받는 것은 비효율적이기 때문입니다.


이제 화면 크기에 맞는 적절한 이미지를 보여주는 방법을 알아볼 필요가 있습니다.

 

https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images

 

srcset 속성

 srcset은 브라우저에게 제시할 이미지 목록과 그 크기를 정의합니다. HTML의 <img> 태그에 사용되며, 브라우저에게 여러 이미지 소스를 제공하고 이미지를 다양한 해상도에서 표시할 수 있게 합니다. 이를 통해 반응형 웹 디자인에서 디스플레이 크기나 픽셀 밀도에 따라 가장 적절한 이미지를 선택하고 로드할 수 있습니다.

 

<img src="tooo1-small.jpg"
     srcset="tooo1-small.jpg 480w, tooo1-medium.jpg 720w, tooo1-large.jpg 1280w"
     alt="퉁이리가 짱이다">

📢 (스크린 리더): 퉁이리가 짱이다 이미지

alt 속성에 이미지라는 단어는 안 넣어도 돼요!
스크린 리더가 <img>를 통해 ‘이미지’로 결정해줘요.

그리고
저처럼 사용하시면 안 돼요. (퉁이리가 짱이다)
이미지에 적합한 대체 텍스트를 사용해 주세요!

 

여기서 src 속성은 기본 이미지를 설정하고, srcset 속성에는 각 이미지 파일과 그에 해당하는 이미지의 너비(해상도)를 지정합니다. w 단위는 너비를 의미하며, 이미지 너비를 픽셀로 나타냅니다.

위 예시에서 브라우저는 기기의 화면 크기와 픽셀 밀도를 고려하여 사용 가능한 이미지 중 가장 적합한 이미지를 선택합니다. 예를 들어, 화면의 너비가 480픽셀인 경우 tooo1-small.jpg를, 화면의 너비가 720픽셀인 경우 tooo1-medium.jpg를 선택할 수 있습니다.

srcset 속성을 사용하면 다양한 환경에서 이미지를 최적화하고, 사용자에게 더 나은 사용자 경험을 제공할 수 있습니다. 그러나 메모리 등 환경이 여의치 않으면 낮은 해상도의 이미지가 선택되어 화면에 나타날 수 있습니다. srcset은 어느정도 해결해주긴 하지만 완벽하게 지원하지는 않습니다. 해상도별로 다른 사진을 주게되면 기대와 다른 사진을 사용자에게 제공할 수도 있어요. 그래서 동일한 이미지를 크기만 다르게 사용하는 것이 예외 케이스를 막아 최대한 동일한 사용자 경험을 제공할 수 있다고 생각합니다.

 

 

picture 태그

<picture> 태그는 웹 페이지에서 다양한 조건에 따라 이미지 소스를 선택하고 사용할 수 있도록 도와주는 HTML5의 요소입니다. <picture> 태그는 여러 <source> 태그를 포함하며, 이를 통해 미디어 쿼리와 함께 다양한 이미지 소스를 제공할 수 있습니다. 브라우저는 <source> 태그들 중 조건에 맞는 이미지를 선택하여 로드하게 됩니다.

<picture> 태그와 srcset 속성을 함께 사용하면 더욱 정교한 이미지 선택이 가능합니다. 이를 통해 브라우저는 뷰포트 크기와 기기의 픽셀 밀도에 따라 적절한 이미지를 선택할 수 있습니다.

예를 들어 다음과 같이 <picture> 태그와 srcset 속성을 사용하여 뷰포트 크기에 따라 다른 이미지를 제공할 수 있습니다.

 

<picture>
  <source media="(min-width: 1280px)" srcset="tooo1-large.jpg">
  <source media="(min-width: 720px)" srcset="tooo1-medium.jpg">
  <img src="tooo1-small.jpg" alt="퉁이리가 짱이다">
</picture>

위 예시에서는 뷰포트의 너비가 1280 픽셀 이상인 경우 tooo1-large.jpg 이미지를 사용하고, 720 픽셀 이상인 경우 tooo1-medium.jpg 이미지를 사용합니다. 그 외의 경우에는 기본 이미지인 tooo1-small.jpg를 사용합니다.

 

https://caniuse.com/?search=picture

<picture> 태그와 srcset 속성을 함께 사용하면, 화면 크기, 픽셀 밀도, 이미지 형식 등 다양한 조건에 따라 최적화된 이미지를 제공할 수 있으며, 이를 통해 사용자에게 더 나은 사용자 경험을 제공할 수 있습니다. 그러나 모든 브라우저가 지원하고 있지 않아요. 하지만 최신 버전들의 브라우저들은 대부분 picture 태그를 지원하니 안심하고 사용하셔도 될 것 같습니다. 

만약 지원하지 않는 브라우저에서도 picture 태그를 사용하고 싶으시면 polyfill를 활용해요!

 

실제 활용 사례

실제 활용 사례를 찾기 위해 많은 사이트를 프로파일링하였고 예시에 적합한 사이트를 찾았어요!

 

https://about.daangn.com/

당근마켓 소개페이지를 예시로 들어보겠습니다.

 

이미지 로딩이 완료된 상황입니다. 이제 화면 사이즈를 바꿔볼까요?

 

화면 크기가 바뀔 때마다 새로운 사진을 받아오고 있습니다. 코드를 살펴볼게요.

 

<picture
  ><source
    type="image/avif"
    sizes="100vw"
    srcset="
      /static/e196734140dc4952ed1c2ab9e1ce0b12/98582/2107eb7a-c125-4118-b1a8-7fafb49c8509_home_key_mobile(3x4).avif  576w,
      /static/e196734140dc4952ed1c2ab9e1ce0b12/92ec5/2107eb7a-c125-4118-b1a8-7fafb49c8509_home_key_mobile(3x4).avif  768w,
      /static/e196734140dc4952ed1c2ab9e1ce0b12/f851b/2107eb7a-c125-4118-b1a8-7fafb49c8509_home_key_mobile(3x4).avif  992w,
      /static/e196734140dc4952ed1c2ab9e1ce0b12/13c44/2107eb7a-c125-4118-b1a8-7fafb49c8509_home_key_mobile(3x4).avif 1080w
    " />
  <source
    type="image/webp"
    sizes="100vw"
    srcset="
      /static/e196734140dc4952ed1c2ab9e1ce0b12/540d8/2107eb7a-c125-4118-b1a8-7fafb49c8509_home_key_mobile(3x4).webp  576w,
      /static/e196734140dc4952ed1c2ab9e1ce0b12/3f179/2107eb7a-c125-4118-b1a8-7fafb49c8509_home_key_mobile(3x4).webp  768w,
      /static/e196734140dc4952ed1c2ab9e1ce0b12/89940/2107eb7a-c125-4118-b1a8-7fafb49c8509_home_key_mobile(3x4).webp  992w,
      /static/e196734140dc4952ed1c2ab9e1ce0b12/91c76/2107eb7a-c125-4118-b1a8-7fafb49c8509_home_key_mobile(3x4).webp 1080w
    " />
  <img
    data-main-image=""
    style="opacity: 1"
    sizes="100vw"
    decoding="async"
    loading="lazy"
    alt="당근마켓 사무실 전경, 넓은 라운지에서 당근이가 손을 흔들고 있어요."
    src="/static/e196734140dc4952ed1c2ab9e1ce0b12/5129e/2107eb7a-c125-4118-b1a8-7fafb49c8509_home_key_mobile(3x4).jpg"
    srcset="
      /static/e196734140dc4952ed1c2ab9e1ce0b12/24fdc/2107eb7a-c125-4118-b1a8-7fafb49c8509_home_key_mobile(3x4).jpg  576w,
      /static/e196734140dc4952ed1c2ab9e1ce0b12/7511c/2107eb7a-c125-4118-b1a8-7fafb49c8509_home_key_mobile(3x4).jpg  768w,
      /static/e196734140dc4952ed1c2ab9e1ce0b12/d8184/2107eb7a-c125-4118-b1a8-7fafb49c8509_home_key_mobile(3x4).jpg  992w,
      /static/e196734140dc4952ed1c2ab9e1ce0b12/5129e/2107eb7a-c125-4118-b1a8-7fafb49c8509_home_key_mobile(3x4).jpg 1080w
    "
/></picture>

 

제가 설명드렸던 것과 동일하게 화면 크기 및 해상도에 따라 서로 다른 이미지 파일을 제공하고 있으며, 또한 이미지 형식도 다양하게 제공하고 있습니다. 두 개의 <source> 태그 중 첫 번째는 AVIF 이미지 형식을, 두 번째는 WebP 이미지 형식을 사용합니다.

 

네트워크 탭을 살펴보면 브라우저에서 어떤 이미지를 지원하는지도 알 수 있습니다. 기본적으로 Accept 헤더에 표시되고 있고 또한 User-Agent Client Hints를 통해 다양한 정보 힌트를 담을 수 있습니다. 저같은 경우에는 다음과 같네요!

 

Sec-Ch-Ua: Google Chrome 113, Chromium 113, 그리고 Not-A.Brand 24가 포함되어 있고 저는 힌트를 토대로 크롬을 이용하고 있습니다.

Sec-Ch-Ua-Mobile: 클라이언트가 모바일 기기인지 여부를 나타냅니다. 이 경우에는 ?0으로 표시되어, 모바일 기기가 아님을 나타냅니다. 노트북으로 들어왔어요!
Sec-Ch-Ua-Platform: 클라이언트의 운영 체제를 나타냅니다. 저는 Windows입니다.
Sec-Fetch-Dest: 요청 목적을 나타냅니다. 이 경우에는 이미지를 가져오는 것이 목적입니다. 우리는 image를 공부하고 있죠!
Sec-Fetch-Mode: 요청 모드를 나타냅니다. 이 경우에는 no-cors입니다.
Sec-Fetch-Site: 요청이 어떤 출처에서 이루어졌는지를 나타냅니다. 이 경우에는 same-origin입니다.
User-Agent: 클라이언트의 브라우저 및 운영 체제에 대한 정보를 나타내는 문자열입니다. 

 

https://developer.chrome.com/ko/articles/user-agent-client-hints/

 

자세한 예시를 통해 학습을 한 후 실제 활용 사례를 보니 더욱 이해가 되네요.

 

 

웹 페이지의 이미지 최적화를 위한 다양한 방법과 기술을 살펴보았습니다. 먼저, 여러 이미지 종류와 그 특징들을 알아보았고 이미지 변환 기법 중 무손실 압축과 손실 압축에 대해서도 알아봤습니다. 이어서, 이미지를 더 효율적으로 관리하기 위해 사용하는 srcset 속성과 picture 태그에 대해, 마지막으로, 실제 활용 사례를 통해 이미지 최적화 기법들이 어떻게 적용되는지를 확인하였습니다.

이미지 최적화는 사용자 경험과 웹 페이지의 로딩 속도에 큰 영향을 미치기 때문에 프론트엔드 개발자들이 주목해야 할 중요한 주제입니다. 이 글을 통해 소개된 이미지 최적화 기법들을 적용하여 웹 페이지의 이미지 관리를 개선하고, 사용자들에게 더 나은 웹 환경을 제공할 수 있기를 바랍니다.

 

 

 

좋아요는 로그인하지 않아도 누를 수 있습니다!

728x90
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함