[Observer API ํํค์น๊ธฐ] 3. ResizeObserver
โฐ 2024-06-20 (๋ชฉ) 01:14:40
ResizeObserver
ResizeObserver
๋ ์์์ ํฌ๊ธฐ ๋ณํ๋ฅผ ๊ฐ์งํ๋ ์ต์ ๋ฒ๋ค. ์์์ width
, height
๊ฐ ๋ณํ ๊ฒฝ์ฐ, ์ด๋ฅผ ๊ฐ์งํ์ฌ ์ํ๋ ๋์์ ์ํํ ์ ์๋ค.
TYPESCRIPT
1 2 3
const ro = new ResizeObserver(callback); ro.observe(tag, options);
์ด์ ์ฅ์ IntersectionObserver
์ ๋ค๋ฅด๊ฒ ์ต์
์ API์์ ํ ๋นํ์ง ์๋๋ค. observe
๋ฉ์๋๋ฅผ ํตํด ์์๋ฅผ ๋ฑ๋กํ ๋, options
๋ฅผ ๊ฐ์ด ์ง์ ํ ์ ์๋ค.
options
์์ ๋ฑ๋ก ์ options
๋ฅผ ์ ๋ฌํ์ฌ ์ธ๋ถ ์ต์
์ ์กฐ์ ํ ์ ์๋ค. ResizeObserverOptions
ํ์
์ ๊ฐ์ง๋ค.
๋ฐ์ค ์ข
๋ฅ (box)
์์์ ์ข ๋ฅ๋ฅผ ์ง์ ํ๋ค.
content-box
- CSS์ ์ ์๋ ์ปจํ ์ธ ์์ญ์ ํฌ๊ธฐborder-box
- CSS์ ์ ์๋ ๋ฐ์ค ์ ์ฒด ์์ญ์ ํฌ๊ธฐ (margin
,padding
,border
ํฌํจ)device-pixel-content-box
- ๊ธฐ๊ธฐ์ ํฝ์ ๋จ์ ๊ธฐ์ค์ผ๋ก ์ ์๋ ์ปจํ ์ธ ์์ญ์ ํฌ๊ธฐ
callback
ResizeObserver
์ ์ฝ๋ฐฑ ๋ฉ์๋๋ ์์์ ํฌ๊ธฐ๊ฐ ๋ณํ ๊ฒฝ์ฐ ๋์ํ๋ ์ด๋ฒคํธ ๋ฉ์๋๋ค.
ResizeObserverCallback
ํ์
์ผ๋ก ์ ์ธ๋์ด ์์ผ๋ฉฐ, ์ด๋ฅผ ์ฝ๋๋ก ํ๊ธฐํ๋ฉด ์๋์ ๊ฐ๋ค.
TYPESCRIPT
1
const ro = new ResizeObserver((entries, observer) => {});
ResizeObserverEntry
entries
๋ ResizeObserverEntry[]
ํ์
์ ๊ฐ๋๋ค. ResizeObserverEntry
์ ๋ฑ๋ก๋ ์์์ ์ด๋ฒคํธ ์ ๋ณด๋ฅผ ๋ฐฐ์ด ํํ๋ก ๋ฐํํ๋ค.
ResizeObserverEntry
์ ์ฌ๋ฌ DOM์ ๋ฑ๋กํ์ฌ, ์ฌ๋ฌ ๊ฐ์ฒด์ ์ต์ ๋ฒ๋ฅผ ์ ์ฉํ ์ ์๋ค.
๊ฐ ์์์ ์๋ฏธ๋ ์ ๋ฐ์ค๋ฅผ ๊ธฐ์ค์ผ๋ก ์ค๋ช ํ๋ค.
์ ์ฒด ์์ญ์ ํฌ๊ธฐ ์ ๋ณด (borderBoxSize)
CSS์์ ์ปจํ ์ธ ์ ํฌ๊ธฐ๋ฅผ ๊ตฌ์ฑํ๋ ์์๋ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์๋ค.
๊ฐ๊ฐ border
, padding
์ผ๋ก ๋ ์ด์์์ด ๊ตฌ์ฑ๋๋ฉฐ, ๋ด๋ถ์ ์ปจํ
์ธ ์ ๋ฐ๋ผ ํฌ๊ธฐ๊ฐ ์ ํด์ง๋ค.
borderBoxSize
๋ ์ด ๋ชจ๋ ์์๋ฅผ ์์ฐ๋ฅด๋ ๋ฐ์ค์ ํฌ๊ธฐ๋ฅผ ์ ๊ณตํ๋ค. ๋ฐฐ์ด๋ก ์ด๋ฃจ์ด์ ธ ์์ผ๋ฉฐ, ๊ฐ ์์ดํ
์ blockSize
, inlineSize
๋ฅผ ๊ฐ์ง๋ค.
blockSize
- ๋์ด (height
)inlineSize
- ๋๋น (width
)
์์ ์ปจํ
์ธ ์์ญ์ ํฌ๊ธฐ ์ ๋ณด (contentBoxSize)
CSS์์ ๋ฐ์ค ๋ ์ด์์์ ๊ตฌ์ฑํ๋ border
, padding
์ ์ ์ธํ ์์ ์ปจํ
์ธ ์ ํฌ๊ธฐ ์ ๋ณด๋ฅผ ๋ฐํํ๋ค.
borderBoxSize
์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฐฐ์ด๋ก ์ด๋ฃจ์ด์ ธ ์์ผ๋ฉฐ, ๊ฐ ์์ดํ
์ ์ ๋ณด ์ญ์ ๋์ผํ๋ค.
blockSize
- ๋์ด (height
)inlineSize
- ๋๋น (width
)
๊ธฐ๊ธฐ ํฝ์
๊ธฐ์ค ์ปจํ
์ธ ์์ญ์ ํฌ๊ธฐ ์ ๋ณด (devicePixelContentBoxSize)
๊ธฐ๊ธฐ ํฝ์ ๊ธฐ์ค์ ์ปจํ ์ธ ์์ญ ํฌ๊ธฐ ์ ๋ณด๋ฅผ ๋ฐํํ๋ค.
borderBoxSize
์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฐฐ์ด๋ก ์ด๋ฃจ์ด์ ธ ์์ผ๋ฉฐ, ๊ฐ ์์ดํ
์ ์ ๋ณด ์ญ์ ๋์ผํ๋ค.
blockSize
- ๋์ด (height
)inlineSize
- ๋๋น (width
)
์์์ ํฌ๊ธฐ ์ ๋ณด (contentRect)
์์๋ค์ ๋ค์ํ ํฌ๊ธฐ ์ ๋ณด๋ฅผ ๋ฐํํ๋ ๊ฐ์ฒด๋ก, ๋ค๋ฅธ ๊ฐ์ฒด์์ ์ ๊ณตํ๋ ์ ๋ณด๊ฐ ์ผ๋ถ ์ค๋ณต๋์ด ์๋ค.
ํด๋น ๊ฐ์ฒด๋ ๋ ๊ฑฐ์ ์์ฑ์ผ๋ก, ํธํ์ฑ ์ ์ง๋ก ์ธํด ์ง์๋๊ณ ์์ผ๋ฉฐ, ์ธ์ ๊ฐ ์ง์ ์ข ๋ฃ๋ ๊ฐ๋ฅ์ฑ์ด ์๋ค. ๐ (์ฐธ๊ณ )
width
- ์์ ์ปจํ ์ธ ์์ญ์ ๋๋น (contentBoxSize
์ ๋์ผ)height
- ์์ ์ปจํ ์ธ ์์ญ์ ๋์ด (contentBoxSize
์ ๋์ผ)x
- ๋ฐ์ค๋ฅผ ๊ธฐ์ค์ผ๋ก ์์นํ ์ปจํ ์ธ ์x
์ขํy
- ๋ฐ์ค๋ฅผ ๊ธฐ์ค์ผ๋ก ์์นํ ์ปจํ ์ธ ์y
์ขํleft
- ์ปจํ ์ธ ์ ์ข์ธก ๊ธฐ์ค ์์น. ํต์x
์ ๋์ผtop
- ์ปจํ ์ธ ์ ์๋จ ๊ธฐ์ค ์์น. ํต์y
์ ๋์ผright
- ์ปจํ ์ธ ์ฐ์ธก ๊ธฐ์ค ์์น.bottom
- ์ปจํ ์ธ ํ๋จ ๊ธฐ์ค ์์น.
์ด๋ฒคํธ ๋์ (target)
ResizeObserver
์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํจ DOM ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
observer
ResizeObserver
๊ฐ์ฒด๋ฅผ ๋ฐํํด์ค๋ค. ์ด๋ฅผ ํตํด ์ฝ๋ฐฑ ๋ฉ์๋ ๋ด์์๋ ResizeObserver
๋ฅผ ์ฐ์์ ์ผ๋ก ๋ค๋ฃฐ ์ ์๋ค.
React์์ ์ปค์คํ
ํ
์ผ๋ก ๊ฐํธํ๊ฒ ์ฌ์ฉํ๊ธฐ
ResizeObserver
๋ฅผ ์ปค์คํ
ํ
์ ํตํด ๊ฐํธํ๊ฒ ์ฌ์ฉํด๋ณด์.
TYPESCRIPT
1 2 3 4
export function useResizeObserver(): void { // }
์์ ๊ฐ์ด useResizeObserver
๋ฉ์๋๋ฅผ ์ ์ํ๋ค.
useResizeObserver
๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ ์๋์ ์ธ ์์๊ฐ ํ์ํ๋ค.
- ๋์ DOM
- ์ฝ๋ฐฑ ๋ฉ์๋
- ์ต์
์ ์ธ ์์๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ์ ์ํ์. 1๋ฒ์ ๊ฒฝ์ฐ, ์ผ๋ฐ์ ์ผ๋ก HTMLElement
๊ฐ ํ์ํ์ง๋ง, ํด๋น ํ
์์๋ HTMLElement
ํ์
๋ฟ๋ง ์๋๋ผ, string
์ ๋ฐ์ #id
, .class
์ ๊ฐ์ ์ ํ์๋ก ํ๊ทธ๋ฅผ ํ์ฉํ ์ ์๋๋ก ๋ง๋ค ๊ฒ์ด๋ค.
TYPESCRIPT
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import { useEffect } from "react"; export type UseResizeObserverCallback = (entry: ResizeObserverEntry) => void; /** * ResizeObserver ์ ์ฉ ํ ๋ฉ์๋ * * @param {Element | string | null} ref: Element * @param {UseResizeObserverCallback} callback: ์ฝ๋ฐฑ ๋ฉ์๋ * @param {ResizeObserverOptions} options: ์ต์ */ export function useResizeObserver(ref: Element | string | null, callback: UseResizeObserverCallback, options?: ResizeObserverOptions): void { // }
ํ๋ผ๋ฏธํฐ๋ ์์ ๊ฐ๋ค. ์ดํ ResizeObserver
๋ฅผ ์ ์ธํ๊ณ ์ฝ๋ฐฑ ๋ฉ์๋๋ฅผ ํ ๋นํ๋ค.
TYPESCRIPT
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
import { useEffect } from "react"; export type UseResizeObserverCallback = (entry: ResizeObserverEntry) => void; /** * ResizeObserver ์ ์ฉ ํ ๋ฉ์๋ * * @param {Element | string | null} ref: Element * @param {UseResizeObserverCallback} callback: ์ฝ๋ฐฑ ๋ฉ์๋ * @param {ResizeObserverOptions} options: ์ต์ */ export function useResizeObserver(ref: Element | string | null, callback: UseResizeObserverCallback, options?: ResizeObserverOptions): void { useEffect(() => { const ro = new ResizeObserver((entries) => { entries.forEach(callback); }); }, [ ref, callback, options ]); }
ResizeObserver
๋ฅผ ์ด๊ธฐํํ์ฌ ro
๋ณ์๋ก ํ ๋นํ๋ค.
์ดํ ref
๋ก ์ง์ ํ DOM์ ํ ๋นํ๋ค.
ref
๋ ์ธ ๊ฐ์ง ์ํ์ ๋ฐ๋ผ ์๋์ ๊ฐ์ ๋ถ๊ธฐ๋ฅผ ๊ฑฐ์น๋ค.
null
์ผ ๊ฒฝ์ฐ -> ํจ์คํ๋ค.string
์ผ ๊ฒฝ์ฐ ->document.querySelector
๋ฉ์๋๋ก ํ๊ทธ๋ฅผ ์ ํํ ๋ค, ํด๋น ํ๊ทธ๋ฅผ ๋ฑ๋กํ๋ค.HTMLElement
์ผ ๊ฒฝ์ฐ -> ์ด๋ฏธElement
์ด๋ฏ๋ก, ์ฆ์ ๋ฑ๋กํ๋ค.
typeof ref === "string"
๊ตฌ๋ฌธ์ ํตํด ref
๊ฐ ๋ฌธ์์ด์ธ์ง๋ฅผ ํ๋ณํ์ฌ ๊ตฌํํ๋ค.
ro.observe()
๋ฉ์๋๋ฅผ ํตํด ํ๊ทธ๋ฅผ ๋ฑ๋กํ ์ ์๋ค.
TYPESCRIPT
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
import { useEffect } from "react"; export type UseResizeObserverCallback = (entry: ResizeObserverEntry) => void; /** * ResizeObserver ์ ์ฉ ํ ๋ฉ์๋ * * @param {Element | string | null} ref: Element * @param {UseResizeObserverCallback} callback: ์ฝ๋ฐฑ ๋ฉ์๋ * @param {ResizeObserverOptions} options: ์ต์ */ export function useResizeObserver(ref: Element | string | null, callback: UseResizeObserverCallback, options?: ResizeObserverOptions): void { useEffect(() => { const ro = new ResizeObserver((entries) => { entries.forEach(callback); }); // DOM์ด ์ ํจํ ๊ฒฝ์ฐ if (ref) { // ref๊ฐ ๋ฌธ์์ด์ผ ๊ฒฝ์ฐ if (typeof ref === 'string') { const tag = document.querySelector(ref); // ํ๊ทธ๊ฐ ์ ํจํ ๊ฒฝ์ฐ if (tag) { ro.observe(tag, options); } } // DOM์ผ ๊ฒฝ์ฐ else { ro.observe(ref, options); } } }, [ ref, callback, options ]); }
๋ง์ง๋ง์ผ๋ก, ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง ๋ ๋๋ง๋ค ResizeObserver
์ ๋ฑ๋ก์ด ์ค์ฒฉ๋์ง ์๋๋ก, ์ด๊ธฐํ ์ฝ๋๋ฅผ ๋ฃ์ด์ค๋ค.
ro.disconnect()
๋ฉ์๋๋ฅผ ํตํด ResizeObserver
๋ฅผ ์ ๊ฑฐํ ์ ์๋ค.
์ ์ฒด ์ฝ๋
TYPESCRIPT
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
import { useEffect } from "react"; export type UseResizeObserverCallback = (entry: ResizeObserverEntry) => void; /** * ResizeObserver ์ ์ฉ ํ ๋ฉ์๋ * * @param {Element | string | null} ref: Element * @param {UseResizeObserverCallback} callback: ์ฝ๋ฐฑ ๋ฉ์๋ * @param {ResizeObserverOptions} options: ์ต์ */ export function useResizeObserver(ref: Element | string | null, callback: UseResizeObserverCallback, options?: ResizeObserverOptions): void { useEffect(() => { const ro = new ResizeObserver((entries) => { entries.forEach(callback); }); // DOM์ด ์ ํจํ ๊ฒฝ์ฐ if (ref) { // ref๊ฐ ๋ฌธ์์ด์ผ ๊ฒฝ์ฐ if (typeof ref === 'string') { const tag = document.querySelector(ref); // ํ๊ทธ๊ฐ ์ ํจํ ๊ฒฝ์ฐ if (tag) { ro.observe(tag, options); } } // DOM์ผ ๊ฒฝ์ฐ else { ro.observe(ref, options); } } return () => { ro.disconnect(); }; }, [ ref, callback, options ]); }
์ ์ฒด ์ฝ๋๋ ์์ ๊ฐ๋ค.
CodeSandbox๋ฅผ ํตํ ์์
CodeSandbox๋ก ๊ฐ๋จํ ์์๋ฅผ ๊ตฌํํ๋ค.
๋ง์น๋ฉฐ
์ด์ ๊ฐ์ด ResizeObserver
๋ฅผ ํ์ฉํ๋ฉด DOM์ ๋ทฐํฌํธ ๊ด๋ จ ์์๋ฅผ ์ฝ๊ฒ ๋ค๋ฃฐ ์ ์๋ค.
ํด๋น API๋ resize
์ด๋ฒคํธ๋ฅผ ๋์ฒดํ์ฌ ์ข ๋ ํจ์จ์ ์ธ ์ด๋ฒคํธ ๋์์ ๊ตฌํํ ์ ์๋ค.
๋ค์ ์ฅ์์ MutationObserver
์ ๋ํด ๋ค๋ค๋ณด์.
๐ท๏ธ ํ๊ทธ
์ฝ์ด์ฃผ์ ์ ๊ณ ๋ง์์!
๋์์ด ๋์ จ๋ค๋ฉด, ๊ณต๊ฐ์ด๋ ๋๊ธ์ ๋ฌ์์ฃผ์๋ ๊ฑด ์ด๋ค๊ฐ์?
๋ธ๋ก๊ทธ ์ด์์ ํฐ ํ์ด ๋ฉ๋๋ค.