๐ Image Lazy Loading์ด๋?
ํ์ด์ง ์์ ์๋ ์ค์ ์ด๋ฏธ์ง๋ค์ด ํ๋ฉด์ ๋ณด์ฌ์ง ํ์๊ฐ ์์ ๋ ๋ก๋ฉ ํ ์ ์๋๋ก ์ง์ฐ์ํค๋ ๊ฒ
- ๋๋ฐ์ด์ค ๋ด ๋ฆฌ์์ค ํ์ฉ๋ ์ฆ๊ฐ
- ์น ์ฑ๋ฅ ์ต์ ํ
- EX. SPA(Sing Page Application) ๋ด์์ ๋ฐ๋ก ๋ณด์ฌ์ง ํ์๊ฐ ์๋ ์ด๋ฏธ์ง๋ฅผ ์ง์ฐ ๋ก๋ฉ
โ ๋ฐฉ์
1. ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ด์ฉํด image load๋ฅผ ํธ๋ฆฌ๊ฑฐํ๊ธฐ
HTML
<img src="https://ik.imagekit.io/demo/img/image1.jpeg?tr=w-400,h-300" />
<img src="https://ik.imagekit.io/demo/img/image2.jpeg?tr=w-400,h-300" />
<img src="https://ik.imagekit.io/demo/img/image3.jpg?tr=w-400,h-300" />
<img class="lazy" data-src="https://ik.imagekit.io/demo/img/image4.jpeg?tr=w-400,h-300" />
<img class="lazy" data-src="https://ik.imagekit.io/demo/img/image5.jpeg?tr=w-400,h-300" />
<img class="lazy" data-src="https://ik.imagekit.io/demo/img/image6.jpeg?tr=w-400,h-300" />
JS
document.addEventListener("DOMContentLoaded", function() {
var lazyloadImages = document.querySelectorAll("img.lazy");
var lazyloadThrottleTimeout;
function lazyload () {
if(lazyloadThrottleTimeout) {
clearTimeout(lazyloadThrottleTimeout);
}
lazyloadThrottleTimeout = setTimeout(function() {
var scrollTop = window.pageYOffset;
lazyloadImages.forEach(function(img) {
if(img.offsetTop < (window.innerHeight + scrollTop)) {
//์ฌ๊ธฐ ์ด๋ถ๋ถ์ด ๋ทฐํฌํธ์ ๋ณด์ผ ๋ src ๊ฐ ๋ฃ์ด์ฃผ๋ ๋ถ๋ถ
img.src = img.dataset.src;
img.classList.remove('lazy');
}
});
if(lazyloadImages.length == 0) {
document.removeEventListener("scroll", lazyload);
window.removeEventListener("resize", lazyload);
window.removeEventListener("orientationChange", lazyload);
}
}, 20);
}
document.addEventListener("scroll", lazyload);
window.addEventListener("resize", lazyload);
window.addEventListener("orientationChange", lazyload);
});
2. Intersection Observer API
- Intersection Observer๋ ๋น๊ต์ ์ต๊ทผ์ ๋์จ API๋ก ์๋ฆฌ๋จผํธ ์์๊ฐ ๋ทฐํฌํธ์ ๋ค์ด๊ฐ๋ ๊ฒ์ ๊ฐ์งํ๊ณ ์ก์ ์ ์ทจํ๋ ๊ฒ์ ๊ฐ๋จํ๊ฒ ๋ง๋ค์ด์ค(๋์ ์ฐ์ฐํด์ค)
- ๋ธ๋ผ์ฐ์ ํธํ์ฑ ํ์ธ ํ ์ฌ์ฉ
JS
document.addEventListener("DOMContentLoaded", function() {
var lazyloadImages;
if ("IntersectionObserver" in window) {
lazyloadImages = document.querySelectorAll(".lazy");
//Observer ์ฌ์ฉ
var imageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
//intersecting์ด๋ ๋์ ์๋ฆฌ๋จผํธ๊ฐ ๋ฃจํธ(๋ํดํธ๋ ์๋ง ๋ทฐํฌํธ)์ ๊ต์ฐจํ ๋ true๊ฐ
if (entry.isIntersecting) {
var image = entry.target;
image.src = image.dataset.src;
image.classList.remove("lazy");
imageObserver.unobserve(image);
}
});
});
lazyloadImages.forEach(function(image) {
imageObserver.observe(image);
});
} else {
var lazyloadThrottleTimeout;
lazyloadImages = document.querySelectorAll(".lazy");
function lazyload () {
if(lazyloadThrottleTimeout) {
clearTimeout(lazyloadThrottleTimeout);
}
lazyloadThrottleTimeout = setTimeout(function() {
var scrollTop = window.pageYOffset;
lazyloadImages.forEach(function(img) {
if(img.offsetTop < (window.innerHeight + scrollTop)) {
img.src = img.dataset.src;
img.classList.remove('lazy');
}
});
if(lazyloadImages.length == 0) {
document.removeEventListener("scroll", lazyload);
window.removeEventListener("resize", lazyload);
window.removeEventListener("orientationChange", lazyload);
}
}, 20);
}
document.addEventListener("scroll", lazyload);
window.addEventListener("resize", lazyload);
window.addEventListener("orientationChange", lazyload);
}
})
3. Native Lazy Loading
- chrome 76์์ ์ง์
- ์ด๋ฏธ์ง์ loading="lazy"๋ง ์ถ๊ฐ
- ์ง์ฐ ๋ก๋ฉ ๋ ๋ ์๋ฆฌ ์ฐจ์ง์ ๋ณ๊ฒฝ์ผ๋ก ์ธํ ํ ์ฝํ ์ธ ์ ๋ด์ฉ ๋ฐ๋ ค๋จ ๋ฐฉ์ง๋ฅผ ์ํด ๊ณต๊ฐ ํฌ๊ธฐ ๋ถ์ฌ ๊ผญ ํด์ค์ผํจ
- ํ ๋ธ๋ผ์ฐ์ ํธํ๋์ง ์๋ ๋ฌธ์ ์์(์์ ์ฌ์ดํธ : https://www.joongang.co.kr/society)
HTML
<img src="…" loading="lazy" alt="…" width="200" height="200">
4. CSS ์์ฑ ์ค background image ์ฌ์ฉ
HTML
<div id="container">
<h3>Lazy loading CSS background images</h3>
<p>์์ฒญ ๊ธด ๋ก๋ ์
์จ</p>
<p>์์ฒญ ๊ธด ๋ก๋ ์
์จ</p>
<div id="bg-image" class="lazy"></div>
<p>
๋ก๋ ์
์จ
</p>
</div>
CSS
#bg-image.lazy {
background-image: none;
background-color: #F1F1FA;
}
#bg-image {
background-image: url("https://ik.imagekit.io/demo/img/image10.jpeg?tr=w-600,h-400");
max-width: 600px;
height: 400px;
}
JS๋ ์ต์ ๋ฒ์ ๊ฐ์
5. React.lazy
import React, { lazy } from 'react';
const LazyComponent = lazy(() => import('./LazyComponent'));
const CommonComponent = () => (
<div>
<LazyComponent />
</div>
)
6. ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- yall.js
- lazysizes
โ ์ฃผ์ํ ์
- ์นํ์ด์ง ์๋จ์ ์ด๋ฏธ์ง๋ lazy loading ํ์ง ์์
- ์ด๋ฏธ์ง๊ฐ ๋ทฐํฌํธ์ ์์ ํ ๋ค์ด์ฌ ๋ ๊ฐ ์๋, ๋ง์ง ๊ฐ์ ์ฃผ์ด์ ์ฌ์ฉ์๊ฐ ๋ณผ ๋๋ณด๋ค ๋ก๋ฉ ํธ๋ฆฌ๊ฑฐ ์์ ์ ์ด์ง ๋ ๋นจ๋ฆฌ ์ก์์ placeholder๋ฅผ ๋ณด์ฌ์ฃผ์ง ์๋๋ก ํ๊ธฐ
- placeholder๋ฅผ ์ฐ๋๋ผ๋, ๊ธฐ๋ณธ ์ด๋ฏธ์ง์ ์์์ ์ถ์ถํด์ ๋น์ทํ ์์์ placeholder ๋๋ ์ ํ์ง์ placeholder๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง ์ฉ๋ ์ค์ด๋ฉด์ ux ๋์ด๊ธฐ
์ฐธ๊ณ
'CS ๊ณต๋ถ - front' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[์น] Google AMP (1) | 2023.04.06 |
---|---|
[์น] ๊ฒ์์์ง์ต์ ํ, SEO (0) | 2023.03.09 |
[๋ฆฌ์กํธ] flux ํจํด๊ณผ, ๋ฏธ๋ค์จ์ด ์ข ๋ฅ ๋ฐ ์ฅ๋จ์ (0) | 2023.02.23 |
[JS] ๊น์๋ณต์ฌ vs ์์๋ณต์ฌ (0) | 2023.02.15 |
[React] ๊ฐ์๋ (0) | 2023.02.15 |