이때까지 외면해오던 것이 있었다. useState 와 useEffect만 사용해도 충분히 기능을 구현하는 것에 문제가 없었기에, useMemo와 useCallback을 알아볼 생각이 없었다. 이 두개는 렌더링 최적화를 위한 hook이기 때문에, 무언가 아직 최적화까지 내가 생각을 해야해? 라는 생각이 머릿속을 지배했었던 것 같다.
하지만, 어떻게 개발자가 최적화를 외면할 수 있겠는 가.
지금이라도 렌더링 최적화를 위한 hook에 익숙해져보자.
class형 컴포넌트는 리액트 16.8버전이였나, 훅이 나오면서 이제는 deprecated 될 것이다. (조만간 사라지게 될 상태)
대부분이 현재 함수형 컴포넌트를 사용하고 있는데, 함수형 컴포넌트는 말 그대로 함수이다.
즉, 컴포넌트가 실행된다는 것은 함수가 실행되어 jsx를 반환하는 것과 마찬가지이다.
- 우리가 아는 컴포넌트는 함수이기 때문에, 매번 실행될 때마다 함수 내의 표현식(변수 및 함수 등)도 매번 선언되고 사라진다.
- 그리고, 컴포넌트는 자신의 state 또는 props가 변경되었을 때마다 렌더링 된다. (부모가 렌더링되면, 자식또한 리렌더링 된다.)
이게 문제다. 부모컴포넌트가 리렌더링되면, 불필요하게 자식컴포넌트가 무조건 리렌더링 된다.
이러한 불필요한 리렌더링을 방지하는 것이 리액트 메모이제이션이다.
Memoization
연산의 결과값을 메모리에 저장해 두고 이전 값과 결과가 동일할 경우 재사용하는 방법
그렇다면 리액트에서는 어떠한 메모이제이션 방법들을 제공할까?
- React.memo (컴포넌트) -props의 값으로 변경을 확인
- useMemo ( () => 함수 리턴값 , [ 의존성 ] ) -의존성배열 내부의 값으로 변경을 확인
- useCallback ( () => { 함수 } , [ 의존성 ] ) -의존성배열 내부의 값으로 변경을 확인
총 3가지를 제공한다.
그렇다면, 왜 useMemo와 useCallback을 사용할까? 그냥 React.memo로 props의 변화만 감지하면 되지 않을까??
원시타입이 아닌 객체타입은 매번 생성될때마다 메모리주소가 다르기 때문에, 변화한 것으로 감지된다.
이 때문에, 모든 의존성배열에는 객체타입이나 배열을 넣어주지 않는 것이 좋다. 어차피 메모리주소가 달라져 변화로 감지하기 때문에.
즉, 아래와 같이 아무리 똑같이 생긴 객체여도 참조하는 메모리주소가 다르기때문에 같지 않다고 간주한다.
const name = {name:1}
const name1 = {name:1}
//false
console.log(name === name1)
따라서 useMemo나 useCallback을 통해서, 객체타입을 메모이제이션 해주어야한다.
또한 차이점은
- React.memo는 리액트의 HOC(Higher Order Component) 패턴, useMemo는 리액트 Hooks의 함수이다.
- 따라서 React.memo는 HOC이기 때문에 클래스형, 함수형 컴포넌트 모두 사용 가능
But, useMemo는 Hook이기 때문에 함수형 컴포넌트에서만 사용 가능
그렇다고 무조건 memo를 사용할 필요는 없다.
- 순수 함수 컴포넌트 일때 → 이건 요즘 다 클래스형이 아니라 함수형으로 작성하기 때문에 넘어가도 괜찮다.
- Renders often → 자주 렌더링 될때 : 말 그대로 빈번하게 렌더링 되는 것들. Profile로 체크할 수 있다.
- 같은 prop으로 리렌더링 될때 : 똑같은 prop을 가지고 있는데 계속 리렌더링 될때. 보통 Input을 작성할 때 계속 상관없는 컴포넌트가 렌더링 되는 것을 본 적 있을 텐데 이를 의미한다.
- 컴포넌트가 클 때: 말 그대로다. 그런데 이 네 번째 조건은 굳이 안 넣어도 되지 않았을까?
어차피 자주 다른 props로 렌더되는데, memo를 사용하면 오히려 불필요하게 조건문을 수행할 뿐이다.
다음 프로젝트에서는 useMemo와 useCallback을 적극적으로 사용해봐야겠다.
'React' 카테고리의 다른 글
네이버클라우드에서 Nginx적용 후, 리액트 배포하기 (0) | 2023.02.14 |
---|---|
리액트 this키워드 문제 (0) | 2023.01.06 |
useEffect는 비동기적이지 않다. (0) | 2022.12.12 |
10주간 리액트를 쓰면서, 리액트를 몰랐다. (0) | 2022.12.11 |
CSS 모달창을 만들어보자구나! (0) | 2022.11.18 |