조회 1,253
익명
3월 17일
useCallback과 useMemo를 잘 쓰지 못하면 사용하느니만 못하다는 이야기를 들었는데, 그럼 useCallback과 useMemo 가 유용한 경우는 어떤 경우일까요?
구체적이고 정성스러운 질문에 ↑Up 투표를 눌러주세요.
설명이 부족한 질문에 ↓Down 투표를 눌러주세요. 커리어리가 질문자에게 수정을 요청할게요.
답변 5
BEST 답변
설명 전에 먼저 두 가지 배경 지식을 알고 계셔야 합니다. 1. 기본적으로 React 컴포넌트는 리렌더링이되면 모든 자식들을 재귀적으로 다시 렌더링합니다. 2. React 컴포넌트 안에 정의된 함수는 렌더링마다 매 번 새로 생성됩니다. 이 배경지식을 가지고 아래의 시나리오를 읽어보시면 최적화가 어느 부분에서 필요한지를 유추해보실 수 있습니다. 1. Parent와 Child 컴포넌트가 있음 2. Parent에서 Child 컴포넌트에 handleSubmit 이라는 함수를 전달함 3. Parent 컴포넌트가 1초에 100번 렌더링됨, 이 때 handleSubmit도 100번 재생성됨 4. Child 컴포넌트는 handleSubmit이 100번 바뀌므로 Child 컴포넌트도 100번 리렌더링됨 어느 부분에서 최적화가 필요한지 감이 오시나요? 3번을 보면 handleSubmit이 100번 재생성되서 Child 컴포넌트에 불필요한 리렌더링을 유발하여 퍼포먼스 이슈를 발생시키는 것을 확인할 수 있습니다. 이 때, useCallback/useMemo를 사용하면 자식 컴포넌트의 불필요한 리렌더링을 방지할 수 있습니다. '그냥 되는대로 함수에 useCallback/useMemo를 갖다 쓰면 성능은 보장되는거 아닌가요?' 라는 악마의 유혹에 빠질수도 있습니다. 하지만 모든 것에 공짜는 없다는 사실을 기억하셔야 합니다. useCallback/useMemo는 내가 정의한 함수를 메모리에 기억하는 방식으로 최적화를 합니다. 렌더링이 여러 번 일어나도 브라우저가 이를 기억하고 있기 때문에 다시 함수를 만들지 않는 겁니다. 브라우저가 이를 기억한다는 건 무슨 의미일까요? 메모리에 함수를 저장한다는 뜻입니다. 즉, 모든 함수를 훅으로 감싼다면 브라우저의 메모리 사용량도 비례해서 커진다는 의미입니다. 따라서, 정말 필요한 경우에만 최적화를 진행하시면 됩니다.
익명
작성자
3월 22일
좋은 답변 감사합니다! 정말 공짜는 없네요 ㅎㅎ
흥미로워 보이는 글이 있어서 추천드립니다. https://github.com/yeonjuan/dev-blog/blob/master/JavaScript/should-you-really-use-usememo.md usememo가 언제 도움이 되는지 실험한 글인데, 결론이 이렇다고 하네요! - 복잡도가 100 미만이면 useMemo가 별로 도움이 되지 않음. - 복잡도가 5000 이상인 데이터 처리가 있고 어느 정도 리렌더링이 발생한다면 useMemo가 도움이 됨. - 초기 렌더링 비용은 useMemo를 사용하면 훨씬 더 비싸지만, 후속 렌더링에서는 훨씬 성능이 향상됨.
현재 진행 중인 프로젝트에서 실제 용례를 말씀드려봅니다. eCharts를 사용 중이고 차트에 점을 표시합니다. fetch를 통해 새로운 데이터를 주기적으로 갱신하고, 기존과 비교해서 새로운 데이터가 있는 경우에만 리렌더링이 발생해야 하는데 컴포넌트가 마운트되고 나서부터 계속해서 리렌더링이 발생하는 버그가 있었습니다. 'useCallback'을 사용해서 데이터 의존성을 넘겨주니 문제가 해결되었습니다.
1// 실제 코드에서 많이 생략했습니다.
2export default function ScatterChart({ data }: ChartProps) {
3 const initialChartData: ChartData[] = [];
4 const chartRef = useRef(null);
5
6 const updateChartData = useCallback(() => {
7 try {
8 if (!chartRef.current) return;
9
10 const chartInstance = (chartRef.current as ReactECharts).getEchartsInstance();
11 chartInstance.setOption<echarts.EChartsOption>({
12 // 생략
13 });
14 } catch (error) {
15 console.error(error);
16 }
17 }, [data]);
18
19 // ... 중략 ...
20
21 useEffect(() => {
22 updateChartData();
23 });
24
25 return (
26 <ReactECharts ref={chartRef} option={initialOption} opts={{ renderer: 'canvas' }} />
27 );
28}
지금 가입하면 모든 질문의 답변을 볼 수 있어요!
현직 개발자들의 명쾌한 답변을 얻을 수 있어요.
이미 회원이신가요?
지금 가입하면 모든 질문의 답변을 볼 수 있어요!
현직 개발자들의 명쾌한 답변을 얻을 수 있어요.