사이드 프로젝트를 다시 보면서 이미지 관련해서 적용해보고 싶은 것들이 있어 다시 건드리게 되었다.
현재 API에서 모든 포켓몬은 1035마리로 각 포켓몬은 앞/뒤 모습을 이미지로 보여주고 있다. 뒷 모습의 경우 마우스를 호버해서 보여주지만 앞모습의 경우 모든 포켓몬의 이미지를 다운로드하기 때문에 더욱 빠른 초기화면을 보여주기 위해 여러가지 방법을 시도해보았다.
우선 다른 처리 없이 한번에 모든 포켓몬을 보여줬을 때 총 개발자 도구 Network 탭 기준으로 3초 정도 걸렸다.
이후 시도해볼 방식과 비교하기 위해서 조금 느린 Slow 4G 환경에서도 시간을 측정하였다. 약 21초 정도 나오는 것을 확인할 수 있었다.
가장 먼저 프로젝트에서 시도했던 방식은 무한 스크롤을 적용하는 것이었다.
첫 화면에서는 30장의 포켓몬만 보여주고, Intersection Observer를 활용하여 각 페이지의 26번째 포켓몬이 화면에 등장하면 다음 30마리의 포켓몬을 이어 붙여 보여주는 식으로 처리하였다.
동일한 환경에서 측정해봤을 때, 일반 브라우저 환경에서는 1.9초, Slow 4G 환경에서는 10.6초 정도 걸리는 것을 확인할 수 있었다.
프로젝트 내에서 이미지 리소스를 활용할 때 아래와 같이 url과 포켓몬 ID를 조합해서 활용하고 있다.
<img
src={`https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${
focusState ? "back/" : ""
}${pokemonInfo.id}.png`}
alt={`pokemon-${pokemonInfo.id}`}
/>;
처음에는 이미지를 포함하는 컴포넌트에 intersection observer 활용하여 뷰포트에 노출될 떄 이미지를 보여주는 식으로 구현하려고 했지만 이미지 태그 내에 loading property를 활용하면 된다는 것을 확인하고 아래와 같이 코드를 추가하였다.
<img
src={`https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${
focusState ? "back/" : ""
}${pokemonInfo.id}.png`}
alt={`pokemon-${pokemonInfo.id}`}
loading="lazy"
/>;
마찬가지로 동일하게 측정해보니 일반 브라우저 환경에서는 약 2.5초 정도 소요되었고, Slow 4G 환경에서는 약 10초 정도 걸리는 것을 확인할 수 있었다.
앞서 30개씩 잘라서 보여주는 방식을 활용했을 때와는 다르게 이번 초기 로딩에는 60개의 이미지를 먼저 로딩하는 것에서 차이가 있었다.
60개는 임의로 설정한 값이 아니어서 어떤 기준으로 개수가 결정된 것인지 알아보니, MDN Lazy Loading 문서에서 loading 속성을 사용할 때 화면 밖에 있는 이미지의 로딩을 사용자가 가까이 스크롤 할 때 까지 지연시키도록 브라우저에게 지시할 수 있습니다.
라는 설명을 통해, 앞서 구현하려고 했던 Intersection Observer와 비슷하게 뷰포트 기준으로 이미지 로딩이 이루어짐을 추측해볼 수 있었다.
사실 이번 이미지 핸들링 하기 전에 이미지 사이즈들이 작아 Lazy Loading을 적용했을 때 유의미한 차이가 있을까 하는 생각이 먼저 들었었다. 하지만 두가지 방식을 몇가지 환경에서 실험해보니 불러오는 이미지의 개수나, 브라우저 환경에 따라 사소한 차이가 크게 느껴질 수도 있겠다는 생각이 들었다.
일단 프로젝트에는 loading 속성을 활용한 코드를 반영하기로 결론을 내렸다. 이번 프로젝트의 경우 포켓몬 데이터를 전부 받아오기 때문에 굳이 30개씩 슬라이스 한 후, 스크롤에 따라 컴포넌트를 리랜더링 할 이유가 없겠다고 생각했고, 각 방식을 비교했을 때 두 방식의 성능차이가 크지 않았기 때문에 loading 속성을 사용하는 것으로 결론을 내렸다.
하지만 다른 프로젝트에서 백엔드에서 넘겨주는 데이터가 페이지 별로 호출해야할 때는 1번과 2번 모두 적용해볼 수 있겠다는 생각이 들었다.
Image Lazy Loading의 경우 2가지외에 css를 활용하거나, placeholder UI를 활용한 방식들도 존재해서 더 다양한 방향에서 깊게 고민해봐야할 부분인 것 같다.
https://helloinyong.tistory.com/297
https://velog.io/@syoung125/WIL-2021.11-1st
https://developer.mozilla.org/ko/docs/Web/Performance/Lazy_loading