π₯οΈ μ΅κ·Ό νμ¬μμ κ°λ°νλ κΈ°λ₯ μ€ μμμ κ°μμ±μ λ°λΌ API λ₯Ό νΈμΆν΄μΌνλ μμ μ΄ μμμ΅λλ€.
κΈ°μ‘΄μλ νμ΄μ§μ μ§μ νλ μκ° κ΄λ ¨ APIλ₯Ό λͺ¨λ νΈμΆνμ¬ νλ©΄μ κ·Έλ €μ£Όλ λ°©μμΌλ‘ ꡬνμ΄ λμ΄μμλλ°μ,
ν΄μλλ μ μ μ μΈν μνμ λ°λΌ 보μ΄μ§ μλ κΈ°λ₯μ APIκΉμ§ μ λΆ νΈμΆνλ λΆλΆμ΄ λΉν¨μ¨μ μ΄λΌκ³ νλ¨λμ΄, μΌλ°μ μΌλ‘λ μ΄λ―Έμ§λ₯Ό Lazy loading νλλ°μ μ£Όλ‘ μ°μ΄λ Intersection Observer API λ₯Ό νμ©νμ¬ μλ²λ‘ νΈμΆνλ API μ체λ Lazy loading μ μλν΄λ³΄μκ³ , κ΄λ ¨ λ΄μ©μ 곡μ ν΄λ³΄λ €κ³ ν©λλ€.
Lazy loading μ΄λ?
Lazy loading μ 'μ§μ° λ‘λ©', μ¦ λ¦¬μμ€λ₯Ό μλ³νμ¬ νμν λλ§ λ‘λνλ μ λ΅μ
λλ€.
μΉμ΄ λ°μ ν¨μ λ°λΌ μ¬μ©μμκ² μ μ‘λλ assetsμ μμ ν¬κΈ°λ μμ²λκ² μ¦κ°νμ΅λλ€. μ΄ λ¬Έμ λ₯Ό ν΄κ²°νλ λ° μ¬μ©ν μ μλ λ°©λ² μ€ νλκ° λ λλ§μ΄ λ°μνλ λ° μ€μνμ§ μμ 리μμ€λ₯Ό μ§μ° λ‘λνμ¬, λ λλ§ κ²½λ‘ κΈΈμ΄λ₯Ό μ€μ΄λ κ²μ
λλ€.
μ§μ° λ‘λ©μ μ ν리μΌμ΄μ
μμ μ¬λ¬ μκ°μ λ°μν μ μμ§λ§ μΌλ°μ μΌλ‘ μ€ν¬λ‘€ λ° νμκ³Ό κ°μ μΌλΆ μ¬μ©μ μνΈ μμ©μμ λ°μν©λλ€.

