개요
Google
의 Chrome
브라우저에서는 웹 페이지의 성능을 측정할 수 있는 Lighthouse
라는 기능을 제공하고 있습니다. 이 기능을 사용하면 웹 페이지의 전반적인 성능을 확인할 수 있고, 다음과 같이 문제점도 확인할 수 있습니다.

이번 블로그 포스트에서는 웹 페이지에서 이미지 포맷을 최적화하여 Serve images in next-gen formats
문제를 해결하고 이미지의 lazy loading
으로 Defer offscreen images
문제를 해결하는 방법에 대해서 알아보겠습니다.
avif와 webp 포맷
Serve images in next-gen formats
문제를 해결하기 위해서는 avif
포맷 또는 webp
포맷의 이미지를 제공할 필요가 있습니다. avif
와 webp
포맷의 이미지는 IE
를 제외한 대부분의 모던 브라우저에서 지원하는 이미지 포맷입니다.
Python으로 avif와 webp 포맷 이미지 생성
이번 블로그 포스트에서는 jpg
또는 png
포맷의 이미지 파일을 Python
을 사용하여 avif
와 webp
포맷의 이미지를 생성하는 방법에 대해서 알아보도록 하겠습니다.
Python
을 사용하여 avif
또는 webp
포맷의 이미지를 생성하기 위해서는 Pillow
와 pillow-avif-plugin
라이브러리를 설치할 필요가 있습니다. 다음 명령어를 사용하여 Pillow
와 pillow-avif-plugin
라이브러리를 설치합니다.
pip install Pillow pillow-avif-plugin
Pillow
는 Python
에서 이미지를 다루기 위한 라이브러리이며, pillow-avif-plugin
은 Pillow
라이브러리를 사용하여 이미지의 포맷을 변경할 때, avif
포맷으로 저장할 수 있게 도와주는 라이브러리입니다.
- Pillow: https://pypi.org/project/Pillow/
- pillow-avif-plugin: https://pypi.org/project/pillow-avif-plugin/
라이브러리를 설치했다면, optimization_images.py
파일을 생성하고 다음과 같이 수정합니다.
import os
import glob
from PIL import Image
import pillow_avif
target_folder = './assets'
files = glob.glob(f'{target_folder}/**/*.jpg', recursive=True) + glob.glob(f'{target_folder}/**/*.png', recursive=True)
for f in files:
print(f)
title, ext = os.path.splitext(f)
webp_file = title + '.webp'
avif_file = title + '.avif'
if os.path.isfile(webp_file) == False:
img = Image.open(f)
img.save(webp_file, format='webp')
img.close()
if os.path.isfile(avif_file) == False:
img = Image.open(f)
img.save(avif_file, format='AVIF' )
img.close()
그럼 소스 코드를 조금 더 자세히 살펴보도록 하겠습니다.
저는 이미지 파일들을 assets
폴더에 저장하고 있습니다. 만약 이미지 파일을 다른 폴더에 저장하고 있다면 다음 부분을 수정하시기 바랍니다.
...
target_folder = './assets'
...
이미지를 저장한 폴더안에서 모든 jpg
와 png
포맷의 파일을 찾습니다.
...
files = glob.glob(f'{target_folder}/**/*.jpg', recursive=True) + glob.glob(f'{target_folder}/**/*.png', recursive=True)
...
그런 다음 모든 파일을 루프를 돌며 파일 포맷을 변경합니다. 파일 포맷을 변경하고 포맷에 맞게 파일명도 변경하기 위해 os.path
를 사용하여 파일명을 준비하였습니다.
...
for f in files:
title, ext = os.path.splitext(f)
webp_file = title + '.webp'
avif_file = title + '.avif'
...
그런 다음, webp
포맷의 파일이 존재하는지 확인하고, 존재하지 않는 경우, 기존 파일을 webp
포맷으로 변경하여 저장합니다.
...
for f in files:
...
if os.path.isfile(webp_file) == False:
img = Image.open(f)
img.save(webp_file, format='webp')
img.close()
...
마찬가지로, avif
포맷의 파일이 존재하는지 확인하고, 존재하지 않는 경우, 기존 파일을 avif
포맷으로 변경하여 저장합니다.
...
for f in files:
...
if os.path.isfile(avif_file) == False:
img = Image.open(f)
img.save(avif_file, format='AVIF' )
img.close()
이것으로 jpg
또는 png
포맷의 이미지 파일을 avif
와 webp
포맷으로 변경하는 Python
스크립트를 제작했습니다.
avif와 webp 파일 생성
그럼 이렇게 만든 optimization_images.py
파일을 실행하여 avif
와 webp
포맷 파일을 생성해 봅시다. avif
와 webp
포맷 파일을 생성하기 위해 다음 명령어를 실행하여 Python
스크립트를 실행합니다.
python optimization_images.py
그럼 다음과 같이 이미지 파일 리스트를 확인할 수 있으며, avif
와 webp
포맷 파일이 생성되는 것을 확인할 수 있습니다.
...
./assets/images/category/flutter/2023/RefreshIndicator/refreshindicator_new_data_with_no_data.png
./assets/images/category/flutter/2023/RefreshIndicator/refreshindicator_pull_to_refresh.png
./assets/images/category/flutter/2023/RefreshIndicator/refreshindicator_no_data.png
./assets/images/category/flutter/2023/RefreshIndicator/listview.png
./assets/images/category/flutter/2023/RefreshIndicator/refreshindicator_refresh_no_data.png
./assets/images/category/flutter/2023/find_child_and_parent_widget/basic_app.png
picture와 source 태그
그럼 이렇게 생성한 avif
와 webp
포맷 파일을 웹 페이지에서 사용하는 방법에 대해서 알아보도록 하겠습니다. 웹 페이지에서 여러 포맷의 이미지를 사용하기 위해서는 <picture />
태그와 <source />
태그를 사용할 필요가 있습니다. 이미지를 불러오는 부분을 다음과 같이 <picture />
태그와 <source />
태그를 사용하여 avif
와 webp
포맷을 불러오도록 수정합니다.
<picture>
<source srcset="example.avif" type="image/avif" />
<source srcset="example.webp" type="image/webp" />
<img src="example.png" alt="example file" />
</picture>
이렇게 <picture />
와 <source />
태그를 사용하면, 브라우저가 지원하는 포맷의 이미지를 다운로드하여 표시하게 됩니다.
loading lazy
Lighthouse
를 사용하여 이미지가 많은 웹 페이지를 검사하면, Defer offscreen images
문제를 발견할 수 있습니다. 이 문제를 해결하기 위해서는 <img />
태그에 다음과 같이 loading="lazy"
를 추가합니다.
<picture>
<source srcset="example.avif" type="image/avif" />
<source srcset="example.webp" type="image/webp" />
<img src="example.png" alt="example file" loading="lazy" />
</picture>
loading lazy
에 관한 자세한 정보는 다음 링크에서 확인하실 수 있습니다.
- Lazy loading: https://developer.mozilla.org/en-US/docs/Web/Performance/Lazy_loading#images_and_iframes
완료
이것으로 웹 페이지 성능 향상을 위해 새로운 이미지 포맷인 avif
와 webp
파일을 생성하고, <picture />
와 <srouce />
태그를 사용하여 이미지 로딩을 최적화하는 방법에 대해서 알아보았습니다. 또한 loading="lazy"
을 사용하여 이미지 로딩을 최적화 하는 방법에 대해서도 알아보았습니다.
Lighthouse
에서 자주 발생하는 지적 사항이므로 이번 기회에 잘 기억해 두면 좋을 거 같습니다. 혹시 브라우저가 아닌 로컬이나 CI
환경에서 Lighthouse
를 실행시키는 방법에 대해 궁금하신 분들은 아래 링크를 참고하시기 바랍니다.
제 블로그가 도움이 되셨나요? 하단의 댓글을 달아주시면 저에게 큰 힘이 됩니다!
앱 홍보
Deku
가 개발한 앱을 한번 사용해보세요.Deku
가 개발한 앱은 Flutter로 개발되었습니다.관심있으신 분들은 앱을 다운로드하여 사용해 주시면 정말 감사하겠습니다.