ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 웹 성능 최적화를 위한 Image Lazy Loading 기법
    개발 블로깅/Improving Performance 2020. 11. 29. 10:37

     

     

    현재 화면에 보여지지 않는 lazy loading된 이미지들은 웹 페이지 초기의 로딩 시간을 단축하여 웹 성능을 향상시킵니다.
    이 글은 lazy loading 처리 기법과 관련된 모든 것들을 깊게 다루게 됩니다.

    해당 글은 작성자 imagekit.io 의 동의하에 'Lazy Loading Images - The complete Guide'의 아티클을 번역하였습니다.

    외국 아티클 번역은 처음으로 도전하다보니, 거의 발 번역 수준입니다..
    하지만 내용 이해에는 문제가 없을 듯 하여, 귀엽게 봐주시면 감사드리겠습니다!


    이미지는 모든 웹 사이트와 어플리케이션에서 매우 중요한 요소입니다. 마케팅 배너 혹은 상품 이미지, 로고 등 이젠 웹 사이트 내에서 이미지가 없다는 것은 상상할 수 없을 정도입니다. 그러나 슬프게도 이미지는 페이지 성능에 가장 많이 영향을 주고 있는 요소입니다.

    최신 HTTP Archive data에 따라서, 데스크톱 내 페이지 중앙 사이즈는 1511KB 이고, 그중 이미지가 거의 650KB의 크기를 차지하므로 전체 페이지 크기에서 대략 45%를 차지합니다. 이미지를 웹 페이지에서 없앨 수는 없기 때문에, 우리는 이미지를 그대로 쓰면서 웹 페이지를 빠르게 로딩할 수 있는 방법을 찾아야 합니다.

    해당 가이드에서 우리는 기존의 모든 이미지를 그대로 유지한 채 페이지 사이즈를 줄이고 페이지 로딩 시간을 향상시킬 수 있는 기술인 Images laze loading 기법에 대해 다룰 것입니다.

     

    목차 (클릭으로 해당 목록 이동)

     

    Lazy Loading 기법으로 무엇을 이룰 수 있는가

    먼저 lazy loading으로 이미지가 동작하는 비디오 샘플을 보여드리겠습니다. 페이지를 스크롤할 때, 회색의 placeholder가 실제 이미지로 어떻게 바뀌는지를 주의해서 보도록 합시다.

     

    Image Lazy Loading이란 무엇인가

    Image Lazy Loading은 페이지 안에 있는 실제 이미지들이 실제로 화면에 보여질 필요가 있을 때 로딩을 할 수 있도록 하는 테크닉입니다. 웹 페이지 내에서 바로 로딩을 하지 않고 로딩 시점을 뒤로 미루는 것이라 볼 수 있습니다. 이 방식은 웹 성능과 디바이스 내 리소스 활용도 증가, 그리고 연관된 비용을 줄이는데 도움을 줄 수 있습니다.

    영어 단어 중 'lazy'는 '가능한 길게 일을 미루는 행위' 란 의미에 기반합니다.

    유사하게, lazy loading은 페이지 내에서 실제로 필요로 할 때까지 리소스의 로딩을 미루는 것입니다. 페이지를 로드하자마자 리소스를 로딩하는 일반적인 방식 대신, 실제로 사용자 화면에 보여질 필요가 있을 때까지 이러한 로딩을 지연하는 것입니다.

    laze loading을 다루는 방식은 페이지 내의 거의 모든 리소스에 적용할 수 있습니다. 예를 들어, SPA(Single Page Application) 내에서 JS 파일이 나중에까지 필요하지 않으면 초기에 로드해서 가져오지 않는 것이 가장 좋습니다. 이 처럼 이미지도 바로 보여질 필요가 없다가, 실제로 보여질 필요가 있을 때 로딩을 하는 것입니다.

     

    왜 lazy loading을 사용해야 하는가

    Lazy Loading은 페이지 내에서 바로 필요하지 않은 이미지들을 로딩 시점을 뒤로 미루는 것입니다. 페이지 로드 시점에 유저에게 보여지지 않는 이미지는 스크롤 등으로 실제로 이미지가 보여지는 시점이 올 때 로딩됩니다. 만약 사용자가 스크롤하는 행위가 없으면, 사용자에게 보여지지 않은 이미지는 절대 로딩되지 않습니다.

    이것은 2가지의 장점을 가지고 있습니다.

    1. 성능 향상

    이것은 웹 사이트의 로딩 시간, 성능 관리 면에서 가장 중요한 요소 중 하나입니다.

    lazy loading을 이용하면, 페이지 초기 로딩 시 필요로 한 이미지의 수를 줄일 수 있습니다. 리소스 요청을 줄이는 것은 다운로드 bytes를 줄이는 것이며, 이는 유저가 사용할 수 있는 제한된 네트워크 대역폭의 경쟁을 줄이는 것을 의미합니다. 이것은 디바이스가 다른 리소스들을 더 빠르게 처리해서 다운로드하도록 확보하는 것입니다. 그러므로, lazy loading을 쓰지 않는 것에 비해서 페이지를 훨씬 빨리 유저가 이용하게 되는 것입니다.

     

    2. 비용 감소

    두 번째 장점은 통신 비용 관점에 있습니다. 이미지 전달 또는 다른 전달할 무언가는 주로 전송 바이트 수에 기반하여 청구됩니다.

    lazy loading에 대해 앞서 언급했듯이, 이미지가 보여지지 않으명 절대 로딩하지 않으므로, 페이지 내에서 전달할 총 바이트 용량을 줄일 수 있습니다. 특히나 페이지를 이탈하거나 페이지의 제일 상단에만 서비스를 이용하는 유저에게 효과적입니다. 이처럼 네트워크로부터 전송될 바이트의 감소는 전송 비용을 줄입니다. 이 부분은 lazy loading에 대해 알아보면서 더욱 자세하게 알게 될 것입니다.

     

    어떤 이미지에 Lazy Loading을 적용할 수 있는가

    lazy loading의 기본적인 방법은 매우 간단합니다. 지금 당장 필요하지 않은 모든 요소들을 잠시 로딩을 지연하는 것입니다. 따라서 사용자 화면에 보여지지 않는 이미지들은 로딩을 지연시킬 수 있습니다.

    사용자가 페이지에서 스크롤을 아래로 내림으로써, 이미지의 placeholder는 뷰포트(웹 페이지 내 보여지는 부분)에 다가오게 됩니다. 뷰포트에 보여지게되면 이미지를 로딩하도록 트리거를 일으킵니다.

    lazy loading에 어떤 이미지가 적합한지, 그리고 페이지 초기 로딩 시 얼마나 바이트 용량을 줄일 수 있는지 Google Lighthouse audit tool을 이용해서 알 수 있습니다. 또한 ImageKit's website analyzer는 lazy loading 사용 여부를 확인할 수 있을 뿐 아니라, 페이지 내에서 크리티컬한 이미지 관련해서 최적화 용도로도 사용할 수 있습니다.

    Lazy loading은 좋은 퍼포먼스 뿐 아니라 서비스 사용성에서도 매우 효과적입니다.

     

    Lazy Loading을 다루는 여러가지 기술

    웹 페이지 내 이미지는 두 가지 방법으로 로드할 수 있습니다. 바로 <img>태그와 CSS 속성 중'background'를 이용하는 것입니다. 둘 중 조금 더 흔히 쓰이는 <img>를 먼저 확인해봅시다.

    <img> 태그를 이용한 일반적인 방법

    Lazy loading 이미지들은 두 단계로 나눌 수 있습니다.

    첫 번째는, 이미지 로딩을 사전에 막는 것입니다. 일반적으로 <img>태그를 이용해서 이미지를 로드하기 위해서, 브라우저는 태그 내 src 속성을 이용합니다. HTML 내 첫 번째 이미지든 1000번째 이미지이든, 혹은 뷰포트 밖에 있든 상관없이, 만약 브라우저가 src 속성을 가지면, 이미지를 무조건 로드합니다.

    그러므로, 이와 같은 이미지들의 로딩을 지연시키려면, src 속성 대신 다른 속성에다가 이미지  URL을 넣는 것입니다. 우리가 <img> 태그의 data-src라는 속성에 이미지 URL을 지정했다고 가정해 봅시다. 그러면 src는 비워져 있고, 브라우저는 해당 이미지를 로드하지 않습니다.

    <img data-src="https://ik.imagekit.io/demo/default-image.jpg" />

     

    위 방식으로 이미지 로드를 사전에 막았으니, 이제는 브라우저에게 해당 이미지를 언제 로딩할 것인지 알려주어야 합니다.

    이를 위해서는, 해당 이미지(현재는 그냥 placeholder 상태)가 뷰포트에 들어오자마자 로딩할 수 있도록 확인해야 합니다. 확인할 수 있는 방법은 두 가지 방식이 있습니다.

    자바스크립트 이벤트를 이용하여 image load를 일으키는 방법

    이 기술은 브라우저 내 scroll, resize 그리고 orientationChange 이벤트 리스너를 이용할 수 있습니다. scroll 이벤트는 사용자가 페이지에서 스크롤하는 시점을 확인할 수 있습니다. resize와 orientationChange 이벤트는 lazy loading을 위해서는 함께 사용해야 합니다. resize 이벤트는 윈도우 브라우저 크기가 바뀔 때 발생합니다. orientationChange 이벤트는 디바이스 화면이 가로에서 세로 모드로(또는 반대로) 바뀔 때 발생합니다. 이 처럼 가로, 세로 모드를 변경하는 것은 화면 내 보여지는 이미지의 수가 바뀔 수 있으므로 이미지들을 로드하는 트리거가 필요할 것입니다.

    이 이벤트들 중 하나가 발생할 때 로딩이 지연되었거나 아직 로딩되지 않은 이미지들을 모두 찾습니다. 윈도우 높이, 현재 스크롤 위치, 그리고 이미지의 위치를 이용해서 어떤 이미지가 뷰포트 안으로 들어왔는지 확인하게 됩니다. 뷰포트 안으로 들어가면 <img>태그의 data-src 속성에 지정된 URL을 src 속성에 넣어서 이미지를 로드합니다. 이후 나중에 트리거 이벤트를 일으키기 위해 로딩을 지연시킬 이미지로 식별하던 lazy 클래스를 제거합니다. 모든 이미지가 로딩되면 그때 트리거를 일으키던 이벤트 리스너를 제거하게 됩니다.

    scroll 이벤트는 스크롤 시 여러 이벤트가 급격히 발생하므로, 약간의 쓰로틀 기능을 이용해서 lazy loading 기능을 적용하는 게 좋습니다.

     

    아래는 구현 방식의 실제 예시입니다.

    See the Pen Lazy loading images using event handlers - example code by ImageKit.io (@imagekit_io) on CodePen.

     

    여기서 주목할 것은, 위 예시에서 처음 3개의 이미지는 미리 로딩되어 있습니다. URL이 data-src 속성 대신 src 속성에 적용되어 있습니다. 이것은 유저 사용성에 있어 좋습니다. 페이지 상단에 있는 이미지들은 JS 파일이 로딩되고 이벤트가 발생할 때까지 기다릴 수 없으므로 이 처럼 가능한 한 빨리 보여지게 해야 합니다.

    Intersection Observer API를 이용하여 image load를 일으키는 방법

    Intersection Observer API는 비교적 나온 지 꽤 안된 새로운 API입니다. 이 API는 엘리먼트 요소가 뷰포트에 들어가는 것을 감지하고 액션을 취하는 것을 아주 간단하게 만들어 줍니다. 앞에서 본 방법들은, 엘리먼트가 뷰포트에 들어가는 것에 대해서 연산하는 것을 구현하고 이벤트를 직접 바인드 시켰지만, Intersection Observer API를 이용하면 이러한 부분들을 쉽게 구현할 수 있을 뿐 아니라 성능 면으로도 좋습니다.

    Intersection Observer API를 이용하여 lazy load를 구현한 예시:

    우리는 이미지 로드를 지연시키기 위해 모든 이미지에 옵저버를 부착시킵니다.  엘리먼트가 뷰포트에 들어간 것은 API가 감지했을 때, isIntersecting 속성을 이용해서 URL을 data-src 속성에서 src 속성으로 이동시켜서 브라우저가 이미지를 로드하도록 트리거를 일으킵니다. 전부 로드되면 lazy 클래스명을 이미지에서 삭제하고 부착했던 옵저버를 제거합니다.

     

    See the Pen Lazy loading images using IntersectionObserver - example code by ImageKit.io (@imagekit_io) on CodePen.

    이벤트 리스너Intersection Observer 이 두 방법에 대해 이미지 로딩 시간을 비교해보면, 후자가 이미지를 로드하는 트리거가 훨씬 빠르며 스크롤할 때 이미지가 느리게 나타나지 않는 것을 확인할 수 있습니다. 이벤트 리스너를 이용한 방식은 성능을 위해 timeout을 추가했었는데, 이 부분은 사용성 측면에서 이미지 로드에 약간의 딜레이가 발생하는 미미한 영향을 끼칩니다.

    그러나 Intersection Observer API는 아직 모든 브라우저가 지원되고 있지 않습니다. 그렇기에 해당 API가 지원되지 않는 브라우저에서는 event listener 방식으로 사용하도록 해야 합니다. (event listener 방식은 위에서 다루었습니다.)

     

    Native Lazy Loading 방식

    아주 최신의 Google Chrome 브라우저 버전(Chroem 76)에서는 native lazy loading을 지원합니다.

    해당 방식이 지원되면서, 개발자는 lazy loading을 구현하기 위해 임베딩 할 이미지에 'loading' 속성만 추가해주면 됩니다. 

    이를 구현하기 위해서 심지어 개발자가 필요할 정도도 아닙니다. 어느 정도 HTML 기초만 있으면 충분히 'loading' 속성을 추가할 수 있고, 해당 기능을 관리할 수 있는 사람을 더 많도록 합니다.

    해당 방식에 대한 코드를 보겠습니다.

    <img src="example.jpg" loading="lazy" alt="..." />
    <iframe src="example.html" loading="lazy"></iframe>

     

    아래는 loading 속성에 사용할 수 있는 값들입니다.

    • lazy - 뷰포트에서 일정한 거리에 닿을 때까지 로딩을 지연시킵니다.
    • eager - 현재 페이지 위치가 위, 아래 어디에 위치하던 상관없이, 페이지가 로딩되자마자 해당 요소를 로딩합니다. 
    • auto - 이 속성은 디폴트로 로딩을 지연하는 것을 트리거합니다. 기본적으로 이것은 loading 속성을 쓰지 않을 것과 같습니다.

    하지만, native lazy loading을 지원하지 않는 브라우저의 경우, 위에서 설명했던 다른 방식을 이용해야 합니다.

    Update (source: web.dev)

    로딩 지연된 이미지들이 다운로드될 때 다른 감싸고 있는 콘텐트 내용들이 밀려나는 것을 방지하려면, 반드시 heightwidth 속성을 <img>태그에 추가하거나 inline style로 직접 값을 지정해야 합니다.

    <img src="…" loading="lazy" alt="…" width="200" height="200">
    <img src="…" loading="lazy" alt="…" style="height:200px; width:200px;">
    Source: Web.dev - https://web.dev/native-lazy-loading/#load-in-distance-threshold

     

    CSS 속성 중 Background Image를 Lazy Loading 하는 방법

    background image는 <img> 태그 다음으로 웹 페이지에서 가장 많이 쓰이는 이미지 로딩 방식입니다. <img>태그의 경우, 브라우저가 이미지 URL이 사용 가능할 때 로딩하도록 하는 것은 매우 간단했습니다.

    그러나 CSS background 이미지는 이 처럼 간단하지 않습니다. CSS background image를 로드하기 위해서는 현재 문서 내 DOM 노드에 CSS 스타일이 적용되는지 여부를 결정하기 위해 CSSOM(CSS Object Model)과 DOM(Document Object Model) Tree를 구성하는 것이 필요합니다. 

    만약 문서 내 엘리먼트에 CSS의 background image가 적용되어 있지 않다면, 브라우저는 background image를 로드하지 않고, 엘리먼트에 CSS 규칙에 적용될 경우 브라우저가 이미지를 로딩할 것입니다.

    이것은 보기엔 구현하기 어려워 보이지만, 기본적으로 구현하는 방식은 똑같습니다. 간단히 말하면 엘리먼트가 뷰포트에 들어올 때까지 CSS background image 속성을 적용하지 않도록 하면 됩니다.

    아래는 해당 방식에 대한 구현 예시입니다.

    See the Pen Lazy Loading background images in CSS by ImageKit.io (@imagekit_io) on CodePen.

     

    위 예시에서 주목할 점은 lazy loading 관련해서 구현한 자바스크립트 코드가 똑같다는 것입니다. 이벤트 리스너와 Intersection Observer API를 함께 이용해서 구현되어 있습니다. 트릭은 CSS 부분에 있습니다. 

    ID bg-image를 가진 엘리먼트는 지정된 background-image를 가집니다. lazy라는 클래스를 엘리먼트에 추가하게 되면, 해당 엘리먼트는 background-image 속성을 none으로 변경됩니다.

    #bg-image.lazy class를 같이 적용하면 #bg-image만 쓴 것보다 더 높은 성능이 나타나므로, 브라우저는 초기에 엘리먼트에게 background-image: none 속성을 적용합니다. 스크롤을 아래로 내릴 때, Intersection Observer(또는 이벤트 리스너)는 이미지가 뷰포트에 들어오는 것을 감지하고 엘리먼트의 lazy 클래스를 삭제함으로써, 엘리먼트가 background image를 로드하도록 실제 background-image속성을 적용하게 됩니다. 

     

    lazy loading 기법으로 유저 인터페이스 향상시키는 방법

    Lazy loading은 뛰어난 성능이라는 장점이 있습니다. 페이지 내에서 몇 백개의 상품 이미지를 쓰는 E-커머스 기업의 경우, lazy loading 방식은 페이지의 초기 로딩에 엄청나게 성능을 향상시킬 수 있을 것입니다.

    하지만, 거의 대부분 기업에서는 초기 placeholder가 보기 좋지 않다던가, 로딩 시간이 느리다 와 같은 여러 가지 이유로 유저 사용성에 좋지 않다고 판단하여 lazy loading을 쓰지 않습니다.

    그렇다면 이러한 lazy loading에 대한 사용성 문제에 대해 어떻게 해결할 수 있을까요?

     

    1. 올바른 image placeholder를 이용한 방법

    placeholder는 실제 이미지가 로딩될 때까지 해당 이미지 자리에 대신 표시할 요소를 말합니다. 보통 개발자들은 이미지의 단색 이미지를 사용하거나 모든 이미지에다가 대체할 특정 이미지를 넣는 방식으로 구현합니다.

    이전 예시 코드로 동작하던 lazy code를 본다면, placeholder로 밝은 회색을 사용하고 있습니다. 그러나 이 부분을 유저 사용성에 더 좋게 만들 수 있습니다.

    그러면 아래에서 placeholder를 더 좋게 만드는 예시를 확인해봅시다.

     

    a) 주요 색상을 placeholder로 사용하기

    특정 색상을 placeholder로 사용하는 대신, 사용하려는 실제 이미지의 주요한 색상을 이용하는 방법이 있습니다.

    이 방식은 구글 이미지 검색 결과와 Pinterest에서 꽤 오래 사용되어 왔습니다.

    아래는 Manu.ninja에서 소개하고 있는 예시입니다.

    처음에는 이를 구현하기 어려워 보이겠지만, 단지 이미지의 첫 1x1 픽셀로 스케일을 감소 시키고 해당 픽셀 요소로 placeholder을 채우는 아주 간단한 방식입니다. 하지만 해당 이미지의 단일 색상을 추출하는 것은 약간 번거로울 수도 있습니다.

    ImageKit을 사용하면, 체인변환을 이용해서 주요 단일 색상을 얻을 수 있습니다. 아래에서 ImageKit에 대해 확인해봅시다.

    ImageKit을 이용한 이미지의 주요 단색의 URL을 얻는 예시

    <!-- Original image at 400x300 -->
    <img src="https://ik.imagekit.io/demo/img/image4.jpeg?tr=w-400,h-300" alt="original image" />
    
    <!-- Dominant colour image with same dimensions -->
    <img src="https://ik.imagekit.io/demo/img/image4.jpeg?tr=w-1,h-1:w-400,h-300" alt="dominant color placeholder" />

    placeholder 이미지는 단지 661 바이트의 용량을 가집니다. 원본 이미지의 12700바이트의 용량과 비교해서 약 19배 단축되었습니다. 뿐만 아니라 실제 이미지의 placeholder로부터 사용성 면으로 더욱 좋게 변했습니다.

    아래에서 이에 대한 예시를 확인해보세요 :

     

    위 샘플 영상에 대한 코드 샘플은 여기서 확인할 수 있습니다.

     

    b) 저화질의 이미지로 placeholder로 사용하기(LQIP)

    앞 단의 방식인 주요 색상 placeholder를 이용해서 더 좋은 방식으로 확장시킬 수 있을 것 같습니다.

    하나의 색상을 사용하는 대신, 원본 이미지에 대한 저화질의 흐린 이미지를 placeholder로 사용하는 것입니다. 이는 이미지가 로딩되는 동안 유저가 보기에 이전보다 더 보기 좋을 뿐 아니라 원본 이미지에 대해 어느정도 추측하도록 유도할 수 있습니다. 

    이 방식은 Facebook과 Medium.com 같은 웹 사이트와 어플리케이션에서 사용되어 왔습니다. 

    아래는 ImageKit을 이용해서 LQIP 이미지 URL을 적용한 예시 입니다.

    <!-- Original image at 400x300 -->
    <img src="https://ik.imagekit.io/demo/img/image4.jpeg?tr=w-400,h-300" alt="original image" />
    
    <!-- Low quality image placeholder with same dimensions -->
    <img src="https://ik.imagekit.io/demo/img/image4.jpeg?tr=w-400,h-300,bl-30,q-50" alt="dominant color placeholder" />

    LQIP(저화질 이미지)는 1300바이트의 크기를 가지므로, 원본 이미지에서 약 10배 정도 감소된 사이즈입니다. 그리고 다른 placeholder 기술보다 시각적인 면에서 더 좋은 사용성을 제공합니다.

    아래 비디오 예시에서 직접 유저에게 어떤 효과를 주는지 확인해보세요 :

     

    위 비디오 샘플이 동작하는 예시는 여기서 확인할 수 있습니다.

    앞서 본 주요 색상을 이용하는 방식, 저화질 이미지를 이용하는 방식은 비디오 샘플에서 본 것처럼, 유저가 placeholder를 봤을 때 로딩 중인 것을 인지시키면서 스무스하게 원본 이미지로 변환시킬 수 있는 것을 확인할 수 있었습니다.

     

    2. 이미지 로딩을 위한 버퍼 시간을 추가하는 방법

    앞서 이미지를 로딩하는 트리거에 대한 차이점을 논의할 때, 뷰포트의 하단 부분과 이미지의 상단 부분이 만나는 시점이 뷰포트에 들어오는 시점인 것을 확인할 수 있었습니다.

    문제점

    사용자가 페이지에서 종종 빠르게 스크롤하면 이미지가 로딩될 시간이 필요하단 것이 placeholder로 보여지게 되는 것입니다. 이것은 이미지를 로딩하는 스크롤 이벤트를 성능 이슈로 인해 쓰로틀링을 사용해서 딜레이가 약간 발생하는 것입니다. 이로인해 placeholder가 뷰포트에 오게되면 유저는 이미지가 로딩되는 약간의 시간을 기다리게 됩니다. 이러한 딜레이는 유저 사용성에서 좋지 않을 수 있습니다. 

    Intersection Observer 또는 저화질의 이미지를 이용한 방식으로 placeholder의 퍼포먼스를 더 좋게 만들면서도, 더 나아가 간단한 트릭으로 이미지가 뷰 포트에 들어올 때 완벽하게 이미지가 로딩하도록 할 수 있습니다. 그것은 바로 이미지의 로딩할 트리거 시점에 마진 값을 넣는 것입니다. 

    해결 방법

    이미지가 뷰포트에 완전히 들어올 때 로딩하는 대신, 뷰포트에 들어오는 부분에서 예시로 500px정도 떨어진 곳에 들어오면 로딩을 하는 것입니다. 이 방식은 실제로 이미지가 뷰포트에 들어왔을 때 완전히 로딩되어 보여지기 위해 미리 로딩 트리거 시점을 더 빨리 잡도록 하는 것입니다.

    Intersection Observer API에서는 'root'파라미터와 'rootMargin'파라미터(기본 CSS 마진 규칙에서 동작)를 함께 사용하여 'intersection'(이벤트가 발생되는 부분)을 찾는 위치를 증가시킬 수 있습니다.

    이벤트 리스너 방식에서는 이미지 위치와 뷰 포트 위치의 간격을 체크하는 대신에 어느 정도의 임계 값을 추가하는 방식을 이용할 수 있습니다.

    더 자세히 알고 싶다면 여기서 500px의 임계값을 이용한 예시를 확인해보세요.

    아래 비디오(특히 개발자 도구의 네트워크 요청 탭을 주목)에서 정확히 알 수 있듯이, 스크롤 하는 동안, 상단 3개의 이미지는 바로 보여질 때 5개의 이미지가 로딩이 됩니다. 또한 4개의 이미지가 보여졌을 때, 6개의 이미지가 로딩됩니다. 이 방법은 이미지가 완벽히 로딩되도록 충분히 시간을 가지게 합니다. 이로 인해 사용자는 거의 placeholder를 보지 않게 될 것입니다.

     

    모든 예시에서 보면, 상단 3개의 이미지는 뷰포트에 들어와 있지 않았어도 항상 미리 로드 되어있습니다. 이것은 더 나은 사용성을 위해 threshold에 완전히 로딩되는 대신 미리 약간 로딩하는 방식과 동일하게 사용됩니다.

     

    3. lazy loading으로 콘텐트 요소들이 이동하는 것을 방지하는 방법

    이것은 만약 해결된다면 유저 사용성을 조금 더 좋게 할 수 있는 아주 사소한 부분입니다.

    문제점

    이미지가 없을 때, 브라우저는 보여지고 있는 콘텐트의 공간을 알고있지 않습니다. 그래서 만약 CSS로 따로 지정해주지 않으면, 콘텐트를 감싸고 있던 컨테이너 부분은 공간을 따로 가지고 있지 않음으로 0x0 픽셀이 됩니다. 따라서 이미지가 로딩되면, 브라우저가 해당 이미지의 크기에 맞게 컨테이너를 다시 리사이징합니다.

    이러한 갑작스런 변경은 다른 엘리먼트 요소들이 이동되어 밀려나게 되는 원인으로 인해 일어나게 됩니다. 이 부분은 Smashing 매거진의 content shifting article & video 에서 정확히 알 수 있으며, 이는 이미지가 로딩될 때 갑작스런 콘텐트 이동으로 인해 꽤나 유저에게 좋지 않은 사용성을 주게 됩니다. 

    해결 방법

    콘텐트를 감싸고 있는 컨테이너에 너비/높이를 지정함으로써 이러한 문제를 피할 수 있습니다. 이로 인해 브라우저는 너비와 높이를 가지고 이미지 영역을 알 수 있습니다. 이후 이미지가 로딩되면 이미 이미지 사이즈 영역이 이미지 크기에 완벽히 맞게 지정되어 있으므로, 나머지 컨테이너 영역들은 그대로 유지됩니다.

     

    4. 모든 이미지에 lazy load를 적용하지 않기

    이것은 개발자들이 종종 실수하는 부분인데, 페이지 내 사용되는 모든 이미지에 lazy load를 하도록 구현합니다. 초기 로딩 시에는 로딩이 줄어들기는 하지만, 많은 이미지들로 인해 유저 사용성으로 좋지 않은 결과가 주어질 수도 있습니다. 특히나 웹 페이지 상단의 이미지는 자바스크립트가 적용되고 동작할 때까지 보여지지 않을 것입니다.

    이를 위해, 아래에는 lazy loading에 어울리는 이미지가 무엇인지 식별할 수 있는 일반적인 원칙입니다.

    a) 뷰포트에 있거나, 웹 페이지에서 시작되는 이미지들은 lazy loading을 하도록 하면 안됩니다. 페이지 상단 이미지나 마케팅 배너, 로고 등과 같은 이미지는 페이지가 로딩 되자마자 유저에게 보여져야 합니다.

    또한, 모바일과 데스크톱에는 화면 크기가 다르게 때문에, 초기에 화면에 보여지는 이미지 수가 다릅니다. 따라서 어떤 리소스들을 미리 로딩할 것인지 결정하기 위해 디바이스 타입을 고려할 필요가 있습니다.

    b) 뷰포트에서 살짝 떨어져 있는 이미지는 lazy loading할 이미지로 적합하지 않습니다. 이것은 앞 단에서 뷰포트에 완벽히 들어서기 전에 미리 로딩을 하는 부분을 다루던 내용에 기반한다면, 뷰포트 하단으로부터 500px 이내인 이미지들은 미리 로딩되어야 하는 것을 예시로 들 수 있습니다.

     

    c) 만약 페이지가 길지 않다면, 한, 두번 정도의 스크롤로 페이지를 내리거나 뷰포트 바깥에 이미지 개수가 5개 이하일 것입니다. 이럴 땐 lay loading을 전부 걸지 않는게 더 좋을 수 있습니다.

    성능 면으로 최종적으로 유저에게 중요한 장점을 제공하지 않을 수도 있습니다. lazy loading를 걸기위해 추가한 JS파일이 고작 몇 안되는 이미지 수의 lazy loading을 위해서 오히려 장점이 사라질 수도 있습니다.

     

    자바스크립트에 대한 Lazy Loading의 의존성

    이러한 lazy loading에 대한 방식들은 유저 브라우저 내에서 자바스크립트 동작에 의존되어 일어합니다.

    대부분 유저들이 브라우저 내 자바스크립트 코드가 요즘 거의 모든 웹 사이트에서 효과적으로 실행되는 동안, 자바스크립트가 지원되지 않는 브라우저를 사용한다거나, 자바스크립트 동작을 허용하지 않도록 한 유저들을 위해 계획을 세울 필요가 있을 것입니다.

    유저들에게 최신 브라우저를 이용, 또는 자바스크립트를 활성화 하라는 메시지나 혹은 왜 이미지가 로딩되지 않는지 알려주어야 할 것입니다. 아니면 noscript 태그를 이용해서 유저들에게 좋은 사용성을 제공하도록 할 수도 있습니다. 그러나 <noscript>태그를 이용한 방식은 몇가지 문제점을 가지고 있습니다.

    여기에 이에 대한 좋은 해결방법이 있습니다. 이에 대한 해결법을 찾는 사람들에게 추천 드립니다.

     

    lazy loading과 관련해 인기있는 자바스크리브 라이브러리 소개

    브라우저 환경과 상세하게 구현하는 것은 브라우저와 디바이스마다 다를 수 있으므로, lazy loading 기능 그리고 관련 테스트 라이브러리를 이용할 수 있습니다.

    아래는 이와 관련된 인기있는 라이브러리와 특정 플러그인입니다. 이것들은 최소한의 노력으로 lazy loading을 구현할 수 있습니다.

    yall.js (또 다른 Lazy Loader 구현 방법)

    • Intersection Observer 방식이며, 이벤트 기반으로 lazy loading을 되돌리는 방식.
    • 주요한 HTML 요소들은 모두 지원하지만 background-image는 안됨.
    • 게다가 브라우저 IE11도 지원됨.

    lazysizes

    • 엄청 인기있고 광범위한 기능
    • src 이미지 응답이 지원되고 속성 사이즈 지정 가능
    • Intersection Observer 없는 좋은 성능

    JQuery Lazy

    • jquery 기반 lazy loading을 구현할 수 있는 간단한 라이브러리

    WeltPixel Lazy Loading Enhanced

    • lazy loading을 위한 Magento 2 확장판

    Magento Lazy Image Loader

    • lazy loading을 위한 Magento 1.x 확장판

    Shopify Lazy Image Plugin

    • lazy loading을 위한 Shopify 확장판

    Wordpress A3 Lazy Load

    • Wordpress 전용 lazy loading 플러그인

     

    lazy loading을 테스트 하는 방법

    lazy loading을 구현했다면, 웹 사이트 내에서 이미지들이 의도한대로 동작하는지 확인하기를 원할 것입니다. 간단한 방법은 크롬 브라우저의 개발자 툴을 이용하는 것입니다.

    브라우저 내 네트워크 탭 -> 이미지를 확인하십시오.

    여기에서 처음으로 페이지를 새로고침 하면, 미리 로딩되었던 이미지들이 다시 새롭게 로딩이 될 것입니다. 그러면 페이지 내 스크롤을 아래로 내림으로써, 다른 이미지들이 로드 요청 트리거가 일어나면서 이미지가 로딩될 것입니다.

    화면 내 waterfall column에서 이미지의 로딩 타이밍도 알 수 있습니다. 이것은 이미지 로딩 트리거 관련 이슈사항이 있을 경우, 각 이미지 로딩에 대해 식별하는 것에 도움을 줄 것입니다.

     

    마치며

    이 글에서 거의 lazy loading 관련된 모든 것을 다루었습니다. 만약 이에 대해 올바르게 구현한다면 여러분들의 웹 페이지에 불필요하게 미리 리소스 로딩되는 것을 제거하여 리소스 비용을 줄임으로써 로딩 성능을 엄청나게 증가시킬 것입니다. 이는 실제로 초기 로딩에 필요로 한 리소스를 보유할 수 있습니다. 빠른 로딩은 유저 사용성에 매우 좋을 것이고 여러분들의 웹 사이트 방문자들에게 매력적으로 적용될 것입니다.

    그래서, 무엇을 기다리시나요? 지금 당장 lazy loading 방식을 구현하러 갑시다!

    웹 사이트에 이미지를 최적화 하고 계신가요? 아닌가요? 지금 당장 ImageKit's image CDN무료 최적화 툴을 이용해 봅시다!

     

    원본 출처

     

    Lazy Loading Images – The Complete Guide

    Lazy loading images that are not in the viewport improves initial page load performance and user experience. This is an in-depth guide to everything about lazy loading of images.

    imagekit.io

     

    반응형

    댓글

Designed by Tistory.