ReactJS - useCallback 사용법: 초보자 가이드

안녕하세요, 미래의 React 개발자 여러분! 오늘 우리는 React의 강력한 훅 중 하나인 useCallback에 대해 깊이 다루어보겠습니다. 프로그래밍에 처음 도전하는 분이라면 걱정하지 마세요; 저는 여러분을 단계별로 안내해드릴 것입니다. 여러 해 동안 많은 학생들을 가르쳐온 경험을 바탕으로 말이죠. 이 흥미로운 여정을 함께 시작해보겠습니다!

ReactJS - Using useCallback

useCallback는 무엇인가요?

자, 구체적인 내용으로 들어가기 전에 useCallback에 대해 이해해보겠습니다. 쿠키를 만드는 것을 상상해보세요 (이 비유는 정말 좋아요. 누가 쿠키를 좋아하지 않을까요?). 매번 사용하는 특별한 레시피가 있죠. useCallback은 그 레시피를 한 번 작성하고 필요할 때마다 사용하는 것과 같습니다. 매번 기억하려고 노력할 필요 없이요.

React의 용어로는, useCallback은 우리의 애플리케이션 성능을 최적화하기 위해 함수를 메모이즈(기억)하는 훅입니다.

useCallback 훅의 서명

먼저 useCallback을 어떻게 작성하는지 보겠습니다:

const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);

πανκ! 이 부분이 복잡해 보일 수 있지만, 단계별로 설명해드리겠습니다:

  1. memoizedCallback: 이는 useCallback이 반환하는 함수입니다.
  2. () => { doSomething(a, b); }: 이는 메모이즈할 함수입니다.
  3. [a, b]: 이는 의존성 배열입니다. React가 함수를 다시 생성해야 할 때를 알려줍니다.

이렇게 생각해보세요: React에게 "이 함수를 기억하고, ab가 바뀌지 않는 한 새로운 함수를 주지 말아줘"라고 말하는 것입니다.

useCallback 적용하기

이제 useCallback을 간단한 예제로 실제로 사용해보겠습니다:

import React, { useState, useCallback } from 'react';

function Counter() {
const [count, setCount] = useState(0);

const increment = useCallback(() => {
setCount(c => c + 1);
}, []);

return (
<div>
Count: {count}
<button onClick={increment}>Increment</button>
</div>
);
}

이를 단계별로 설명해보겠습니다:

  1. useCallback을 React에서 import합니다.
  2. useState를 사용하여 count 상태 변수를 생성합니다.
  3. useCallback을 사용하여 increment 함수를 정의합니다. 이 함수는 count을 1 증가시킵니다.
  4. 빈 배열 []을 두 번째 인자로 제공하여 이 함수는 절대로 바뀌지 않음을 의미합니다.
  5. count과 버튼을 렌더하여, 버튼을 클릭할 때 increment를 호출합니다.

useCallback의 사용 사례

이제 useCallback을 언제 사용해야 할지 고민이 드실 수도 있습니다. 훌륭한 질문입니다! 몇 가지 일반적인 시나리오를 살펴보겠습니다:

1. 최적화된 자식 컴포넌트에 콜백을 전달하기

자식 컴포넌트가 React.memo로 감싸인 경우를 상상해보세요. 이 컴포넌트에 함수를 전달하고 싶습니다:

import React, { useState, useCallback } from 'react';

function ParentComponent() {
const [count, setCount] = useState(0);

const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]);

return (
<div>
<ChildComponent onClick={handleClick} />
<p>Count: {count}</p>
</div>
);
}

const ChildComponent = React.memo(({ onClick }) => {
console.log("Child rendered!");
return <button onClick={onClick}>Increment</button>;
});

여기서 useCallbackhandleClickcount이 바뀔 때만 변경되도록 해서 ChildComponent의 불필요한 재랜더링을 방지합니다.

2. useEffect 의존성에 사용하기

useCallbackuseEffect 훅의 의존성으로 사용할 때도 유용합니다:

import React, { useState, useCallback, useEffect } from 'react';

function DataFetcher() {
const [data, setData] = useState(null);

const fetchData = useCallback(() => {
// API에서 데이터를 가져오는 것을 상상해보세요
setTimeout(() => setData("New Data!"), 1000);
}, []);

useEffect(() => {
fetchData();
}, [fetchData]);

return <div>{data ? data : "Loading..."}</div>;
}

이 예제에서 useCallbackfetchData가 매 랜더링마다 변경되지 않도록 해서 효과가 불필요하게 실행되지 않도록 합니다.

useCallback의 장단점

useCallback의 장점과 단점을 요약해보겠습니다:

장점 단점
불필요한 재랜더링을 방지합니다 코드가 더 복잡해질 수 있습니다
자식 컴포넌트의 성능을 최적화합니다 과도한 사용이 성능 문제를 일으킬 수 있습니다
useEffect 의존성에 유용합니다 클로저와 메모이제이션 이해가 필요합니다
안정적인 콜백을 만듭니다 간단한 컴포넌트에서는 큰 이점이 없을 수 있습니다

결론

와우! 오늘 많은 내용을 다루었습니다. useCallback은 여러분의 React 도구箱에서 강력한 도구입니다. 하지만 모든 도구처럼, 지혜롭게 사용해야 합니다. React의 여정을 계속하면서, 언제 useCallback을 사용해야 하는 직감을 키워갈 수 있을 것입니다.

최적화는 좋지만, 명확하고 읽기 쉬운 코드는 더 중요합니다. useCallback을 어디서나 사용하的压力을 늦추세요 – 애플리케이션에 적합한 경우에만 사용하세요.

계속 연습하고, 호기심을 가지고, 행복하게 코딩하세요! 그리고 기억하세요, 완벽한 쿠키 레시피를 완성하는 것처럼, React 마스터하기는 시간과 인내가 필요합니다. 여러분이 할 수 있습니다!

Credits: Image by storyset