June 10, 2021
리액트 Hooks 로 개발을 하다보면, 컴포넌트가 리렌더링 될 때 컴포넌트 내부에 있는 모든 일반함수가 리렌더링 되는 것을 알 수 있다.
이것은 매우 비효율적인 작업이기 때문에 리액트에서는 useCallback 이라는 api 를 제공해준다. 그래서 나는 이제껏 컴포넌트 내부에서 정의되는 대부분의 함수에 useCallback을 사용해왔다. 왜냐하면, 불필요한 리렌더링을 막고싶어서이다.
하지만 때때론, useCallback으로 함수를 감싸는게 더 부담되는 작업일 수 있다. 그렇게 되면 useCallback으로 감싸진 함수는 결국 오버엔지니어링의 산물이 되고, 성능 개선하려다가 성능 저하만 야기시키는 셈이 된다.
그러면 언제 useCallback을 써야하고, 언제 쓰지 말아야할까?
함수가 업데이트
될 수 있도록 변경할 수 있다. 함수를 메모라이징 해놓는다면 함수 내부에서 사용되는 상태값 역시 메모라이징 된 상태이다. 따라서, 상태값에 따라 함수 연산을 달리 해야한다면 Dependency 배열에 상태값을 넣어주면 된다.렌더링 성능이 최적화 된 자식 컴포넌트에 함수를 Props로 넘겨주는 경우
여기서 렌더링이 최적화 된이란, 자식 컴포넌트가 Props 변경의 영향을 많이 받지 않아야하는 경우를 일컫는다. 즉, 컴포넌트를 React.memo로 감싸고 있는 경우가 그러하다.
만약 연산이 복잡한 함수를 useCallback으로 감싸고 해당 컴포넌트에 렌더링이 자주 일어난다면 성능 최적화를 위한 것이라고 볼 수 있겠다. 하지만 아래와 같은 경우는 정말 useCallback을 사용하는게 괜한 메모리낭비이므로 사용하지 말도록 하자.
단순히 함수 내부에서 setState나 dispatch 함수를 호출하는 경우
cosnt handleChange = useCallback((newState)=>{ setState(newState) },[]);
왜냐하면, 이미 리액트 자체에서 useState 와 useDispatch 에 대한 성능 최적화를 보장해주고 있기 때문이다. 렌더링이 새로 되어도 setState함수와 dispatch 함수는 새로 생성되지 않는다.
당연하다. 그들도 Hooks API 이기 때문이다.