Intersection Observer API(๊ต์ฐจ ๊ด์์) ๋ ํ์ผ ์์๊ฐ ํ๋ฉด์ ๋ณด์ด์ง๋์ง ์ฌ๋ถ๋ฅผ ๊ด์ฐฐํ๋ API ์ด๋ค.
React๋ก Infinite Scroll ๊ตฌํ์ ์ํด ํ๋ฌ๊ทธ์ธ์ ์ฐพ์๋ณด๋ ์ค JavaScript API๋ก๋ ๊ฐ๋ฅํ๋ค๊ณ ํด์ ์ ๋ฆฌํด๋ณด๊ณ ์ํ๋ค.
scroll event
๋ก๋ ๊ตฌํ์ด ๊ฐ๋ฅํ์ง๋ง ์ฌ์ฉ์๊ฐ ์คํฌ๋กค์ ๋ฐ์์ํฌ๋ ๋ง๋ค ํธ์ถ๋๊ธฐ ๋๋ฌธ์ ๋ฉ์ธ ์ค๋ ๋(Main Thread)์ ์ํฅ์ ์ค๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋๋ฐ์ด์ฑ(Debouncing)๊ณผ ์ฐ๋กคํ๋ง(Throttling)์ ์ฌ์ฉํด์ผ ํ๋ค.
๋ํ getBoundingClientRect()
ํจ๊ผ ์ฌ์ฉํด์ผํ๋๋ฐ ์ด ํจ์๋ ๋ฆฌํ๋ก์ฐ๊ฐ ๋ฐ์ํ๋ค.
๋จผ์ IntersectionObeserver
๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ค.
const observer = new intersectionObserver(callback,options)
์์ฑ์, ์ฝ๋ฐฑ ํจ์์ ์ต์ ์ ํจ๊ป ์ ๋ฌํ ์ ์๋๋ฐ, ๋จผ์ ์ต์ ๋ถํฐ ์์๋ณด์.
์๋ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํ๋ฉด ์ดํดํ๊ธฐ ์ฝ๋ค.
root
: ์ด ์์๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ด์ฐฐํ๊ณ ์ํ๋ ์์์ ๊ฐ์์ฑ์ ๊ฒฐ์ ํ๋ค. (default
: ๋ธ๋ผ์ฐ์ viewport)rootMargin
: ๋จ์ด์ ๋ป ๊ทธ๋๋ก root๊ฐ ๊ฐ๋ margin ๊ฐ์ด๋ค. (default
: 0)threshold
: root๋ฅผ ๊ธฐ์ค์ผ๋ก ๋์์์๊ฐ ์ผ๋ง๋งํผ ๋ณด์ผ๋ ์ฝ๋ฐฑํจ์๋ฅผ ์คํํ ์ง 0~1 ์ฌ์ด์ ๊ฐ์ผ๋ก ๋ํ๋ธ๋ค. ๋ง์ฝ ์์๊ฐ 25%์ฉ ๋ณด์ผ๋๋ง๋ค ์คํํ๊ณ ์ถ๋ค๋ฉด [0, 0.25, 0.5, 0.75, 1]
์ ๊ฐ์ด ๋ฐฐ์ด๋ก ์์ฑํ๋ฉด ๋๋ค. (default
: 1)์ฝ๋ฐฑํจ์๋ ๋๊ฐ์ง์ ์ธ์๋ฅผ ๋ฐ์ ์ ์๋๋ฐ, entries์ obeserver ์ด๋ค.
const observer = new intersectionObserver((entries,observer)=>{
entries.forEach((entry) => {
console.group('Intersection Observer Entry');
console.log(entry.boundingClientRect);
console.log(entry.intersectionRatio);
console.log(entry.intersectionRect);
console.log(entry.isIntersecting);
console.log(entry.rootBounds);
console.log(entry.target );
console.log(entry.time);
console.groupEnd()
})
})
entries
: Intersection Observer Entry ์ ๋ฐฐ์ด๊ฐ์ด๋ค. ์ฝ๊ฒ ๋งํด์ ๋ฑ๋ก๋ ๋์์์๋ค์ ๋ฐฐ์ด๊ฐ ์ด๋ค.boundingClientRect
: target์ getBoundingClientRect() ๊ฐintersectionRatio
: target์ด ์ผ๋ง๋งํผ ๋
ธ์ถ๋ฌ๋์ง 0~1 ์ฌ์ด์ ๊ฐ์ผ๋ก ๋ํ๋ธ๋ค. (๋
ธ์ถ๋น์จ)intersectionRect
: ๋
ธ์ถ๋ ์์ญ์ ๋ํ ์ฌ๊ฐํ ์์ฑ๊ฐisIntersecting
: ๋
ธ์ถ์ฌ๋ถ๋ฅผ true/false ๊ฐ์ผ๋ก ๋ํ๋ธ๋ค.rootBounds
: ๋ฃจํธ์ ์ฌ๊ฐํ ์์ฑ๊ฐtarget
: ๋์์์time
: ๋์์ด ๊ต์ฐจ๋ ์๊ฐobserver
: ๋ง๋ค์ด์ง Intersection Observer ๊ฐ์ฒด์ด๋ค. Intersection Observer ๊ฐ์ฒด๋ 4๊ฐ์ง์ ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
๐ญ observe
: ์์์ ๋ํ ๊ด์ฐฐ์ ์์โ disconnect
: ๋ชจ๋ ๋์์์๋ค์ ๋ํ ๊ด์ฐฐ์ ์ค๋จ (์ฐ๊ฒฐ์ ๋๋๋ค.)๐ takeRecordes
: ๋ชจ๋ ๋์์์๋ค์ ๋ํ Intersection Observer Entry ๋ฐฐ์ด์ ๋ฐํโ๐ป unobserve
: ํน์ ์์์ ๋ํ ๊ด์ฐฐ์ ์ค๋จ์. ์ด์ ๋ฌดํ ์คํฌ๋กค์ ๊ตฌํํด๋ณด์.
๊ตฌํ ๋ฐฉ๋ฒ์ ๊ฐ๋จํ๋ค.
๋จผ์ , html๋ก scroll์ด ์๊ธธ๋งํ ํฌ๊ธฐ์ ์์๋ฅผ ๋ง๋ ๋ค.
๋์ ์์๋ฅผ intersection Observer ๊ฐ์ฒด์ observe
ํ๋ค.
๊ทธ ํ ์ฝ๋ฐฑํจ์๋ก ๊ฐ์์ ๋ฐ์ดํฐ๋ฅผ ๋๋ฉฐ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ ๋ง์ง๋ง์ผ๋ก ๋ง๋ค์ด์ง๋ ์์๋ฅผ ๋ค์ observe
ํ๋ ํจ์๋ฅผ ๋ฆฌํด์ํจ๋ค.
API ํ์ ํ๋ ์ ๋๋ก๋ง ์์ฃผ ๊ฐ๋จํ๊ฒ ๋ง๋ค๊บผ๋ผ CSS๋ถํฐ ๊ฐ๋จํ๊ฒ ์งฐ๋ค.
body {
width: 100%;
height: 100%;
}
/* ๋ฃ์ง ์๊ณ div์ ํฌ๊ธฐ๋ฅผ ๋๋ ค๋ ๋๋ค. */
header {
width: 500px;
height: auto;
padding: 10px;
background-color: #f9f8ed;
color: #6a9c78;
text-align: center;
margin: 10px auto 20px auto;
border-radius: 20px;
}
div {
width: 400px;
height: 400px;
border: 10px solid #c4e3cb;
border-radius: 200px;
margin: auto;
text-align: center;
line-height: 400px;
font-size: 2em;
color:forestgreen;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>๋ฌดํ์คํฌ๋กค ๊ตฌํํ๊ธฐ</title>
</head>
<body>
<div></div>
<div></div>
<div id="target">target</div>
</body>
</html>
// ๋ฐ์ดํฐ๋ฅผ ๋ง๋ ๋ค.
let data = [];
const count = 10
for(let i = 0;i < 10;i++){
data.push('์๋ก์๊ธด Element' + (i+1));
}
const target = document.querySelector('#target');
const body = document.querySelector('body');
div
์์๋ฅผ ๋ง๋๋ ํจ์๋ฅผ ๋ง๋ ๋ค. ์ด ๋ ๋ง์ง๋ง div
๋ฅผ ๊ด์ฐฐ๋์์ผ๋ก ๋ฑ๋กํ๋ค.const createElement = (data,observer) => {
data.forEach((item,index)=>{
let div = document.createElement('div');
// ๋ฐ์ดํฐ์ ๋ง์ง๋ง ์์๋ฅผ ๊ด์ฐฐ๋์์ผ๋ก ๋ฑ๋กํ๋ค.
if(index === data.length -1){
div.innerText = "target";
observer.observe(div);
} else {
div.innerText = item;
}
body.appendChild(div);
})
}
observe
ํ๋ค.const option = {
rootMargin: '0px',
threshold: 1.0
}
const observer = new IntersectionObserver((entries,observer)=>{
console.log(entries);
entries.forEach((entry,index)=>{
console.log(entries[index]);
if(entry.isIntersecting){
return createElement(data,observer);
} else {
return;
}
})
},option);
observer.observe(target);
http://blog.hyeyoonjung.com/2019/01/09/intersectionobserver-tutorial
https://velog.io/@meganatc7/Intersection-Observer-%EB%9E%80
https://developer.mozilla.org/ko/docs/Web/API/Intersection_Observer_API
https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry
https://developer.mozilla.org/ko/docs/Web/API/IntersectionObserver/IntersectionObserver