내가 헷갈리는 훅들인 useRef, useMemo, useCallback에 대해서 정리하려고 한다.
useRef
1. 무엇을 기억? : 변경 가능한 값 혹은 DOM 요소의 참조
2. 렌더링에 영향? : 값이 바뀌어도 컴포넌트는 다시 렌더링되지 않음
3. 렌더와 상관없이 값을 저장할 때 사용 (ex. 타이머 ID, 이전 상태값 저장) / DOM 엘리먼트에 직접 접근할 때 (ref 연결)
import { useRef } from "react";
function Timer() {
const timerId = useRef(null);
const startTimer = () => {
timerId.current = setInterval(() => {
console.log("Tick");
}, 1000);
};
const stopTimer = () => {
clearInterval(timerId.current);
};
return (
<>
<button onClick={startTimer}>시작</button>
<button onClick={stopTimer}>멈춤</button>
</>
);
}
타이머 ID 저장
- setInterval이나 setTimeout을 쓸 때, 타이머를 멈추거나 초기화하려면 타이머 ID 필요
const timerId = setInterval(() => {
console.log("Tick");
}, 1000);
- 이 timerId는 렌더링과 상관없이 계속 유지되어야 하므로 useRef에 저장!
- 즉, 컴포넌트가 렌더링돼도 새 타이머가 계속 만들어지는 것을 막기 위함이다.
이전 상태값 저장
- 상태가 바뀔 때 이전 상태와 비교하거나, 상태 변경 전에 값을 기억해야 할 때 사용
const [count, setCount] = useState(0);
const prevCount = useRef(0);
useEffect(() => {
if (count !== prevCount.current) {
console.log("count가 바뀜:", count);
prevCount.current = count; // 이전 값을 업데이트
}
}, [count]);
- count가 변할 때마다 useEffect가 실행되고 리렌더링 됨. (count - 0 -> 1)
- 하지만 prevCount는 리렌더링의 영향을 받지 않으므로 prevCount -> 0
- if (count !== prevCount.current) 를 만족하며 prevCount -> count -> 1로 업데이트
- 즉, prevCount는 리렌더링 전의 count 값을 가리키고 있다가, 리렌더링 이후에 새 값으로 업데이트
useMemo
1. 무엇을 기억? : 함수 결과값 (계산 결과)
2. 렌더링에 영향? : 직접 렌더를 일으키지는 않지만, 의존성이 바뀌면 다시 계산됨
3. 무거운 계산 결과를 메모리에 저장해두고 재사용 / 렌더마다 같은 계산 반복하는 낭비 방지
import { useMemo, useState } from "react";
function ExpensiveCalculation({ number }) {
const squared = useMemo(() => {
console.log("계산 중...");
return number * number;
}, [number]);
return <div>제곱: {squared}</div>;
}
useCallback
1. 무엇을 기억? : 함수 자체 (함수의 참조)
2. 렌더링에 영향? : 직접 렌더를 일으키지 않으며, 의존성이 바뀌면 새 함수 생성
3. 자식 컴포넌트에 함수를 props로 넘길 때 불필요한 리렌더 방지 / 이벤트 핸들러 같은 함수 재생성 비용 줄이기
import { useCallback, useState } from "react";
function ClickCounter() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount((c) => c + 1);
}, []);
return <button onClick={handleClick}>클릭 {count}회</button>;
}
자식 컴포넌트에 함수를 props로 넘길 때
- 함수 참조가 바뀌게 될 경우(부모 컴포넌트 리렌더링) 자식 컴포넌트도 불필요하게 리렌더링 될 수 있다.
- useCallback을 사용하면 부모가 리렌더돼도 같은 함수 객체를 자식에게 넘기기 때문에 불필요한 자식 리렌더링을 막아준다.
Hook | 기억하는 대상 | 렌더링에 영향 | 의존성 배열 존재 | 주용도 |
useRef | 변경 가능한 값, DOM 참조 | 없음 | 없음 | 렌더와 상관없는 값 저장, DOM 접근 |
useMemo | 함수 실행 결과 값 | 의존성 바뀔 때 재계산 | 있음 | 무거운 계산 결과 캐싱 |
useCallback | 함수 참조 | 의존성 바뀔 때 새 함수 생성 | 있음 | 함수 재생성 방지, 자식 리렌더 방지 |
'개발 > React' 카테고리의 다른 글
Typography - MUI (1) | 2025.08.11 |
---|---|
[React] 영화 추천 사이트 제작하기 (마무리) (3) | 2024.11.13 |
[React] 영화 추천 사이트 제작하기 (3) (8) | 2024.11.10 |
[React] 영화 추천 사이트 제작하기 (2) (2) | 2024.11.08 |
[React] 영화 추천 사이트 제작하기 (1) (23) | 2024.11.07 |