React memo를 사용하는 이유

최문경·2022년 1월 19일
1

react에서 컴포넌트를 다시 실행하는 경우는 3가지이다.

  1. 부모 컴포넌트가 재실행될 때
  2. props가 변경되었을 때
  3. state가 변경되었을 때

먼저 2, 3번의 경우를 살펴보자.
props와 state가 변경되었을 때 컴포넌트가 재실행되는 것은 당연해 보인다. 왜냐하면 변경된 props또는 state에 맞게 화면을 다시 그려야하기 때문이다.

그런데, 1번의 경우에서 부모 컴포넌트로부터 어떠한 props로 넘겨받지 않는 컴포넌트는 부모 컴포넌트가 재실행될 때 같이 재실행될 필요가 있을까? 당연히 없을 것이다. 왜냐하면 리렌더링을 하지 않을 것이기 때문이다.

이러한 경우를 막기위해서 사용하는 메서드가 memo이다. memo를 사용하면 부모 컴포넌트가 재실행될 때 같이 재실행되는 것을 막고, props가 변경되었을 때만 컴포넌트가 재실행 되도록 한다. (state가 변경되었을 때도 재실행됨)

이것이 가능한 이유는 memo는 컴포넌트의 props를 기억하고 있다가 부모 컴포넌트가 재실행되어서 컴포넌트도 재실행되려고 할 때 이전의 props와 비교해서 재실행 여부를 결정한다고 한다.

적용하는 방법은 아래와 같이 컴포넌트를 memo로 감싸주면 된다.

export default React.memo(ComponentName)
export default react.memo(ComponentName)

하지만, 부모 컴포넌트가 재실행될 때마다 props가 변하는 자식 컴포넌트는 memo를 사용하는 것이 오히려 비효율적일 것이다. (어차피 재실행되어야 하는데 계속 비교하니까)

그리고 자식 컴포넌트들에 모두 memo를 사용하기보다 root컴포넌트와 가까운 컴포넌트에게 memo를 적용해주는 것이 그 컴포넌트의 자식 컴포넌트들도 재실행이 방지되기 때문에 더 효율적일 것이다.

아래의 코드와 실행결과를 보며 제대로 이해했는지 확인해보자.
토글로 Pragraph를 보이고 안보이게 하는 코드이다.

// App.js
import { Fragment, useState } from 'react';

import Button from './components/Button';
import Paragraph from './components/Paragraph';

function App() {
  console.log('App Running');

  const [showParagraph, setShowParagraph] = useState(false);

  const toggleParagraphHandler = () => {
    setShowParagraph((prevState) => !prevState);
  };

  return (
    <Fragment>
      <Paragraph show={false} />
      <Button onChangeText={toggleParagraphHandler} />
    </Fragment>
  );
}

export default App;
// Paragraph.js
import react from 'react';

const Paragraph = (props) => {
  console.log('Paragraph Running');

  return <p>{props.show ? 'HELLO' : ''}</p>;
};

export default react.memo(Paragraph);
// Button.js
import react from 'react';

const Button = (props) => {
  console.log('Button Running');

  return <button onClick={props.onChangeText}>Change Text!</button>;
};

export default react.memo(Button);

위의 세 줄은 초기 렌더링시 출력되는 것이고 아래 두 줄은 버튼을 클릭했을 때 출력된다.

그런데 이상하다.. Pragraph컴포넌트와 마찬가지로 Button컴포넌트도 memo를 적용하고 props도 변하지 않았는데 왜 App컴포넌트가 재실행될 때 Button컴포넌트만 재실행되는 것일까?

다음 useCallback 포스팅에서 계속...

profile
프론트엔드 공부하고 있습니다!

0개의 댓글