κ°μ₯ μΌλ°μ μΌλ‘ μ°μ΄λ μμλ μΌνλͺ°μ΄λ λΈλ‘κ·Έ λ± νμλΌμΈ ννλ‘ λ§μ μ΄λ―Έμ§μ ν¨κ» λλλ§λλ μλΉμ€μΈ κ²½μ°μ μ΄λ―Έμ§μ μ§μ°λ‘λ© μ²λ¦¬λ₯Ό νμ¬ κ²½μ°κ° λ§μ΅λλ€. κΈ°λ³Έμ μΌλ‘ CSSλ λ λλ§ μ°¨λ¨ λ¦¬μμ€λ‘ μ·¨κΈλκΈ° λλ¬Έμ λΈλΌμ°μ λ CSSOMμ΄ κ΅¬μ±λ λκΉμ§ μ²λ¦¬λ μ½ν
μΈ λ₯Ό λ λλ§νμ§ μμ΅λλ€. λ°λΌμ CSSλ κ°λ₯ν ν 빨리 μ λ¬λμ΄μΌ ν©λλ€. λ°λΌμ λΈλΌμ°μ κ° DOM λ° CSSOMμ μλ£νκ³ , λ λλ§ νΈλ¦¬λ₯Ό ꡬμΆνκ³ , νμλλ λͺ¨λ μ½ν
μΈ μ μ€νμΌμ κ³μ°νκ³ , λͺ¨λ λ λ νΈλ¦¬ μμμ μμΉμ ν¬κΈ°λ₯Ό μ μνκΈ°κΉμ§μ κ³Όμ μμ λΆνμν 컨ν
μΈ μ λ‘λ©μ μ΅μ ν νκΈ° μν΄μ μ§μ° λ‘λ©μ κ°λ
μ΄ νμν κ²μ΄μ£ .
<img src="image.jpg" alt="..." loading="lazy" />
<iframe src="video-player.html" title="..." loading="lazy"></iframe>
μ¬μ€ μ΄λ²μ μ μ κ²½μ°μ λΈλΌμ°μ λ‘λ©μ μ΅μ ννκΈ° μν λͺ©μ μΌλ‘ μ§μ° λ‘λ©μ μ¬μ©ν κ²μ μλλλ€. λΈλΌμ°μ μ κ·Έλ €μ§λ μ½ν
μΈ λ₯Ό μ΅μ ννκΈ° μν΄ 'νμν 리μμ€λ§ λ λλ§νλ€' λ μ κ°λ
μμ μΈμ¬μ΄νΈλ₯Ό μ»μ΄, '보μ΄μ§ μλ μλ§μ κ°λ€μ νλ²μ λΆλ¬μ€λ건 λΉν¨μ¨μ μ΄λ, νλ©΄μ κ·Έλ €μ§λ λΆλΆλ§ API νΈμΆμ λ¨Όμ νλ©΄ λμ§ μμκΉ?' λΌλ μκ°μ νκ² λμκ³ , Lazy loading μ μν΄ μ°μ΄λ λ°©λ² μ€ μ μ μΌμ΄μ€μ λμ
ν΄λ³΄κΈ°μ μ ν©νλ€κ³ νλ¨λ Intersection Observer API λ₯Ό νμ©νκ² λ κ²½μ°μ΄μ£ . 보νΈμ μΌλ‘ μκ°λλ 'μ΄λ―Έμ§λ₯Ό μ§μ°λ‘λ©νλ κ²½μ°'κ° μλλλΌλ Intersection Observer λ₯Ό λ€μνκ² νμ©ν μ μλ€λ κ²μ μκ°νλ μ λμ κΈλ‘ μ΄ν΄ν΄μ£Όμλ©΄ μ’μ κ² κ°μ΅λλ€.
Intersection Observer API λ?
Intersection Observer APIλ νκ² μμμ μμ μμ λλ μ΅μμ document μ viewport μ¬μ΄μ intersection λ΄μ λ³νλ₯Ό λΉλκΈ°μ μΌλ‘ κ΄μ°°νλ λ°©λ²μ
λλ€. 곡μλ¬Έμμμ μκ°νλ νμ© μΌμ΄μ€λ μλμ κ°μ΅λλ€. μ μ κ²½μ°λ λ€λ²μ§Έμ ν΄λΉμ΄ λκ² λ€μ.
- νμ΄μ§κ° μ€ν¬λ‘€ λλ λμ€μ λ°μνλ μ΄λ―Έμ§λ λ€λ₯Έ 컨ν μΈ μ μ§μ° λ‘λ©.
- μ€ν¬λ‘€ μμ, λ λ§μ 컨ν μΈ κ° λ‘λ λ° λ λλ§λμ΄ μ¬μ©μκ° νμ΄μ§λ₯Ό μ΄λνμ§ μμλ λκ² νλ infinite-scroll μ ꡬν.
- κ΄κ³ μμ΅μ κ³μ°νκΈ° μν μ©λλ‘ κ΄κ³ μ κ°μμ± λ³΄κ³ .
- μ¬μ©μμκ² κ²°κ³Όκ° νμλλ μ¬λΆμ λ°λΌ μμ μ΄λ μ λλ©μ΄μ μ μνν μ§ μ¬λΆλ₯Ό κ²°μ .

