Component & Hook
Function Component와 Class Component
Hook은 class가 아닌 function형 컴포넌트에서만 동작한다.
Hook 사용규칙
1. 리액트 함수의 최상위에서만 호출해야 한다.
반복문, 조건문, 중첩된 함수 내에서 Hook을 실행하면 예상대로 동작하지 않을 우려가 있다.
컴포넌트 안에는 useState나 useEffect와 같은 hook이 여러번 사용될 수 있는데.
react는 이 hook을 호출되는 순서대로 저장을 해놓는다.
그런데 조건문, 반복문 내에서 hook을 호출하게 되면, 호출되는 순서대로 저장을 하기 어려워지고
결국 예기치 못한 버그를 초래할 수 있다.
2. 오직 리액트 함수 내에서 사용되어야 합니다.
이는 리액트 함수형 컴포넌트나 커스텀 hook이 아닌 다른 일반 javascript 함수 안에서 호출해서는 안된다는 의미입니다
애초에 hook은 react의 함수 컴포넌트 내에서만 사용되도록 만들어진 메서드이기 때문에
일반 javascript 함수 내에서는 정상적으로 돌아가지 않습니다
컴포넌트는 기본적으로 상태가 변경되거나 부모 컴포넌트가 렌더링될때마다 리렌더링을 하는 구조로 이루어져 있다.
하지만, 너무 잦은 리렌더링은 앱에 좋지 않은 영향을 끼친다
React Hook 중 렌더링 최적화를 위한 Hook이 2가지 존재하는데,
바로, useMemo 와 useCallback 이다
useMemo란?
useMemo는 특정 값을 재사용하고자 할 때 사용하는 Hook 입니다.
function Calculator({value}){
const result = calculate(value);
return
<>
<div>
{result}
</div>
</>;
}
만약 여기서 calculate가 내부적으로 복잡한 연산을 해야하는 함수라 시간이 몇 초 이상 걸린다고 가정해봅시다.
해당 컴포넌트는 렌더링을 할 때마다 이 함수를 계속해서 호출할 것이고, 그때마다 시간이 몇 초 이상 소요가 될 것입니다. 이 몇 초의 지연은 렌더링에도 영향을 미칠 것이고, 사용자는 “앱의 로딩 속도가 느리네?”라는 생각을 하게 될 것입니다.
/* useMemo를 사용하기 전에는 꼭 import해서 불러와야 합니다. */
import {useMemo} from "react";
function Calculator({value}){
const result = useMemo(() => calculate(value), [value]);
return
<>
<div>
{result}
</div>
</>;
}
여기 value를 인자로 받는 Calculator 컴포넌트가 있습니다.
value 가 일종의 값으로서, 이 값이 계속 바뀌는 경우라면 어쩔 수 없겠지만 이 값을 어딘가에 저장을 해두었다가
다시 꺼내어 쓸 수 있다면 굳이 calculate 함수를 호출할 필요도 없을 것입니다.
여기서 useMemo Hook을 사용할 수 있습니다.
이렇게 useMemo 를 호출하여 calculate을 감싸주면,
이전에 구축된 렌더링과 새로 만들어진 렌더링을 비교해 value 값이 동일할 경우에는
이전 렌더링의 value 값을 그대로 재활용할 수 있게 됩니다.
이는 메모이제이션이랑 관계가 있습니다
Memoization
메모이제이션(Memoization)은 알고리즘에서 자주 나오는 개념입니다.
기존에 수행한 연산의 결과값을 메모리에 저장을 해두고, 동일한 입력이 들어오면 재활용하는 프로그래밍 기법을 말합니다.
이 메모이제이션을 적절하게 사용한다면 굳이 중복연산을 할 필요가 없기 때문에 앱의 성능을 최적화시킬 수 있습니다
useCallback 이란?
useCallback 또한 useMemo 와 마찬가지로 메모이제이션 기법을 활용한 Hook 입니다.
useMemo는 값의 재사용을 위해 사용하는 Hook이라면, useCallback은 함수의 재사용을 위한 사용하는 Hook 입니다.
function Calculator({x,y}){
const add = () => x + y;
return <>
<div>
{add()}
</div>
</>;
}
해당 컴포넌트가 리렌더링 되더라도 그 함수가 의존하고 있는 값인 x와 y가 바뀌지 않는다고 생각해 봅시다.
그렇다면 함수 또한 메모리 어딘가에 저장해 뒀다가 다시 꺼내서 쓸 수 있을 것입니다.
이때 useCallback Hook을 사용하면 그 함수가 의존하는 값들이 바뀌지 않는 한 기존 함수를 계속해서 반환합니다. 즉 x와 y값이 동일하다면 다음 렌더링 때 이 함수를 다시 사용합니다.
/* useCallback를 사용하기 전에는 꼭 import해서 불러와야 합니다. */
import React, {useCallback} from "react";
function Calculator({x,y}){
const add = useCallback(() => x + y, [x,y])
return <>
<div>
{add()}
</div>
</>;
}
사실 useCallback 만 사용해서는 useMemo에 비해 꽤 괜찮은 최적화는 느낄 수 없다.
useCallback은 함수를 호출하지 않는 Hook이 아니라, 그저 메모리 어딘가에서 함수를 꺼내서 호출하는 Hook 이기 때문이다.
단순히 컴포넌트 내에서 함수를 반복해서 생성하지 않기 위해서 useCallback 을 쓰는 것은 큰 의미가 없다
그러면 언제 사용하는 것이 좋을까?
바로 자식컴포넌트의 props 로 함수를 전달해줄때 useCallback을 사용하기 좋다.
'React' 카테고리의 다른 글
Custom Hooks (0) | 2023.05.23 |
---|---|
React.lazy() 와 Suspense (0) | 2023.05.23 |
Virtual DOM과 React Diffing Algorithm (0) | 2023.05.20 |
styled-component가 웹표준을 향상시킨다고? (0) | 2023.04.28 |
코드를 읽는 순차적인 흐름과 오류처리에 관하여 (Cmarket Redux) (6) | 2023.04.25 |