๐ฉ IntersectionObserver
https://developer.mozilla.org/ko/docs/Web/API/Intersection_Observer_API
ํน์ ์์๊ฐ ๋ทฐํฌํธ ๋๋ ๋ค๋ฅธ ํน์ ์์์ ๊ต์ฐจํ๋์ง๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ๊ฐ์งํ ์ ์๊ฒ ํด์ค๋ค.
๊ธฐ์กด์๋ scroll ์ด๋ฒคํธ๋ฅผ ํตํด ๋ ์์ ์ฌ์ด์ ๊ฐ์์ฑ์ ๊ฐ์งํ์ง๋ง, IntersectionObserver๋ ๊ด์ฐฐ ๋์ ์์๊ฐ ๋ทฐํฌํธ์ ๋ค์ด์ค๊ฑฐ๋ ๋๊ฐ ๋๋ง ์ฝ๋ฐฑ ํจ์๋ฅผ ์คํํ๋ค. ์ด ๊ณผ์ ์ ๋น๋๊ธฐ์ ์ผ๋ก ์ด๋ฃจ์ด์ง๋ฏ๋ก, ๋ฉ์ธ ์ค๋ ๋์ ์์ ์ ๋ฐฉํดํ์ง ์๊ณ ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฝ๋ฐฑ ํจ์๋ฅผ ์คํํ๋ค.
์ต์ ์ค์
const options = {
root: document.querySelector("#scrollArea"),
rootMargin: "0px",
threshold: 1.0,
};
const observer = new IntersectionObserver(callback, options);
- root
- ๊ต์ฐจ์ ์ ๊ฐ์ํ๋๋ฐ ์ฌ์ฉ๋๋ ์์. ๋ฐ๋์ ํ๊ฒ์ ์์ ์์์ด์ด์ผ ํ๋ค.
- ๊ธฐ๋ณธ๊ฐ์ ๋ทฐํฌํธ
- rootMargin
- root ์์์ ๋ฒ์๋ฅผ ์ค์
- ๊ธฐ๋ณธ๊ฐ์ 0