κ³Όκ±°μ intersection κ°μ§λ₯Ό ꡬννλ©΄ μν₯μ λ°λ λͺ¨λ μμλ₯Ό μκΈ° μν΄μ Element.getBoundingClientRect()μ κ°μ λ©μλλ₯Ό νΈμΆνλ μ¬λ¬ μ΄λ²€νΈ νΈλ€λ¬μ 루νκ° μ½νμμμ΅λλ€. νλ©΄μ ν¬κΈ°λ₯Ό λ¨Όμ κ³μ°νκ³ , μμμ μμΉλ₯Ό κ³μ°νλ λ±μ λͺ¨λ μ½λκ° λ©μΈ μ€λ λμμ μ€νλκΈ° λλ¬Έμ, μ΄ μ€ νλλΌλ μ±λ₯ λ¬Έμ λ₯Ό μΌμΌν¬ μ μκ³ μ΄λ¬ν κ³μ° λ‘μ§λ€κ³Ό ν¨κ» νμ΄μ§κ° λ‘λλλ©΄ μν©μ΄ λμ± λλΉ μ§ μ μμμ΅λλ€.
νμ§λ§ Intersection Observer API λ κ°μνκ³ μ νλ μμκ° λ€λ₯Έ μμ(viewport)μ λ€μ΄κ°κ±°λ λκ°λ λλ μμ²ν λΆλΆλ§νΌ λ μμμ κ΅μ°¨λΆλΆμ΄ λ³κ²½λ λ λ§λ€ μ€νλ μ½λ°± ν¨μλ₯Ό λ±λ‘ν μ μμ΅λλ€. μ¦, μμμ κ΅μ°¨λ₯Ό μ§μΌλ³΄κΈ° μν΄ λ©μΈ μ€λ λλ₯Ό μ¬μ©ν νμκ° μμ΄μ§κ³ , λΈλΌμ°μ λ μνλ λλ‘ κ΅μ°¨ μμ κ΄λ¦¬λ₯Ό μ΅μ ν ν μ μμ΅λλ€. μμ§κΉμ§λ μ νν λͺ ν½μ μ΄ κ²Ήμ³μ‘κ³ μ΄λ ν ν½μ μ΄ κ²Ήμ³μ‘λμ§λ μ μκ° μμ§λ§, "N% μ λ κ΅μ°¨νλ κ²½μ° μνΈμμ©μ΄ μ΄λ£¨μ΄μ ΈμΌνλ€." μ κ°μ κ²½μ°μ μ¬μ©μ΄ κ°λ₯ν©λλ€.
νμ© λ°©λ²
1. Observer μμ±
let options = {
root: document.querySelector('#κ΄μ°°μμλ₯Όν¬ν¨νμμ'),
rootMargin: '0px',
threshold: 0.7
}
let observer = new IntersectionObserver(callback, options);
1) root
λμ κ°μ²΄μ κ°μμ±μ νμΈν λ μ¬μ©λλ λ·°ν¬νΈ μμμ
λλ€. μ΄λ κ΄μ°°νκ³ μνλ λμ κ°μ²΄μ μ‘°μ μμμ¬μΌ ν©λλ€. κΈ°λ³Έκ°μ λΈλΌμ°μ λ·°ν¬νΈμ΄λ©°, root κ°μ΄ null μ΄κ±°λ μ§μ λμ§ μμ λ κΈ°λ³Έκ°μΌλ‘ μ€μ λ©λλ€.
2) rootMargin
root κ° κ°μ§ μ¬λ°±μΌλ‘, CSSμ margin μμ±κ³Ό μ μ¬ν©λλ€. κΈ°λ³Έκ°μ 0μ
λλ€.
3) threshold
observerμ μ½λ°±μ΄ μ€νλ λμ μμμ κ°μμ± νΌμΌν°μ§λ₯Ό λνλ΄λ λ¨μΌ μ«μ νΉμ μ«μ λ°°μ΄μ λλ€. λ§μΌ 50%λ§νΌ μμκ° λ³΄μ¬μ‘μ λλ₯Ό νμ§νκ³ μΆλ€λ©΄, κ°μ 0.5λ‘ μ€μ νλ©΄ λ©λλ€. νΉμ 25% λ¨μλ‘ μμμ κ°μμ±μ΄ λ³κ²½λ λλ§λ€ μ½λ°±μ΄ μ€νλκ² νκ³ μΆλ€λ©΄ [0, 0.25, 0.5, 0.75, 1] κ³Ό κ°μ λ°°μ΄μ μ€μ ν μλ μμ΅λλ€. κΈ°λ³Έκ°μ 0μ΄κ³ , 0μΌλ‘ μ€μ νλ κ²½μ°λ λμ μμκ° 1ν½μ μ΄λΌλ 보μ΄λ©΄ λ°λ‘ μ½λ°±μ΄ μ€νλ¨μ μλ―Έν©λλ€. κ·Έλ¦¬κ³ λ°λλ‘ 1.0μ μμμ λͺ¨λ ν½μ μ΄ νλ©΄μ λ ΈμΆλκΈ° μ μλ μ½λ°±μ μ€νμν€μ§ μμμ μλ―Έν©λλ€.

