레슨 5 / 9·20분
Hooks 활용하기
useRef
useRef는 렌더링 사이에 값을 유지하되, 값이 변경되어도 리렌더링을 일으키지 않는 Hook입니다. DOM 요소에 접근하거나 이전 값을 저장할 때 사용합니다.
tsx
import { useRef, useEffect } from 'react';
function AutoFocusInput() {
const inputRef = useRef<HTMLInputElement>(null);
// 마운트 시 자동 포커스
useEffect(() => {
inputRef.current?.focus();
}, []);
return <input ref={inputRef} placeholder="자동 포커스" />;
}
// 렌더링 횟수 추적
function RenderCounter() {
const count = useRef(0);
useEffect(() => {
count.current += 1;
});
return <p>렌더링 횟수: {count.current}</p>;
}useMemo와 useCallback
useMemo는 비용이 큰 계산 결과를 메모이제이션하고, useCallback은 함수 참조를 메모이제이션합니다. 불필요한 재계산이나 자식 컴포넌트의 불필요한 리렌더링을 방지합니다.
tsx
import { useState, useMemo, useCallback } from 'react';
function ExpensiveList({ items, query }: {
items: string[];
query: string;
}) {
// 비용이 큰 필터링을 메모이제이션
const filtered = useMemo(() => {
console.log("필터링 실행");
return items.filter(item =>
item.toLowerCase().includes(query.toLowerCase())
);
}, [items, query]); // items나 query 변경 시만 재계산
// 콜백 함수 메모이제이션
const handleClick = useCallback((item: string) => {
console.log("선택:", item);
}, []); // 의존성 없음 — 함수가 변경되지 않음
return (
<ul>
{filtered.map(item => (
<li key={item} onClick={() => handleClick(item)}>
{item}
</li>
))}
</ul>
);
}커스텀 Hook
커스텀 Hook은 use로 시작하는 함수로, 여러 컴포넌트에서 재사용할 로직을 추출합니다. 내부에서 다른 Hook을 자유롭게 사용할 수 있습니다.
tsx
// 커스텀 Hook: localStorage와 동기화
function useLocalStorage<T>(key: string, initial: T) {
const [value, setValue] = useState<T>(() => {
const saved = localStorage.getItem(key);
return saved ? JSON.parse(saved) : initial;
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue] as const;
}
// 사용
function Settings() {
const [theme, setTheme] = useLocalStorage("theme", "light");
const [lang, setLang] = useLocalStorage("lang", "ko");
return (
<div>
<button onClick={() => setTheme(
theme === "light" ? "dark" : "light"
)}>
테마: {theme}
</button>
<select value={lang} onChange={e => setLang(e.target.value)}>
<option value="ko">한국어</option>
<option value="en">English</option>
</select>
</div>
);
}💡
useMemo와 useCallback은 성능 최적화 도구입니다. 모든 곳에 사용하면 오히려 코드 복잡도만 올라가므로, 실제 성능 문제가 있을 때만 적용하세요.