-
React 딥다이브프론트엔드 2025. 10. 20. 14:10
React hook 알아보기
useCallback
- useMemo가 값을 기억했다며느 useCallbak은 인수로 넘겨받은 콜백 자체를 기억한다.
- 즉 useCallback은 특정 함수를 새로 만들지 않고 다시 재사용한다는 의미이다.
🧐 음 솔직히 뭔지 모르겠다 ... 예시를 보자아
✅ 확인하고 넘어가기
- React에서 리 렌더링이 일어나면 함수가 다시 만들어지고 다시 실행이 된다. -> 이로 인해 함수 내부 변수가 함수 등이 다른 메모리 주소를 가르킨다."use client"; import { useEffect, useState } from "react"; export default function SignupPage() { const [step, setStep] = useState(1); const onClick = () => { setStep(step + 1); }; useEffect(() => { console.log("click"); }, [onClick]); return ( <div> {step} <button onClick={onClick}>next</button> </div> ); }- 다음과 같은 예제를 보자 버튼을 클릭하면 onClick 함수가 실행이 된다. 그로 인데 setState 상태가 변경이 되어 리액트가 리렌더링을 일으킨다.
- 리렌더링이 일어나니 컴포넌트 내부에 있는 모든 변수, 함수가 다시 생성되고 실행된다. 이로 인해 버튼을 클릭하면 click이라는 콘솔이 나오게 된다. 그렇다면 실행이 되지 말아야 하는 함수의 경우 메모이제이션이 필요하지 않을까??? 해서 나온것이 useCallback이다.
"use client"; import { useCallback, useEffect, useState } from "react"; export default function SignupPage() { const [step, setStep] = useState(1); const onClick = useCallback(() => { setStep(step + 1); }, [step]); useEffect(() => { console.log("click"); }, [onClick]); return ( <div> {step} <button onClick={onClick}>next</button> </div> ); }- useCallback은 다음과 같이 사용하면 된다. 의존성 배열의 값이 변경이 되면 메모이제이션이 된 onClick 함수가 실행이 된다. 음 근데 결국 똑같이 버튼 클릭하면 리렌더링 발생하는거자나???? 🧐 맞긴하다. 하지만 다른 예제를 보면 왜 사용하면 좋은지 알 수 있다.
"use client"; import { useCallback, useState } from "react"; function Child({ onClick }: { onClick: () => void }) { console.log("🧒 자식 리렌더링"); return <button onClick={onClick}>자식 버튼</button>; } export default function SignupPage() { const [count, setCount] = useState(0); // ❌ 리렌더링될 때마다 새로운 함수가 생성됨 const handleClick = useCallback(() => { console.log("clicked"); }, []); console.log("👩 부모 리렌더링"); return ( <div> <p>count: {count}</p> <button onClick={() => setCount(count + 1)}>부모 버튼</button> <Child onClick={handleClick} /> </div> ); }- 위예제를 보면 부모 컴포넌트가 자식 컴포넌트한테 onClick이라는 props를 전달해서 자식 컴포넌트가 이를 사용중인데, 부모 컴포넌트가 리렌더링이 발생하면 자식 컴포넌트 또한 강제로 리렌더링이 되는 것을 볼 수 있다.
- 이유는 부모컴포넌트의 setCount로 인해 상태 변경이 되어 전체 리렌더링이 발생하는데 자식 또한 props가 변경되었다고 판단해 리렌더링이 발생한다. 이를 useCallback을 쓰면 음 근데 부모 리렌더링 이랑 자식 리렌더링 둘다 발생하는데 ??? 😱
useCallback
- useCallback은 함수 주소를 고정시켜주는 것이지, 리렌더링 방지하는 기능은 따로 없다는 것을 알았다...
- 위 원인을 찾아보니 결국 props의 값이 변경이 되지 않더라도 부모 컴포넌트가 리렌더링이 발생하니 같이 리렌더링이 발생하는 것이었다...
이를 통해 useCallback은 함수 메모리 주소를 고정시켜주지만, 결국 리렌더링이 일어난다는 것을 알게되었다...
해결방안은 의존성 배열에 따라 리렌더링 되도록 하는 것이 useCallback을 유연하게 사용하는 것이다useCallback + React.memo
- 두 훅을 같이 사용하면 최적화하는데 도움이 될거 같다. useCallback은 함수의 참조 값을 고정시키고 React.memo는 props를 비교해 같다면 리렌더링을 방지하니 이 둘을 혼합해서 사용해보자
useRef
- useRef는 useState와 비교할 때 컴포넌트 내부에서 렌더링이 일어나도 변경 가능한 상태값을 저장하고 있다. 하지만 2가지 차이가 있다.
- useRef는 반환값인 객체 내부에 있는 current로 값에 접근 변경할 수 있다
- useRef는 그 값이 변하더라도 렌더링을 발생시키지 않는다.
- 여기서 알 수 있는 점은 useRef는 값의 변경이 일어나도 리렌더링이 발생하지 않는다는 것이다.
- 보통 useRef는 검색 엔진을 최적화할때 사용하면 좋을거 같다.
- ⚠️ 여기서 주의할 점은 리렌더링이 발생하지 않아 화면상에는 변경점을 찾아볼 수 없다는 것이다.
'프론트엔드' 카테고리의 다른 글
React Activity? (0) 2026.03.12 쿠키, 세션, 스토리지 (1) 2025.12.06 프로젝트를 하면서 고민점들 (라우팅 렌더링) (0) 2025.10.18 React 딥다이브 (1) 2025.10.17 React 딥다이브 (1) 2025.10.16