5 . ๐ Intersection Observer
๋ฅ์คํธ๋ก ๋ง๋ ํ๋ก์ ํธ์์ ์คํฌ๋กค๊ฐ์ ๋ฐ๋ผ์ ํด๋๊ฐ๋ค๋ฅด๊ฒ ๋ค๋ฅด๊ฒ ๊ตฌํํ๋๋ฐ ์คํฌ๋กค ์ด๋ฒคํธ์ ๋ํด์ ์ซ ๊ณต๋ถํด๋ณผ ํ์๊ฐ ์๋ ๊ฒ ๊ฐ์์ intersection Observer์ ๋ํด์ ๊ณต๋ถํด๋ณด๋ ค๊ณ ํ๋ค.
โจ Intersection Observer
โ Intersection Observer๋
- Intersection observer๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ธ๋ผ์ฐ์ ๋ทฐํฌํธ(Viewport)์ ์ค์ ํ ์์(Element)์ ๊ต์ฐจ์ ์ ๊ด์ฐฐํ๋ฉฐ, ์์๊ฐ ๋ทฐํฌํธ์ ํฌํจ๋๋์ง ํฌํจ๋์ง ์๋์ง, ๋ ์ฝ๊ฒ๋ ์ฌ์ฉ์ ํ๋ฉด์ ์ง๊ธ ๋ณด์ด๋ ์์์ธ์ง ์๋์ง๋ฅผ ๊ตฌ๋ณํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
- ์ด ๊ธฐ๋ฅ์ ๋น๋๊ธฐ์ ์ผ๋ก ์คํ๋๋ฉฐ, scroll ๊ฐ์ ์ด๋ฒคํธ ๊ธฐ๋ฐ์ ์์ ๊ด์ฐฐ์์ ๋ฐ์ํ๋ ๋ ๋๋ง ์ฑ๋ฅ์ด๋ ์ด๋ฒคํธ ์ฐ์ ํธ์ถ ๊ฐ์ ๋ฌธ์ ์์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
โผ Intersection Observer ์ฌ์ฉ์ด์
-
์ฌ์ฉ์ด์ ๋ฅผ ์ดํด๋ณด๊ธฐ ์ Intersection์ด๋ผ๋ ์๋ฏธ์ ๋ํด์ ์์๋ณผ ํ์๊ฐ ์๋ค. Intersection์ด๋ ๊ต์ฐจ์ ,๊ต์งํฉ์ด๋ผ๋ ์๋ฏธ๋ฅผ ๊ฐ๊ณ ์๋ค.
-
intersection observer๋ ๊ต์ฐจ์ ์ ๊ด์ธกํ๊ธฐ ์ํด์ ์ฌ์ฉํ๋ API๋ผ๋ ์๋ฏธ๋ฅผ ๊ฐ๊ณ ์๋๊ฒ์ ์ ์ ์๋ค.
์ฆ, Target Element ๊ฐ ํ๋ฉด์ ๋
ธ์ถ๋์๋ ์ง ์ฌ๋ถ๋ฅผ ๊ฐ๋จํ๊ฒ ๊ตฌ๋
ํ ์ ์๋ API ์ด๋ค.
์๋ฅผ ๋ค์ด, intersection observer๊ฐ ์์ด ๊ตฌํํ๋ค๊ณ ํ๋ค๋ฉด, scroll์ด ์ผ์ด๋ ๋ ๋ง๋ค, ํน์ element๊ฐ ํ๋ฉด์ ์กด์ฌํ๋์ง์ ๋ํ ์ฌ๋ถ๋ฅผ ๊ณ์ ๊ณ์ฐํ๋ code๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค. ํ์ง๋ง intersection์ ์ฌ์ฉํ๋ค๋ฉด ์ฝ๊ฒ ์ฌ์ฉ์ฌ๋ถ๋ฅผ ํ์ธ ํ ์ ์๋ค.
โผ MDN์์ ์ ์ํ ์ ์ฉ ์ํฉ๋ค
1. ํ์ด์ง ์คํฌ๋กค ์ ์ด๋ฏธ์ง๋ฅผ Lazy Loadingํ ๋
2. Infinite scrolling์ ํตํด ์คํฌ๋กค์ ํ๋ฉฐ ์๋ก์ด ์ฝํ
์ธ ๋ฅผ ๋ถ๋ฌ์ฌ ๋
3. ๊ด๊ณ ์ ์์ต์ ๊ณ์ฐํ๊ธฐ ์ํด ๊ด๊ณ ์ ๊ฐ์์ฑ์ ์ฐธ๊ณ ํ ๋
4. ์ฌ์ฉ์๊ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ๊ฒ์ธ์ง์ ๋ฐ๋ผ ์ ๋๋ฉ์ด์
๋์ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ ๋
- Lazy Loading์ด๋?
- ํ์ด์ง๋ฅผ ๋ถ๋ฌ์ค๋ ์์ ์ ๋น์ฅ ํ์ํ์ง ์์ ๋ฆฌ์์ค๋ค์ ์ถํ์ ๋ก๋ฉํ๊ฒ ํ๋ ๊ธฐ์ . ์ฆ, ์ฌ์ฉ์๊ฐ ๋ณด์ง ์์๋๋ ๋น์ฅ ๋ก๋ฉํ์ง ์๊ณ , ๋์ค์ ์ฌ์ฉ์๊ฐ ํ์๋ก ํ๋ ์์ ์ ๋ก๋ฉํ๋ ๊ธฐ์
- infinite scrolling ๊ณผ placeholder๊ฐ Lazy Loading์ ์์
โผ Intersection Observer ์์ฑ, API
โ Intersection Observer๋
- Intersection observer๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ธ๋ผ์ฐ์ ๋ทฐํฌํธ(Viewport)์ ์ค์ ํ ์์(Element)์ ๊ต์ฐจ์ ์ ๊ด์ฐฐํ๋ฉฐ, ์์๊ฐ ๋ทฐํฌํธ์ ํฌํจ๋๋์ง ํฌํจ๋์ง ์๋์ง, ๋ ์ฝ๊ฒ๋ ์ฌ์ฉ์ ํ๋ฉด์ ์ง๊ธ ๋ณด์ด๋ ์์์ธ์ง ์๋์ง๋ฅผ ๊ตฌ๋ณํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
- ์ด ๊ธฐ๋ฅ์ ๋น๋๊ธฐ์ ์ผ๋ก ์คํ๋๋ฉฐ, scroll ๊ฐ์ ์ด๋ฒคํธ ๊ธฐ๋ฐ์ ์์ ๊ด์ฐฐ์์ ๋ฐ์ํ๋ ๋ ๋๋ง ์ฑ๋ฅ์ด๋ ์ด๋ฒคํธ ์ฐ์ ํธ์ถ ๊ฐ์ ๋ฌธ์ ์์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ฌ์ฉ์ด์ ๋ฅผ ์ดํด๋ณด๊ธฐ ์ Intersection์ด๋ผ๋ ์๋ฏธ์ ๋ํด์ ์์๋ณผ ํ์๊ฐ ์๋ค. Intersection์ด๋ ๊ต์ฐจ์ ,๊ต์งํฉ์ด๋ผ๋ ์๋ฏธ๋ฅผ ๊ฐ๊ณ ์๋ค.
intersection observer๋ ๊ต์ฐจ์ ์ ๊ด์ธกํ๊ธฐ ์ํด์ ์ฌ์ฉํ๋ API๋ผ๋ ์๋ฏธ๋ฅผ ๊ฐ๊ณ ์๋๊ฒ์ ์ ์ ์๋ค.
์ฆ, Target Element ๊ฐ ํ๋ฉด์ ๋ ธ์ถ๋์๋ ์ง ์ฌ๋ถ๋ฅผ ๊ฐ๋จํ๊ฒ ๊ตฌ๋ ํ ์ ์๋ API ์ด๋ค.
์๋ฅผ ๋ค์ด, intersection observer๊ฐ ์์ด ๊ตฌํํ๋ค๊ณ ํ๋ค๋ฉด, scroll์ด ์ผ์ด๋ ๋ ๋ง๋ค, ํน์ element๊ฐ ํ๋ฉด์ ์กด์ฌํ๋์ง์ ๋ํ ์ฌ๋ถ๋ฅผ ๊ณ์ ๊ณ์ฐํ๋ code๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค. ํ์ง๋ง intersection์ ์ฌ์ฉํ๋ค๋ฉด ์ฝ๊ฒ ์ฌ์ฉ์ฌ๋ถ๋ฅผ ํ์ธ ํ ์ ์๋ค.
1. ํ์ด์ง ์คํฌ๋กค ์ ์ด๋ฏธ์ง๋ฅผ Lazy Loadingํ ๋
2. Infinite scrolling์ ํตํด ์คํฌ๋กค์ ํ๋ฉฐ ์๋ก์ด ์ฝํ
์ธ ๋ฅผ ๋ถ๋ฌ์ฌ ๋
3. ๊ด๊ณ ์ ์์ต์ ๊ณ์ฐํ๊ธฐ ์ํด ๊ด๊ณ ์ ๊ฐ์์ฑ์ ์ฐธ๊ณ ํ ๋
4. ์ฌ์ฉ์๊ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ๊ฒ์ธ์ง์ ๋ฐ๋ผ ์ ๋๋ฉ์ด์
๋์ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ ๋
- ํ์ด์ง๋ฅผ ๋ถ๋ฌ์ค๋ ์์ ์ ๋น์ฅ ํ์ํ์ง ์์ ๋ฆฌ์์ค๋ค์ ์ถํ์ ๋ก๋ฉํ๊ฒ ํ๋ ๊ธฐ์ . ์ฆ, ์ฌ์ฉ์๊ฐ ๋ณด์ง ์์๋๋ ๋น์ฅ ๋ก๋ฉํ์ง ์๊ณ , ๋์ค์ ์ฌ์ฉ์๊ฐ ํ์๋ก ํ๋ ์์ ์ ๋ก๋ฉํ๋ ๊ธฐ์
- infinite scrolling ๊ณผ placeholder๊ฐ Lazy Loading์ ์์
intersection observer๋ฅผ ์์ฑํ๊ธฐ ์ํด์๋ ์์ฑ์ ํธ์ถ ์ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ ๊ณตํด์ผ ํ๋ค. ์ด ์ฝ๋ฐฑ ํจ์๋ threshold๊ฐ ํ ๋ฐฉํฅ ํน์ ๋ค๋ฅธ ๋ฐฉํฅ์ผ๋ก ๊ต์ฐจํ ๋ ์คํ๋๋ค.
const observer= new IntersectionObserver(callback,options)
โผ callback
const intersectionObserver = new IntersectionObserver((entries, observer) => { entries.forEach((entry) => { if (entry.isIntersecting) { console.log(entry); observer.unobserve(entry.target); } }); }); intersectionObserver.observe(document.getElementById("app"));
โพ entries
entries๋ IntersectionObserverEntry ์ธ์คํด์ค์ ๋ฐฐ์ด์ด๋ค.
IntersectionObserverEntry๋ ์ฝ๊ธฐ ์ ์ฉ(Read only)์ ๋ค์ ์์ฑ๋ค์ ํฌํจํ๋ค.
boundingClientRect(DOMRectReadOnly)
: ๊ด์ฐฐ ๋์์ ์ฌ๊ฐํ ์ ๋ณดintersectionRect(DOMRectReadOnly)
: ๊ด์ฐฐ ๋์์ ๊ต์ฐจํ ์์ญ ์ ๋ณดintersectionRatio
: ๊ด์ฐฐ ๋์์ ๊ต์ฐจํ ์์ญ ๋ฐฑ๋ถ์จ(intersectionRect ์์ญ์์ boundingClientRect ์์ญ๊น์ง ๋น์จ, Number)isIntersecting(Boolean)
: ๊ด์ฐฐ ๋์์ ๊ต์ฐจ ์ํrootBounds(DOMRectReadOnly)
: ์ง์ ํ ๋ฃจํธ ์์์ ์ฌ๊ฐํ ์ ๋ณดtarget(Element)
: ๊ด์ฐฐ ๋์ ์์
โพ observer
- ์ฝ๋ฐฑ์ด ์คํ๋๋ ํด๋น ์ธ์คํด์ค๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
โผ options
let options={ root: document.querySelector('#target'), rootMargin:'0px', threshold:1.0 } let observer = new IntersectionObserver(callback, options);
โพ root
- ํ๊ฒ์ ๊ฐ์์ฑ์ ๊ฒ์ฌํ๊ธฐ ์ํด ๋ทฐํฌํธ ๋์ ์ฌ์ฉํ ์์ ๊ฐ์ฒด๋ฅผ ์ง์ ํ๋ค.
ํ๊ฒ์ ์กฐ์ ์์์ด์ฌ์ผ ํ๋ฉฐ, ์ง์ ํ์ง ์๊ฑฐ๋ null์ผ ๊ฒฝ์ฐ ๋ธ๋ผ์ฐ์ ์ ๋ทฐํฌํธ๊ฐ ๊ธฐ๋ณธ ์ฌ์ฉ๋๋ค.
โพ rootMargin
- ๋ฐ๊นฅ ์ฌ๋ฐฑ(Margin)์ ์ด์ฉํด Root ๋ฒ์๋ฅผ ํ์ฅํ๊ฑฐ๋ ์ถ์ํ ์ ์๋ค.
CSS์ margin๊ณผ ๊ฐ์ด 4๋จ๊ณ๋ก ์ฌ๋ฐฑ์ ์ค์ ํ ์ ์์ผ๋ฉฐ, px ๋๋ %๋ก ๋ํ๋ผ ์ ์๋ค. ๊ธฐ๋ณธ๊ฐ์ 0px 0px 0px 0px์ด๋ฉฐ ๋จ์๋ฅผ ๊ผญ ์ ๋ ฅํด์ผ ํ๋ค.
โพ threshold
- observer์ ์ฝ๋ฐฑ์ด ์คํ๋ ๋์์ ๊ฐ์์ฑ %๋ฅผ ๋ํ๋ด๋ ๋จ์ผ์ซ์, ๋ฐฐ์ด์ด๋ค.
๋ง์ฝ 50% ๋งํผ์ ์์๊ฐ ๋ณด์ฌ์ก์ ๋๋ฅผ ํ์งํ๊ณ ์ถ๋ค๋ฉด 0.5๋ก ์ค์ ํด์ฃผ๋ฉด ๋๋ค.
๊ธฐ๋ณธ๊ฐ์ 0์ด๋ฉฐ, 1.0์ ์์์ ๋ชจ๋ ํฝ์ ์ด ํ๋ฉด์ ๋ ธ์ถ๋๊ธฐ ์ ์๋ ์ฝ๋ฐฑ์ํค์ง ์์์ ์๋ฏธํ๋ค.
โป Method
const observer= new InterSectionObserver((entries) => { entries.forEach(entry => console.log(entry)) },{threshold:0.3}); const target= document.querySelector('#element'); oberver.observe(target) // ๊ด์ฐฐ์์ observer.unobserver(target) // ๊ด์ฐฐ ์ค์ง observer.disconnect() // IntersectionObserver ์ธ์คํด์ค๊ฐ ๊ด์ฐฐํ๋ ๋ชจ๋ ์์ ๊ด์ฐฐ ์ค์ง
โพ observer : ๋์ ์์์ ๊ด์ฐฐ์ ์์ํ๋ค.
- parameter : IntersectionObserver ํ๊ฒ
โพ unobserver : ๋์ ์์์ ๊ด์ฐฐ์ ๋ฉ์ถ๋ค.
- parameter : IntersectionObserver ํ๊ฒ
- ์ฝ๋ฐฑ์ ๋๋ฒ์งธ ์ธ์๊ฐ observer๊ฐ ํด๋น ์ธ์คํดํธ๋ฅผ ์ฐธ๊ณ ํ๋ฏ๋ก ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉ ๊ฐ๋ฅ.
const observer= new InterSectionObserver((entries,observer) => { entries.forEach(entry => { if(!entry.isIntersection){ return false; //๊ต์ฐจ ์ํ๊ฐ ์๋ ๋ return } //๊ด์ฐฐ๋์์ด ๊ต์ฐจ์ํ์ผ๋๋ง ์คํ console.log('๊ต์ฐจ์ํ ํ์ธ:',entry.isIntersection); //์ ์คํ์ ์ฒ๋ฆฌํ๊ณ ๊ด์ฐฐ ์ค์ง. observer.unobserve(entry.target); }) },{threshold:0.3});
โพ disconnect() : IntersectionObserver ์ธ์คํด์ค๊ฐ ๊ด์ฐฐํ๋ ๋ชจ๋ ์์์ ๊ด์ฐฐ์ ์ค์งํ๋ค.
- paramteter: ์์.
๐ ๊ฒฐ๋ก
- ๋ณดํต scroll event๊ฐ ์คํ๋๊ฒ ๋๋ฉด ์คํฌ๋กค์ด ์ผ์ด๋ ๋๋ง๋ค ๋ฐ์๋๊ธฐ ๋๋ฌธ์ ์คํฌ๋กค์ ๋ด๋ฆด ๋ ๋ง๋ค ์คํ๋๋ค. ๊ทธ๋์ ํด๋๋ถ๋ถ์ ๋ค๋ฅด๊ฒ ์ฒ๋ฆฌํ๊ฑฐ๋ ์คํฌ๋กค ์ ๋๋ฉ์ด์ ์ ์คํํ ๋ ๋ถํ์ํ ์ด๋ฒคํธ๊ฐ ๋ง์ด ๋ฐ์๋๊ฒ ๋๋ค.
- Intersection Observer๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด viewport ๊ธฐ์ค์ผ๋ก ์ด๋ฒคํธ๊ฐ ๋ฐ์๋๊ณ , ๊ธฐ์ค์ผ๋ก ํ ํ์ ํ ํ๊ฒ์ ์ง์ ํ ์ ์๊ธฐ๋๋ฌธ์ ๋ถํ์ํ ์ด๋ฒคํธ๊ฐ ์ผ์ด๋์ง ์๋๋ค.
- ์์งํ ํ์ด์ง๋ฅผ ์๋ฒ์ ๋ฐฐํฌํด๋ณธ์ ์ด ์์ด์ ์ด๋ฒคํธ๊ฐ ๋ง์ด ์ผ์ด๋์ ์๊ธฐ๋ ์ด์์ ์ฝ์ ๋ค์, dev๋ชจ๋์์๋ ์๋์ฐจ์ด๊ฐ ํฌ๊ฒ ๋์ง ์๊ธฐ๋๋ฌธ์ ํฌ๊ฒ ๋๋ ์ ์์๋ค. ํ์ง๋ง ํ๋ก์ ํธ์ ์ฌ์ด์ฆ๊ฐ ์ปค์ง๋ค๋ฉด ์ด ๋ถ๋ถ์ ํฐ ์ด์๊ฐ ๋ ์ ์๋ค๊ณ ์๊ฐ๋๋ค.
๋ค์ ํฌ์คํ ์ IntersectionObserver๋ฅผ ์ฌ์ฉํ ๋ฌดํ ์คํฌ๋กค ๊ตฌํํ๊ธฐ!
์ถ์ฒ
- https://developer.mozilla.org/ko/docs/Web/API/Intersection_Observer_API [MDN : Intersection Observer API]
- https://heropy.blog/2019/10/27/intersection-observer/ [
Intersection Observer - ์์์ ๊ฐ์์ฑ ๊ด์ฐฐ] - https://velog.io/@yejinh/Intersection-Observer%EB%A1%9C-%EB%AC%B4%ED%95%9C-%EC%8A%A4%ED%81%AC%EB%A1%A4-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0 [yejinh.log / Intersection Observer๋ก ๋ฌดํ ์คํฌ๋กค ๊ตฌํํ๊ธฐ]
- https://velog.io/@vagabondms/%EA%B8%B0%EC%88%A0-%EC%8A%A4%ED%84%B0%EB%94%94-Lazy-loading%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80 [๊ธ์ ์ ์๊ธฐ๋ถ์ .log / ๊ธฐ์ ์คํฐ๋ Lazy-loading์ด๋ ๋ฌด์์ธ๊ฐ.]
Author And Source
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(5 . ๐ Intersection Observer), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://velog.io/@holicholicpop/5-.-Intersection-Observer์ ์ ๊ท์: ์์์ ์ ๋ณด๊ฐ ์์์ URL์ ํฌํจ๋์ด ์์ผ๋ฉฐ ์ ์๊ถ์ ์์์ ์์ ์ ๋๋ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค