본문 바로가기
SPA/React

[React] Hooks - useCallback

by J4J 2021. 9. 15.
300x250
반응형

안녕하세요. J4J입니다.

 

이번 포스팅은 hooks의 useCallback에 대해 적어보는 시간을 가져보려고 합니다.

 

 

 

useCallback이란?

 

useCallback은 hooks에서 메모이제이션을 이용해 함수를 재사용함으로 써 최적화를 해주는 역할을 담당합니다.

 

예를 들어 어떤 상황에서든 항상 동일한 결과값을 제공해주는 함수(= 순수 함수)가 있다고 가정해보겠습니다.

 

리액트를 개발하다보면 빈번하게 리 렌더링의 상황이 발생되는데 이때 항상 동일한 결괏값을 제공해주는 함수들도 함께 리 렌더링이 이루어집니다.

 

이것은 다른 말로 데이터를 지웠다가 똑같은 상태의 함수를 다시 생성하는 불필요한 작업을 한다고도 말할 수 있습니다.

 

그리고 이런 작업들이 한 개, 두 개 점점 쌓여나가면 결국 서비스의 속도에 영향을 미칠 수 밖에 없게 됩니다.

 

 

 

이런 상황에서 만약 메모이제이션을 사용하여 함수를 저장해 두고 있다면 어떨까요?

 

리 렌더링이 발생될 때 제거했다가 다시 처음부터 만들어내는 것이 아니라 저장된 곳에서 이미 만들어져 있는 함수를 가져오기만 한다면 더 빠른 속도로 렌더링이 되는 것을 도울 수 있습니다.

 

함수 리렌더링에 있어 이런 역할을 해주는 녀석이 바로 useCallback입니다.

 

 

 

여기서 한 가지 알고 가셔야 될 점은 메모이제이션, 캐시 메모리 저장 등을 할 때에도 어느 정도의 작업시간이 소요가 됩니다.

 

그렇기 때문에 재사용성이 거의 발생하지 않는 곳에도 해당 기술들을 적용하게 된다면 오히려 서비스 속도를 더 늦춰버리는 결과를 초래할 수 있습니다.

 

하지만 반대로 재사용이 빈번하게 발생되는 곳에 사용하게 된다면 재사용의 횟수가 많아질수록 더욱 큰 장점으로 다가오게 됩니다.

 

 

 

useCallback의 사용방법은 매우 단순합니다.

 

우선 관련 메서드는 'react'패키지에서 제공해주기 때문에 리액트로 개발되는 곳 어디서든 가져다 사용할 수 있습니다.

 

vscode에서 제공해주는 useCallback에 대한 정보를 확인해보시면 다음과 같습니다.

 

function React.useCallback<() => string>(callback: () => string, deps: React.DependencyList): () => string

 

 

반응형

 

 

파라미터는 총 2개를 입력할 수 있습니다.

 

첫 번째 파라미터인 callback에는 메모이제이션을 적용할 함수를 넣어주시면 됩니다.

 

두 번째 파라미터인 deps에는 callback에 집어넣은 함수의 리 렌더링이 될 수 있는 의존관계가 될 변수들을 배열의 형태로 집어넣어 주시면 됩니다.

 

여기서 배열의 요소로 들어가는 데이터들에 변경점이 생길때마다 callback에 해당하는 함수가 리 렌더링이 되고 변경점이 생기지 않거나 또는 빈 배열을 입력하게 될 때는 리 렌더링이 발생되지 않습니다.

 

 

 

리턴 값으로는 문자열이 나옵니다.

 

해당 문자열을 변수에 저장하여 함수처럼 사용해주시면 됩니다.

 

 

 

useCallback과 관련된 간단한 예시 코드를 작성해보겠습니다.

 

 

 

예시 코드

 

다음과 같은 코드를 작성해보겠습니다.

 

  • 이름과 나이에 해당하는 값들을 추가적인 문자열과 함께 출력될 수 있는 메서드들을 생성
  • 이름과 나이를 각각 변경할 수 있는 텍스트를 생성
  • 텍스트에 값을 입력하고 변경버튼을 클릭할 경우 화면에 출력되는 이름과 나잇값을 변경
  • 이름을 출력하는 메서드에는 useCallback을 적용

 

 

 

