์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
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 |
- ๋ ธ๋ง๋ ์ฝ๋
- ์ํ์ฝ๋ฉ
- javascript
- ์ฝ๋ฉ์ผ๊ธฐ
- ํ๋ก ํธ์๋
- axios-mock-adapte
- next.js
- react
- ์น ๋ธ๋ผ์ฐ์ ๊ตฌ์กฐ
- jest
- clone coding
- JAVA Script
- canvas image
- ์น ๋ธ๋ผ์ฐ์ ๋ ๋๋ง
- HTML
- ๋ฐ๋๋ผ JS๋ก ํฌ๋กฌ ์ฑ ๋ง๋ค๊ธฐ
- HTML ํ์ผ๊ตฌ์กฐ
- negative margin
- JS
- canvas js
- ์ฝ๋ฉ๋ ํ
- typescript
- ์ฝ์ฝ์ํก ํด๋ก ์ฝ๋ฉ
- ๋ฐ๋๋ผ JS๋ก ๊ทธ๋ฆผํ ๋ง๋ค๊ธฐ
- queryprovider
- tailwindcss
- canvas
- ๋ ธ๋ง๋์ฝ๋
- tanstack-query
- CSS
- Today
- Total
Coding Archive
[Next.js] ๊ฒ์๊ธ ์ ๋ก๋ ํ์ด์ง: ๋์ ์ผ๋ก element ๋์ด ์กฐ์ ํ๊ธฐ(custom hook, throttle) ๋ณธ๋ฌธ
[Next.js] ๊ฒ์๊ธ ์ ๋ก๋ ํ์ด์ง: ๋์ ์ผ๋ก element ๋์ด ์กฐ์ ํ๊ธฐ(custom hook, throttle)
์ฝ๋ฑ์ด 2024. 11. 22. 18:03๊ฒ์๊ธ ์ ๋ก๋ ํ์ด์ง: ๋์ ์ผ๋ก element ๋์ด ์กฐ์ ํ๊ธฐ(custom hook, throttle)
โ ๏ธ ๋ฐฐ๊ฒฝ
๊ฒ์๊ธ ์ ๋ก๋ ํ์ด์ง๋ฅผ ๊ตฌํํ๋ฉด์, ํ ์คํธ๋ฅผ ์ ๋ ฅํ๊ธฐ ์ํ textarea์ ๋์ด๊ฐ ๊ณ ์ ๋์ด ์์ง ์๊ณ , ์ ๋ ฅ๋ ํ ์คํธ์ ์์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๋์ด๊ฐ ํ์ฅ๋๋ UI๊ฐ ํ์ํ์ต๋๋ค.
1. ํ ์คํธ ๊ธธ์ด์ ๋ฐ๋ฅธ ๋์ด ๋ณํ
์ฌ์ฉ์๊ฐ ์์ฑํ๋ ํ ์คํธ์ ์์ ๊ณ ์ ๋์ด ์์ง ์์ผ๋ฉฐ, ์์ฑ ๋์ค์ ๊ณ์ ์ฆ๊ฐํ๊ฑฐ๋ ๊ฐ์ํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ textarea์ ๋์ด๊ฐ ํ ์คํธ ์์ ๋ง์ถฐ ์ ์ฐํ๊ฒ ์กฐ์ ๋์ด์ผ ์ฌ์ฉ์ ๊ฒฝํ(UX)์ด ๊ฐ์ ๋ฉ๋๋ค.
2. CSS๋ง์ผ๋ก๋ ํด๊ฒฐ๋์ง ์๋ ์คํฌ๋กค ๋ฌธ์
min-height์ max-height๋ฅผ CSS๋ก ์ค์ ํ๋ฉด ๋์ด๋ฅผ ์ผ์ ๋ฒ์ ๋ด์์ ๊ณ ์ ํ ์ ์์ง๋ง, ํ ์คํธ๊ฐ ์ฆ๊ฐํด๋ textarea์ ํฌ๊ธฐ๊ฐ ์๋์ผ๋ก ํ์ฅ๋์ง ์๊ณ ํ ์คํธ๊ฐ ์๋ฆฌ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค.
-> ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด, ๋์ด๋ฅผ ํ ์คํธ์ ์์ ๋ฐ๋ผ ๋์ ์ผ๋ก ์กฐ์ ํ๋ ๋ก์ง์ ๊ตฌํํ๊ฒ ๋์์ต๋๋ค.
์ด ๊ธ์์๋ onInput ์ด๋ฒคํธ๋ฅผ ํ์ฉํ ๊ธฐ๋ณธ์ ์ธ ๊ตฌํ๋ถํฐ, ์ปค์คํ ํ ์ผ๋ก ๋ก์ง์ ์ถ์ํํ๊ณ ์ฑ๋ฅ ์ด์๋ฅผ throttle ํตํด ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ๊น์ง ์์ธํ ๋ค๋ค๋ณด๊ฒ ์ต๋๋ค.
๐ ๊ตฌํ ๋ฐฉํฅ
textarea์ ๋์ด๋ฅผ ํ ์คํธ ์์ ๋ฐ๋ผ ๋์ ์ผ๋ก ์กฐ์ ํ๋ ๋ก์ง์ ๊ตฌํํ๊ธฐ ์ํด ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ต๋๋ค.
- ํ ์คํธ ์ ๋ ฅ ์ด๋ฒคํธ ํ์ฉ (onInput) : ์ฌ์ฉ์๊ฐ ํ ์คํธ๋ฅผ ์ ๋ ฅํ๊ฑฐ๋ ์ญ์ ํ ๋๋ง๋ค textarea์ ๋์ด๋ฅผ ์กฐ์ ํ๋๋ก ์ค์ .
- scrollHeight ์์ฑ ํ์ฉ : textarea.scrollHeight๋ ํ ์คํธ ์ฝํ ์ธ ์ ์ ์ฒด ๋์ด๋ฅผ ๊ณ์ฐํ ์ ์๋ ์์ฑ์ผ๋ก ์ด๋ฅผ ํ์ฉํด ์ฝํ ์ธ ๋์ด์ ๋ง๊ฒ textarea์ ๋์ด๋ฅผ ์กฐ์ .
- style.height ์ด๊ธฐํ ํ ์ฌ์ค์ : ๊ธฐ์กด ๋์ด๋ฅผ ์ด๊ธฐํ(style.height = 'auto')ํ์ฌ ํ ์คํธ๊ฐ ์ค์ด๋๋ ๊ฒฝ์ฐ์๋ ์ ์ ํ ๋์ด๋ฅผ ๋ค์ ๊ณ์ฐํ ์ ์๋๋ก ์ฒ๋ฆฌ.
๊ธฐ๋ณธ ๊ตฌํ: onInput๋ฅผ ํ์ฉํ ๋์ ๋์ด ์กฐ์
textarea์ ๋์ด๋ฅผ ์ ๋ ฅ ๋ด์ฉ์ ๋ง๊ฒ ์๋์ผ๋ก ์กฐ์ ํ๋ ค๋ฉด ononInput ์ด๋ฒคํธ๋ฅผ ์ฌ์ฉํฉ๋๋ค. onInput์ ์ฌ์ฉ์๊ฐ ํ ์คํธ๋ฅผ ์ ๋ ฅํ ๋๋ง๋ค ์ด๋ฒคํธ๊ฐ ํธ๋ฆฌ๊ฑฐ๋์ด scrollHeight๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋์ด๋ฅผ ์กฐ์ ํฉ๋๋ค.
// UploadForm.tsx
import { useRef } from 'react';
interface IUploadFormProps {
className?: string;
}
export default function UploadForm({ className }: IUploadFormProps) {
const textareaRef = useRef<HTMLTextAreaElement>(null);
const handleTextChange = () => {
const textarea = textareaRef.current;
if (textarea) {
textarea.style.height = 'auto'; // ๋์ด ์ด๊ธฐํ
textarea.style.height = `${textarea.scrollHeight}px`; // ์
๋ ฅ ๋ด์ฉ์ ๋ฐ๋ผ ๋์ด ์กฐ์
}
};
return (
<textarea
ref={textareaRef}
onInput={handleTextChange}
rows={1}
placeholder="๋ด์ฉ์ ์
๋ ฅํ์ธ์"
className="resize-none w-full"
/>
);
}
- textarea์ ๋์ด๋ฅผ scrollHeight ๊ฐ์ผ๋ก ์ค์ ํ์ฌ ์ ๋ ฅ ๋ด์ฉ์ ๋ฐ๋ผ ๋์ด๊ฐ ์กฐ์ ๋ฉ๋๋ค.(textarea.scrollHeight: ์ฝํ ์ธ ์ ์ฒด ๋์ด)
- textarea.style.height = 'auto'๋ ๋์ด๋ฅผ ์ด๊ธฐํํ์ฌ ๊ธฐ์กด ๋์ด๋ฅผ ์ ๊ฑฐํ๊ณ ๋์ด ์กฐ์ ์ ๋ถ๋๋ฌ์์ ์ ์งํฉ๋๋ค.
- ์ต์ ๋์ด๋ rows={1}๋ก ์ค์ ํฉ๋๋ค.
๐ ๏ธ ๋ฆฌํฉํ ๋ง: ์ปค์คํ ํ ์ผ๋ก ๋ก์ง ์ถ์ํ
๋์ด ์๋ ์กฐ์ ์ ์ํ ๋ก์ง์ ๋ณ๋์ ํ (Hook)์ผ๋ก ์ถ์ํํ์ฌ ๋ค๋ฅธ ์ปดํฌ๋ํธ์ ๋ค์ํ DOM ์์์์ ์ฌ์ฌ์ฉํ ์ ์๋๋ก ๋ถ๋ฆฌํ์์ต๋๋ค.
useAutoResizeHeight ํ ์ ํด๋น ์์์ ๋ํ ์ฐธ์กฐ์ ํจ๊ป ์ ๋ ฅ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ์ฌ ๋์ด๋ฅผ ์๋์ผ๋ก ์กฐ์ ํ๋ ๋ก์ง์ ์บก์ํํฉ๋๋ค.
useAutoResizeHeight ์ปค์คํ ํ ์ ์
// useAutoResizeHeight.ts
import { useRef, useCallback } from 'react';
export function useAutoResizeHeight<T extends HTMLElement>() {
const elementRef = useRef<T>(null);
const adjustHeight = useCallback(() => {
const element = elementRef.current;
if (element) {
element.style.height = 'auto'; // ๋์ด ์ด๊ธฐํ
element.style.height = `${element.scrollHeight}px`; // ์ฝํ
์ธ ์ ๋ง๊ฒ ๋์ด ์กฐ์
}
}, []);
return { elementRef, resizeToFitContent };
}
- ์ ๋ค๋ฆญ ์ฌ์ฉ (T extends HTMLElement): textarea๋ฟ๋ง ์๋๋ผ ๋ค๋ฅธ DOM ์์์์๋ ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค.
- useCallback์ผ๋ก ์ต์ ํ: ๋์ผํ ํจ์๋ฅผ ์ฌ๋ฌ ๋ฒ ์์ฑํ์ง ์๋๋ก ํฉ๋๋ค.
useAutoResizeHeight ํ ์ UploadForm์์ ํ์ฉ
UploadForm์์ useAutoResizeTextarea ํ ์ ํธ์ถํ์ฌ elementRef์ resizeToFitContent์ ์ฌ์ฉํฉ๋๋ค.
// UploadForm.tsx
function UploadForm() {
const { elementRef, resizeToFitContent } = useAutoResizeHeight<HTMLTextAreaElement>();
return (
<textarea
className="scrollbar-hidden w-full resize-none text-14px focus:outline-none"
placeholder="๊ฒ์๊ธ ์
๋ ฅํ๊ธฐ..."
ref={elementRef}
onInput={resizeToFitContent}
rows={1}
/>
);
}
๊ฐ์ ํ ํจ๊ณผ
- UploadForm์์ UI ๋ก์ง๋ง ์ฒ๋ฆฌํ๊ณ , ๋น์ฆ๋์ค ๋ก์ง์ ํ ์ผ๋ก ๋ถ๋ฆฌํ์ฌ ๊ฐ๋ ์ฑ์ด ํฅ์๋์์ต๋๋ค.
- ๋ค๋ฅธ ์ปดํฌ๋ํธ์์๋ useAutoResizeHeight๋ฅผ ํธ์ถํด ๋์ผํ ๋์์ ๊ตฌํํ ์ ์๊ฒ ๋์ด ์ฌ์ฌ์ฉ์ฑ์ด ํฅ์๋์์ต๋๋ค. ํนํ DOM ์์์ ํ์ ์ ์ ๋ค๋ฆญ์ผ๋ก ๋ฐ์ ํ์ ์ค๋ฅ๋ฅผ ๋ฐฉ์งํ๊ณ , ๋ค์ํ UI ์ปดํฌ๋ํธ์์ ํ์ฉ ๊ฐ๋ฅํ๋๋ก ์ถ์ํํ ์ ์์์ต๋๋ค.
- useAutoResizeHeight๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ๋์ํ๋ฏ๋ก, ๋ณ๊ฒฝ์ด ํ์ํ ๋ ํด๋น ํ ๋ง ์์ ํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ ์ ์ง๋ณด์์ฑ์ด ํฅ์๋์์ต๋๋ค.
but, ์ด ๋ฐฉ์์ ๊ฐ๋จํ๋ฉด์๋ ์ ์ฉํ์ง๋ง ์ ๋ ฅ์ด ๋ง์์ง ๊ฒฝ์ฐ ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ด ์ฑ๋ฅ ์ต์ ํํ ์ ์๋ ๋ฐฉ๋ฒ์ด ํ์ํ์ต๋๋ค.
โจ ์ฑ๋ฅ ์ต์ ํ: throttle ํ์ฉ
onInput ์ด๋ฒคํธ๋ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๋๋ง๋ค ํธ๋ฆฌ๊ฑฐ๋๊ธฐ ๋๋ฌธ์ ์ ๋ ฅ ์๋๊ฐ ๋น ๋ฅด๊ฑฐ๋ ๋ง์์ง๊ฒ ๋๋ฉด ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด throttle์ ์ ์ฉํด ํธ์ถ ๋น๋๋ฅผ ์ ํํ๋๋ก ์์ ํ์์ต๋๋ค.
throttle์ด๋?
throttle์ ์ฃผ๊ธฐ์ ์ผ๋ก ๋ฐ์ํ๋ ์ด๋ฒคํธ๋ฅผ ์ผ์ ๊ฐ๊ฒฉ์ผ๋ก ์ ํํ์ฌ ์ฒ๋ฆฌํ๋ ์ฑ๋ฅ ์ต์ ํ ๊ธฐ๋ฒ์ ๋๋ค.
์ฆ, ์ด๋ฒคํธ๊ฐ ์๋ฌด๋ฆฌ ์์ฃผ ๋ฐ์ํ๋๋ผ๋ ์ค์ ๋ ์๊ฐ ๊ฐ๊ฒฉ ๋ด์์๋ ํ ๋ฒ๋ง ์คํ๋๋๋ก ํฉ๋๋ค.
throttle์ ๋์ ์๋ฆฌ
- ์ง์์ ์ผ๋ก ์ด๋ฒคํธ๊ฐ ๋ฐ์ : ์ฌ์ฉ์๊ฐ ๋น ๋ฅด๊ฒ ํ์ดํํ๊ฑฐ๋ ์คํฌ๋กคํ๋ ๊ฒฝ์ฐ์ฒ๋ผ, ์ด๋ฒคํธ๊ฐ ๋งค์ฐ ์งง์ ๊ฐ๊ฒฉ์ผ๋ก ๋ฐ๋ณต ๋ฐ์.
- ์ผ์ ํ ๊ฐ๊ฒฉ์ผ๋ก ์ด๋ฒคํธ ์คํ : ์ค์ ๋ ์๊ฐ ๊ฐ๊ฒฉ์ ๋ฐ๋ผ ์ด๋ฒคํธ๋ฅผ ์คํํ๊ณ , ๊ทธ ์ฌ์ด์ ์ด๋ฒคํธ๋ ๋ฌด์.
-> ์ผ์ ํ ์ฃผ๊ธฐ๋ก ์ด๋ฒคํธ๊ฐ ์คํ๋๋ฏ๋ก, ๊ณผ๋ํ ์ฐ์ฐ์ ๋ฐฉ์งํ๊ณ ์ฑ๋ฅ์ ์ต์ ํ.
throttle์ ์ ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ
throttle์ ์ด๋ฒคํธ๊ฐ ์ง์์ ์ผ๋ก ๋ฐ์ํ๋ ์ํฉ์์ ์ผ์ ๊ฐ๊ฒฉ์ผ๋ก๋ง ์คํ์ด ํ์ํ ๋ ์ ํฉํฉ๋๋ค.
- ์คํฌ๋กค ์ด๋ฒคํธ : ์ฌ์ฉ์๊ฐ ํ์ด์ง๋ฅผ ์คํฌ๋กคํ ๋ ์ด๋ฒคํธ๊ฐ ์๋ฐฑ ๋ฒ ํธ์ถ๋ ์ ์๊ธฐ ๋๋ฌธ์ ์คํฌ๋กค ์์น๋ฅผ ์ ๋ฐ์ดํธํ๊ฑฐ๋ ํน์ ์์น์ ๋๋ฌํ๋์ง ํ์ธํ๋ ๋ก์ง์ ์ ์ฉ.
- ์๋์ฐ ๋ฆฌ์ฌ์ด์ฆ ์ด๋ฒคํธ : ๋ธ๋ผ์ฐ์ ์ฐฝ ํฌ๊ธฐ๊ฐ ๋ณ๊ฒฝ๋ ๋ ๋ ์ด์์์ ์ ๋ฐ์ดํธํ๋ ๋ก์ง์ ์ง๋์น๊ฒ ๋น๋ฒํ ํธ์ถ์ ์ ํํ์ฌ ์ฑ๋ฅ์ ์ต์ ํ.
- ๋๋๊ทธ ์ค ๋๋กญ : ์ฌ์ฉ์๊ฐ ๋๋๊ทธํ ๋ ๋ง์ฐ์ค ์์น๋ฅผ ์ ๋ฐ์ดํธํ๋ ๋ก์ง์ ์ ์ฉํด UI ์ ๋ฐ์ดํธ ๋น๋๋ฅผ ์ ํ.
- ์ค์๊ฐ ์ ๋ ฅ ์ฒ๋ฆฌ : ์ ๋ ฅ ์ค์ ์ ๋๋ฉ์ด์ ์ด๋ ํ๋ฉด ์ ๋ฐ์ดํธ๊ฐ ํ์ํ ๊ฒฝ์ฐ(textarea์ ๋์ด๋ฅผ ์กฐ์ ํ๊ฑฐ๋, ์ ๋ ฅ ๋ด์ฉ์ ์ค์๊ฐ์ผ๋ก ๋ณด์ฌ์ฃผ๋ ๋ฏธ๋ฆฌ๋ณด๊ธฐ)์ ์ ์ฉ.
throttle vs debounce
throttle์์ด๋ฒคํธ ๋ฐ์ ๊ฐ๊ฒฉ์ ์ ํ, debounce๋ ์ด๋ฒคํธ ์คํ์ ์ง์ฐํฉ๋๋ค. ๋ ๊ธฐ๋ฒ์ ์ฐจ์ด๋ฅผ ์ดํดํ๋ฉด ์ ์ ํ ์ํฉ์์ ํ์ฉํ ์ ์์ต๋๋ค.
๊ตฌ๋ถ | throttle | debounce |
๋์ ๋ฐฉ์ | ์ง์ ๋ ๊ฐ๊ฒฉ๋ง๋ค ์ด๋ฒคํธ ์คํ | ์ด๋ฒคํธ ๋ฐ์ ํ ์ง์ ๋ ์๊ฐ ๋์ ๋๊ธฐ ํ ์คํ |
์ฌ์ฉ ์ฌ๋ก | ์คํฌ๋กค, ๋ฆฌ์ฌ์ด์ฆ, ๋๋๊ทธ, ์ค์๊ฐ UI ์ ๋ฐ์ดํธ | ๊ฒ์ ์๋์์ฑ, API ์์ฒญ, ์ฌ์ฉ์๊ฐ ์ ๋ ฅ์ ๋ฉ์ท์ ๋ ์คํ |
์ด๋ฒคํธ ์คํ | ์ง์์ ์ผ๋ก ๋ฐ์ํ๋ ์ด๋ฒคํธ ์ค ์ผ์ ๊ฐ๊ฒฉ์ผ๋ก ์คํ | ๋ง์ง๋ง ์ด๋ฒคํธ ํ ํ ๋ฒ๋ง ์คํ |
์ ํฉํ ๊ฒฝ์ฐ | ์ค์๊ฐ ์ ๋ฐ์ดํธ๊ฐ ํ์ํ ๊ฒฝ์ฐ | ์ด๋ฒคํธ ์ฒ๋ฆฌ๊ฐ ๋๋ ํ ์์ ์ด ํ์ํ ๊ฒฝ์ฐ |
Lodash throttle ์ ์ฉ
throttle์ ์ ์ฉํ์ฌ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋๋ผ๋, ๋ง์ง๋ง ์คํ ํ ์ต์ wait ์๊ฐ์ด ์ง๋์ผ ๋ค์ ์คํ๋ฉ๋๋ค.
throttle์ ๋ด๋ถ ์ํ๋ฅผ ๊ฐ์ง๋ฏ๋ก, React๊ฐ ์ปดํฌ๋ํธ ์ธ๋ง์ดํธ ์ ์ด๋ฅผ ํด๋ฆฐ์ ํด์ผ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
1. Lodash throttle์ ๋ด๋ถ ๋์
Lodash์ throttle์ ์ด๋ฒคํธ ์คํ์ ์ ํํ๊ธฐ ์ํด ๋ด๋ถ ์ํ๋ฅผ ์ ์งํฉ๋๋ค.
• ๋ง์ง๋ง์ผ๋ก ์คํ๋ ์๊ฐ(lastRan)
• ํ์ด๋จธ(timeout): ์์ง ์คํ๋์ง ์์ ๋๊ธฐ ์ค์ธ ํจ์
์ด๋ฌํ ์ํ๋ throttle๋ก ์์ฑ๋ ํจ์๊ฐ ๊ณ์ ์ ์ง๋๋ฉฐ ๊ด๋ฆฌํฉ๋๋ค.
2. React ์ปดํฌ๋ํธ์ ์๋ช ์ฃผ๊ธฐ
• React ์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ๋ ๋, throttle ํจ์ ๋ด๋ถ์ ํ์ด๋จธ(timeout)๊ฐ ์ฌ์ ํ ๋์ํ๊ณ ์๋ค๋ฉด ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
• ์๋ฅผ ๋ค์ด textarea์ ์ ๋ ฅ ์ด๋ฒคํธ๊ฐ ๋ฐ์ ์ค์ธ๋ฐ ์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ๋๋ฉด, ๋๊ธฐ ์ค์ด๋ throttle ํจ์๊ฐ ์ฌ์ ํ ์คํ๋ ์ ์์ต๋๋ค.
3. Cleanup์ ํ์์ฑ
• ์ปดํฌ๋ํธ ์ธ๋ง์ดํธ ์ throttle ํจ์์ ํ์ด๋จธ์ ์ํ๋ฅผ ์ ๋ฆฌํด ์ฃผ์ด์ผ ๋ฉ๋ชจ๋ฆฌ ๋์์ ๋ถํ์ํ ์ฐ์ฐ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
• Lodash์ throttle์ cancel() ๋ฉ์๋๋ฅผ ์ ๊ณตํ์ฌ ํ์ด๋จธ์ ๋ด๋ถ ์ํ๋ฅผ ์ ๋ฆฌํ ์ ์์ต๋๋ค.
import { useRef, useCallback } from 'react';
import { throttle } from 'lodash';
export function useAutoResizeHeight<T extends HTMLElement>(throttleTime = 100) {
const elementRef = useRef<T|null>(null);
const resizeToFitContent = useCallback(() => {
const element = elementRef.current;
if (element) {
element.style.height = 'auto';
element.style.height = `${element.scrollHeight}px`;
}
}, []);
// Throttled function ์์ฑ
const throttledResize = useMemo(() => throttle(resizeToFitContent, throttleTime), [
resizeToFitContent,
throttleTime,
]);
// Cleanup: Throttle ํจ์ ์ทจ์
useEffect(() => {
return () => {
throttledResize.cancel(); // Throttled ํจ์ ์ ๋ฆฌ
};
}, [throttledResize]);
return { elementRef, throttledResize };
_throttle ์บ์ฑ
• useMemo๋ก throttle๋ก ์์ฑ๋ ํจ์๋ฅผ ์บ์ฑํด ๋งค๋ฒ ์๋ก ์์ฑ๋์ง ์๋๋ก ์ค์ ํฉ๋๋ค.
• ๋ฉ๋ชจ์ด์ ์ด์ ์ ํตํด ๋์ผํ ์์กด์ฑ ๋ฐฐ์ด(deps)์ ๊ฐ์ง๋ ๋์ ๊ธฐ์กด์ throttle ํจ์๊ฐ ์ฌ์ฌ์ฉ๋ฉ๋๋ค.
• ์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ๋๊ธฐ ์ ์๋ throttle ํจ์์ ๋ด๋ถ ์ํ(์: ํ์ด๋จธ)๊ฐ ์ ์ง๋ฉ๋๋ค.
_Cleanup ์ฒ๋ฆฌ:
• useEffect Cleanup์ ํ์ฉํด throttledResize.cancel()์ ํธ์ถํ์ฌ ์ธ๋ง์ดํธ ์ throttle์ ํ์ด๋จธ(timeout)์ ๋ด๋ถ ์ํ๋ฅผ ์ ๋ฆฌํฉ๋๋ค.
• ๋ฉ๋ชจ์ด์ ์ด์ ์ ์ ์งํ๋ฉด์๋ ์ปดํฌ๋ํธ ์๋ช ์ฃผ๊ธฐ์ ๋ฐ๋ผ throttle์ ์์ ํ ์ข ๋ฃํ์ฌ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
throttle ์ ์ฉ ํ ํจ๊ณผ
- ๊ณผ๋ํ ์ด๋ฒคํธ ํธ์ถ์ด ์ ํ๋์ด ๋ถํ์ํ DOM ์กฐ์์ ๋ฐฉ์งํ์ฌ ์ฑ๋ฅ์ ๋ณด๋ค ํจ์จ์ ์ผ๋ก ๊ฐ์ ํ์์ต๋๋ค.
- ์ฌ์ฉ์ ์ ๋ ฅ ์๋๊ฐ ๋นจ๋ผ๋ ๋ถ๋๋ฝ๊ฒ ๋์ํ์ฌ ์ฌ์ฉ์ ๊ฒฝํ์ด ํฅ์๋์์ต๋๋ค.
- ๋น ๋ฅด๊ฒ ํ์ดํํ ๋๋ ์ง์ ๋ ๊ฐ๊ฒฉ์ผ๋ก๋ง ์ด๋ฒคํธ๋ฅผ ์คํํ์ฌ CPU ๋ถํ๋ฅผ ์ค์ฌ ๊ฒฐ๊ณผ์ ์ผ๋ก ํจ์จ์ ์ผ๋ก ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํ๊ฒ ๋์์ต๋๋ค.
- throttle์ ํ์ฉํ์ฌ ๋ณต์กํ ๋ก์ง ์์ด ๊ฐ๋จํ ์ต์ ํ ๊ตฌํํ ์ ์์์ต๋๋ค.
๋งค๋ฒ ์ฝ๋๋ฅผ ์์ฑํ ๋๋ง๋ค ๋๋ผ๋ ๊ฑฐ์ง๋ง ๋จ์ํ ๋์ํ๋ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์์ ๊ทธ์น์ง ์๊ณ , ์ฑ๋ฅ ์ต์ ํ์ ์ ์ง๋ณด์์ฑ๊น์ง ๊ณ ๋ คํ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋ํ ์ค์์ฑ์ ์ค๊ฐํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
textarea์ ๋์ ๋์ด ์กฐ์ ์ ์์ UX ๊ฐ์ ์ด์ง๋ง, ์ปค์คํ ํ ๊ณผ ์ต์ ํ๋ฅผ ํตํด ํ์ฅ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ๋์์ ๊ฐ์ถ ์๋ฃจ์ ์ ๊ตฌํํ ์ ์์์ต๋๋ค.