์ด๋ฏธ์ง ์ถ์ฒ
https://wilsotobianco.hashnode.dev/a-graphical-introduction-to-the-intersection-observer-api
https://www.smashingmagazine.com/2021/07/dynamic-header-intersection-observer/
- threshold
- ์ฝ๋ฐฑ์ด ์คํ๋๋ ๊ต์ฐจ ๋น์จ
- ๊ธฐ๋ณธ ๊ฐ์ 0 (1px์ด๋ผ๋ ๋ณด์ด๋ฉด ์ฝ๋ฐฑ ์คํ)
- 1์ ํ๊ฒ ์์๊ฐ 100% ๋ณด์ผ๋
- [0, 0.25, 0.5, 1] // 0.25๋ 25% ๋ณด์ผ ๋, 0.5๋ 50% ๋ณด์ผ ๋
๐ฉ MutationObserver
https://developer.mozilla.org/ko/docs/Web/API/MutationObserver
DOM ์์์ ์์ฑ, ์์ ๋ ธ๋ ๋ฑ์ ๋ณํ๋ฅผ ๊ฐ์งํ๊ณ ์ฝ๋ฐฑ ํจ์๋ฅผ ์คํํ๋ค.
MutationObserver๋ ๊ธฐ์กด์ Mutation Event๋ฅผ ๋์ฒดํ๋ฉฐ ๋น๋๊ธฐ์ ์ผ๋ก ๋์ํ๋ค. ๋ณํ๋ฅผ ๊ฐ์งํ ํ, ์ฝ๋ฐฑ์ ๋ง์ดํฌ๋กํ์คํฌํ์ ์ถ๊ฐํ๋ฏ๋ก ๋ฉ์ธ ์ค๋ ๋์ ์์ ์ ๋ฐฉํดํ์ง ์๋๋ค.
์ต์ ์ค์
// ๋ณ๊ฒฝ์ ๊ฐ์งํ ๋
ธ๋ ์ ํ
const targetNode = document.getElementById("some-id");
// ๊ฐ์ง ์ต์
(๊ฐ์งํ ๋ณ๊ฒฝ)
const config = { attributes: true, childList: true, subtree: true };
const observer = new MutationObserver(callback);
// ์ค์ ํ ๋ณ๊ฒฝ์ ๊ฐ์ง ์์
observer.observe(targetNode, config);
- attributes
- ์์์ ์์ฑ(attribute) ๋ณํ๋ฅผ ๊ฐ์ง
- childList
- ์์ ๋ ธ๋์ ์ถ๊ฐ ๋ฐ ์ ๊ฑฐ๋ฅผ ๊ฐ์ง
- subtree
- ๋ชจ๋ ํ์ ๋ ธ๋์ ์ถ๊ฐ, ์ ๊ฑฐ ๋ฐ ๋ณ๊ฒฝ์ ๊ฐ์ง
- attributeOldValue
- ์์ฑ์ ์ด์ ๊ฐ์ ๊ธฐ๋ก
- characterData
- ํ ์คํธ ๋ ธ๋์ ๋ณ๊ฒฝ์ ๊ฐ์ง
- characterDataOldValue
- ํ ์คํธ ๋ ธ๋์ ์ด์ ๊ฐ์ ๊ธฐ๋ก
- attributeFilter
- ๊ฐ์งํ ์์ฑ์ ์ด๋ฆ์ผ ์ง์ , ์ง์ ๋ ์์ฑ๋ง ๋ณํ๊ฐ ๊ฐ์ง๋๋ค.
- attribute๊ฐ true ์ค์ ๋ ๊ฒฝ์ฐ๋ง ์ ํจ
- ['class', 'id', 'style', ...]
๐ฉ ResizeObserver
https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver
์์์ ํฌ๊ธฐ ๋ณํ๋ฅผ ๊ฐ์งํ๊ณ ์ฝ๋ฐฑ ํจ์๋ฅผ ์คํํ๋ค.
๊ธฐ์กด์ resize ์ด๋ฒคํธ๋ ๋ธ๋ผ์ฐ์ ์ฐฝ ํฌ๊ธฐ ๋ณํ๋ฅผ ๊ฐ์งํ๋ฉฐ ๋๊ธฐ์ ์ผ๋ก ์๋ํ๋ค. ๋ฐ๋ฉด, ResizeObserver๋ ํน์ ์์์ ํฌ๊ธฐ ๋ณํ๋ง ๊ฐ์งํ๊ณ , ๋น๋๊ธฐ์ ์ฒ๋ฆฌํ์ฌ ๋ฉ์ธ ์ค๋ ๋์ ์์ ์ ๋ฐฉํดํ์ง ์๋๋ค.
const divElem = document.querySelector("body > div");
const resizeObserver = new ResizeObserver(callback);
resizeObserver.observe(divElem);
๐ฉ IntersectionObserver
https://developer.mozilla.org/ko/docs/Web/API/Intersection_Observer_API
ํน์ ์์๊ฐ ๋ทฐํฌํธ ๋๋ ๋ค๋ฅธ ํน์ ์์์ ๊ต์ฐจํ๋์ง๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ๊ฐ์งํ ์ ์๊ฒ ํด์ค๋ค.
๊ธฐ์กด์๋ scroll ์ด๋ฒคํธ๋ฅผ ํตํด ๋ ์์ ์ฌ์ด์ ๊ฐ์์ฑ์ ๊ฐ์งํ์ง๋ง, IntersectionObserver๋ ๊ด์ฐฐ ๋์ ์์๊ฐ ๋ทฐํฌํธ์ ๋ค์ด์ค๊ฑฐ๋ ๋๊ฐ ๋๋ง ์ฝ๋ฐฑ ํจ์๋ฅผ ์คํํ๋ค. ์ด ๊ณผ์ ์ ๋น๋๊ธฐ์ ์ผ๋ก ์ด๋ฃจ์ด์ง๋ฏ๋ก, ๋ฉ์ธ ์ค๋ ๋์ ์์ ์ ๋ฐฉํดํ์ง ์๊ณ ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฝ๋ฐฑ ํจ์๋ฅผ ์คํํ๋ค.
์ต์ ์ค์
const options = {
root: document.querySelector("#scrollArea"),
rootMargin: "0px",
threshold: 1.0,
};
const observer = new IntersectionObserver(callback, options);
- root
- ๊ต์ฐจ์ ์ ๊ฐ์ํ๋๋ฐ ์ฌ์ฉ๋๋ ์์. ๋ฐ๋์ ํ๊ฒ์ ์์ ์์์ด์ด์ผ ํ๋ค.
- ๊ธฐ๋ณธ๊ฐ์ ๋ทฐํฌํธ
- rootMargin
- root ์์์ ๋ฒ์๋ฅผ ์ค์
- ๊ธฐ๋ณธ๊ฐ์ 0