간단하게 App.jsx는 다음과 같이 작성해보겠습니다.

 

import * as React from 'react';
import MyComponent from './myComponent';

const App = () => {
    const [name, setName] = React.useState('');
    const [age, setAge] = React.useState(0);

    const [nameText, setNameText] = React.useState('');
    const [ageText, setAgeText] = React.useState(0);

    const onClickButton = () => {
        setName(nameText);
        setNameText('');

        setAge(ageText);
        setAgeText(0);
    }

    return (
        <div>
            <input type="text" value={nameText} onChange={(e) => setNameText(e.target.value)} />
            <input type="number" value={ageText} onChange={(e) => setAgeText(e.target.value)} />
            <button onClick={onClickButton}>변경</button>
            <MyComponent name={name} age={age} />
        </div>
    )
}

export default App;

 

 

728x90

 

 

그리고 동일 위치에 myComponent.jsx파일을 생성하여 다음과 같이 작성해보겠습니다.

 

import * as React from 'react';

const myComponent = ({ name, age }) => {
    const getName = React.useCallback(() => {
        console.log('getName');
        return `my name is ${name}`;
    }, [])

    const getAge = () => {
        console.log('getAge');
        return `my age is ${age}`;
    }

    return (
        <div>
            <h3>{getName()}</h3>
            <h5>{getAge()}</h5>
        </div>
    )
}

export default myComponent;

 

 

 

위와 같이 작성하고 실행해보면 다음과 같은 결과가 나옵니다.

 

실행 결과

 

 

 

텍스트에 데이터를 입력하는 상황에 대해 설명해보면 다음과 같습니다.

 

  • useState를 이용해 만들어놓은 nameText, ageText의 값이 변경될 때마다 관련된 useState의 값들이 모두 리 렌더링이 되기 때문에 name, age도 리 렌더링이 됩니다.
  • name, age가 리렌더링이 되면 해당 데이터들을 파라미터로 사용하는 MyComponent도 리 렌더링이 됩니다.
  • MyComponent가 리렌더링이 되면 getAge는 새롭게 만들어지지만 getName은 메모이제이션이 된 데이터를 가져와 사용합니다.
  • MyComponent가 다시 그려질때마다 div태그 내부에서 getName과 getAge를 호출하기 때문에 결과적으로 텍스트가 입력될 때마다 콘솔 값이 출력됩니다.

 

 

 

버튼을 클릭하는 상황에 대해 설명해보면 다음과 같습니다.

 

  • name, age의 값들이 변경되기 때문에 위에서 텍스트를 입력하는 상황과 동일한 상황이 발생됩니다.
  • getAge함수는 MyComponent가 리 렌더링 될 때마다 다시 생성되기 때문에 변경된 age값을 리턴해줍니다.
  • getName함수는 MyComponent가 리렌더링이 되더라도 useCallback의 deps파라미터에 빈 배열이 들어가 있기 때문에 메모이제이션 처리가 되어 다시 생성되지 않고 저장된 데이터를 가져와 사용합니다.
  • 결국 getAge는 반응성을 나타내지만 getName은 초기에 만들어진 함수를 그대로 가져와 사용하기 때문에 name값이 변경되더라도 name이 항상 빈 문자열인 값으로 출력됩니다.

 

 

 

 

 

 

이상으로 hooks의 useCallback에 대해 간단하게 알아보는 시간이었습니다.

 

읽어주셔서 감사합니다.

 

 

 

728x90
반응형

'SPA > React' 카테고리의 다른 글

[React] Hooks - useReducer  (0) 2021.09.27
[React] Hooks - useMemo  (0) 2021.09.22
[React] Hooks - useRef  (0) 2021.09.13
[React] Hooks - useState  (0) 2021.09.05
[React] Hooks - useEffect  (0) 2021.09.02

댓글