2. κ΄μ°°ν μμ νκ²ν
let target = document.querySelector('#κ΄μ°°ν μμ');
observer.observe(target);
3. callback
μ΄μ λ κ΄μ°°ν μμκ° 1λ²μμ μ§μ ν μ΅μ μ μκ³κ°μ μΆ©μ‘±ν λλ§λ€ μ½λ°±μ΄ νΈμΆλ©λλ€.
callback(entries, observer) {
entries.forEach(entry => {
// κ΄μ°°λλ μμλ€μ΄ entries λ‘ λ€μ΄μ€κ³ , entry λ‘ κ°κ°μ μμμ κ°μ νμΈν μ μμ΅λλ€.
// target element:
// entry.boundingClientRect
// entry.intersectionRatio
// entry.intersectionRect
// entry.isIntersecting
// entry.rootBounds
// entry.target
// entry.time
// κ·Έλ¦¬κ³ μ°λ¦¬λ μλμ ννλ‘ μ½λ°±μ νμ©ν μ μλ κ²μ
λλ€.
if (entry.intersectionRatio >= 0.75) { // κ΄μ°° λμμ΄ viewport μμ λ€μ΄μ¨ κ²½μ°
this.isIntersecting = true;
console.log('μ΄μ 75% λμ 보μ΄λκΉ ν μΌμ ν΄λΌ.')
this.action();
} else if (!entry.isIntersecting) { // κ΄μ°° λμμ κ΅μ°¨ μνκ° false μΌ (보μ΄μ§ μλ) κ²½μ°
this.isIntersecting = false;
}
});
};
νμ¬μ μ½λλ₯Ό κ°μ Έμ¬ μλ μμ΄ μ½λ°±μ λΆλΆμ ꡬ쑰λ₯Ό κ°μ Έμ보μμ΅λλ€.
μ μ κ²½μ°μ ν΄λμ€νμΌλ‘ ꡬνλ μ»΄ν¬λνΈμ μ μ½λ°± ν¨μλ₯Ό λ£μ΄λκ³ , μ»΄ν¬λνΈκ° λ§λ€μ΄μ§λ μκ° ν΄λΉ ν¨μλ₯Ό μ½λ°±μΌλ‘ λ±λ‘ν μ΅μ λ²λ₯Ό μμ±μμΌ°μ΅λλ€. κ·Έλ¦¬κ³ ν΄λΉ μ»΄ν¬λνΈκ° 75νΌμΌνΈ μ΄μ λ·°ν¬νΈμ λ€μ΄μ€λ©΄ action ν¨μλ₯Ό νΈμΆνλ ννλ‘ κ΅¬νμ νκ³ , μ€λ³΅μ€νμ λ°©μ§νκΈ° μν νλκ·Έ κ°μΌλ‘ isIntersecting λ₯Ό μ€μ νμ¬ action ν¨μκ° μ€λ³΅μ€νλμ§ μλλ‘ κ΅¬ννμ΅λλ€. μ°Έ μ½μ£ !!?
λ§μΉλ©°
νλ‘ νΈμλ μ±λ₯ μ΅μ νλ₯Ό μν΄ Intersection Observer λ₯Ό νμ©νλ λ°©λ²μ μκ°ν΄ 보μμ΅λλ€.
μ€μ λ‘ ν΄μλμ λ°λΌ 보μ΄λ μμλ§ κ³¨λΌ API λ₯Ό νΈμΆνλλ‘ μ΅μ’
ꡬνλ λͺ¨μ΅μ μ΄ν΄λ₯Ό μν΄ μμλ‘ λ£κ³ μΆμμ§λ§, μμ§ μλΉμ€μμ μ 체 μ μ μκ² μ€νλ κΈ°λ₯μ΄ μλλΌ μμ½κ²λ λ£μ§ λͺ»νμ΅λλ€. μΆν ν΄λΉ κΈ°λ₯μ΄ μ±κ³΅μ μΌλ‘ μ€νλλ©΄ μ΄λ€ ννλ‘ μ΄μνκ²½μμ λμμ€μΈμ§, νΉμλΌλ μ API λ₯Ό νμ
μμ νμ©ν λ λ κ³ λ €ν μ μλ λΆλΆμ μλμ§μ λν λ΄μ©μΌλ‘ 보μν΄μ λμμ€κ² μ΅λλ€. κ°μ¬ν©λλ€.
(μ λ΄μ©μμ λΆμ‘±ν λΆλΆμ λ°κ²¬νκ±°λ μΆκ° μ견 νΉμ κ²½νμ΄ μμΌμλ€λ©΄, μΈμ λ μ§ λκΈ λνμμ
λλ€ ππ»)
'Dev Note > JavaScript' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
ν¬λ‘¬ κ°λ°μλꡬ λ―μ΄λ³΄κΈ° (1) | 2023.04.23 |
---|