์ด๋ฏธ์ง ์ถ์ฒ
https://wilsotobianco.hashnode.dev/a-graphical-introduction-to-the-intersection-observer-api
https://www.smashingmagazine.com/2021/07/dynamic-header-intersection-observer/
- threshold
- ์ฝ๋ฐฑ์ด ์คํ๋๋ ๊ต์ฐจ ๋น์จ
- ๊ธฐ๋ณธ ๊ฐ์ 0 (1px์ด๋ผ๋ ๋ณด์ด๋ฉด ์ฝ๋ฐฑ ์คํ)
- 1์ ํ๊ฒ ์์๊ฐ 100% ๋ณด์ผ๋
- [0, 0.25, 0.5, 1] // 0.25๋ 25% ๋ณด์ผ ๋, 0.5๋ 50% ๋ณด์ผ ๋
๐ฉ MutationObserver
https://developer.mozilla.org/ko/docs/Web/API/MutationObserver
DOM ์์์ ์์ฑ, ์์ ๋ ธ๋ ๋ฑ์ ๋ณํ๋ฅผ ๊ฐ์งํ๊ณ ์ฝ๋ฐฑ ํจ์๋ฅผ ์คํํ๋ค.
MutationObserver๋ ๊ธฐ์กด์ Mutation Event๋ฅผ ๋์ฒดํ๋ฉฐ ๋น๋๊ธฐ์ ์ผ๋ก ๋์ํ๋ค. ๋ณํ๋ฅผ ๊ฐ์งํ ํ, ์ฝ๋ฐฑ์ ๋ง์ดํฌ๋กํ์คํฌํ์ ์ถ๊ฐํ๋ฏ๋ก ๋ฉ์ธ ์ค๋ ๋์ ์์ ์ ๋ฐฉํดํ์ง ์๋๋ค.
์ต์ ์ค์
// ๋ณ๊ฒฝ์ ๊ฐ์งํ ๋
ธ๋ ์ ํ
const targetNode = document.getElementById("some-id");
// ๊ฐ์ง ์ต์
(๊ฐ์งํ ๋ณ๊ฒฝ)
const config = { attributes: true, childList: true, subtree: true };
const observer = new MutationObserver(callback);
// ์ค์ ํ ๋ณ๊ฒฝ์ ๊ฐ์ง ์์
observer.observe(targetNode, config);
- attributes
- ์์์ ์์ฑ(attribute) ๋ณํ๋ฅผ ๊ฐ์ง
- childList
- ์์ ๋ ธ๋์ ์ถ๊ฐ ๋ฐ ์ ๊ฑฐ๋ฅผ ๊ฐ์ง
- subtree
- ๋ชจ๋ ํ์ ๋ ธ๋์ ์ถ๊ฐ, ์ ๊ฑฐ ๋ฐ ๋ณ๊ฒฝ์ ๊ฐ์ง
- attributeOldValue
- ์์ฑ์ ์ด์ ๊ฐ์ ๊ธฐ๋ก
- characterData
- ํ ์คํธ ๋ ธ๋์ ๋ณ๊ฒฝ์ ๊ฐ์ง
- characterDataOldValue
- ํ ์คํธ ๋ ธ๋์ ์ด์ ๊ฐ์ ๊ธฐ๋ก
- attributeFilter
- ๊ฐ์งํ ์์ฑ์ ์ด๋ฆ์ผ ์ง์ , ์ง์ ๋ ์์ฑ๋ง ๋ณํ๊ฐ ๊ฐ์ง๋๋ค.
- attribute๊ฐ true ์ค์ ๋ ๊ฒฝ์ฐ๋ง ์ ํจ
- ['class', 'id', 'style', ...]
๐ฉ ResizeObserver
https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver
์์์ ํฌ๊ธฐ ๋ณํ๋ฅผ ๊ฐ์งํ๊ณ ์ฝ๋ฐฑ ํจ์๋ฅผ ์คํํ๋ค.
๊ธฐ์กด์ resize ์ด๋ฒคํธ๋ ๋ธ๋ผ์ฐ์ ์ฐฝ ํฌ๊ธฐ ๋ณํ๋ฅผ ๊ฐ์งํ๋ฉฐ ๋๊ธฐ์ ์ผ๋ก ์๋ํ๋ค. ๋ฐ๋ฉด, ResizeObserver๋ ํน์ ์์์ ํฌ๊ธฐ ๋ณํ๋ง ๊ฐ์งํ๊ณ , ๋น๋๊ธฐ์ ์ฒ๋ฆฌํ์ฌ ๋ฉ์ธ ์ค๋ ๋์ ์์ ์ ๋ฐฉํดํ์ง ์๋๋ค.
const divElem = document.querySelector("body > div");
const resizeObserver = new ResizeObserver(callback);
resizeObserver.observe(divElem);