Frontend/React

[React] React - React.memo로 렌더링 최적화

w00se 2021. 7. 5. 00:20

https://pixabay.com/ko/photos/tv-타워-건물-저녁-6139241/

 

렌더링을 최적화하기 위해서는 컴포넌트가 렌더링 되는 시점을 알아야 한다.

 

공식 문서에서 해당 내용을 찾아보고 싶었지만 아쉽게 찾지 못했고, 구글링을 통해 해답을 찾았다.

 

React에서 컴포넌트가 리렌더링되는 시점은 크게 네 가지로 나뉜다.

 

1. 부모 컴포넌트가 리렌더링 될 때

2. props가 변할 때

3. state가 변할 때

4. forceUpdate가 호출될 때

 

위 네 가지 경우 중 1번은 불필요한 렌더링을 초래할 수 있다.

자세히 말하면 부모 컴포넌트에서 자식 컴포넌트로 전달되는 props에는 변화가 없는데, 부모 컴포넌트의 리렌더링으로 인해 자식 컴포넌트도 불필요하게 리렌더링 되는 경우다.

이런 경우를 방지하기 위한 방법으로는 자식 컴포넌트에 React.memo를 적용하는 것이다.

 

React.memo 란?

React.memo은 '같은 props에 대해서 동일한 결과를 갖는 컴포넌트라면, memoizing을 하는 React.memo를 통해 성능을 향상할 수 있다.'

React.memo에 대해 조금 더 쉽게 정리하면 부모 컴포넌트가 다시 렌더링 돼도 자식 컴포넌트로 전달되는 props의 값에 변화가 없다면 React.memo를 사용한 자식 컴포넌트는 다시 렌더링 되지 않는다.

 

React.memo에 대한 자세한 설명은 아래 공식 문서에 나와있다.

https://reactjs.org/docs/react-api.html#reactmemo

 

React Top-Level API – React

A JavaScript library for building user interfaces

reactjs.org

 

React.memo의 사용 전과 사용 후 차이는 아래의 예시에서 확인할 수 있다.

 

React.memo 사용 예시

React.memo 사용 전 코드

 

PracticeMemo.tsx

: 하나의 input 엘리먼트와 PracticeMemoResetButton 자식 컴포넌트를 가지고 있다.

import React, { useState } from 'react';
import PracticeMemoResetButton from '../components/PracticeMemoResetButton';

interface PracticeMemoProps {

}

function PracticeMemo(props: PracticeMemoProps) {
    const [ input, setInput ] = useState<string>("");

    const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        setInput(event.target.value);    
    }

    return (
        <div>
            <div>
                <input value={input} onChange={onChange}/> 
            </div>
            <PracticeMemoResetButton/>     
        </div>
    )
}

export default PracticeMemo;

 

PracticeMemoResetButton.tsx

: PracticeMemo.tsx의 자식 컴포넌트이다. 리렌더링 될 때마다 문구가 출력되도록 설정했다.

import React, { useEffect } from 'react';

interface PracticeMemoResetButtonProps {

}

function PracticeMemoResetButton (props: PracticeMemoResetButtonProps) {
    useEffect(()=>{
        console.log("리렌더링 됨");
    });
    return (
        <button style={{ marginTop: 20, }}>
            리셋
        </button>
    )
}

export default PracticeMemoResetButton;

 

실행 예시

React.memo 사용 전

onChange 이벤트에 의해 input state가 변경되면서 PracticeMemo 컴포넌트(부모 컴포넌트)가 다시 렌더링 되고, 리렌더링이 필요 없는 PracticeMemoResetButton(자식 컴포넌트)도 불필요하게 리렌더링 되는 것을 확인할 수 있다.

 

 

React.memo 사용 후 코드

 

PracticeMemoResetButton.tsx

import React, { useEffect } from 'react';

interface PracticeMemoResetButtonProps {

}

function PracticeMemoResetButton (props: PracticeMemoResetButtonProps) {
    useEffect(()=>{
        console.log("리렌더링 됨");
    });
    return (
        <button style={{ marginTop: 20, }}>
            리셋
        </button>
    )
}

export default React.memo(PracticeMemoResetButton); // 이 부분이 변경됐다.

 

실행 예시

React.memo 사용 후

 


느낀 점

이전까지 React-Native로 개발을 하면서 최적화의 필요성을 느끼고 있었다.

오늘 공부 덕분에 React에서 컴포넌트가 렌더링 되는 시점과 React.memo를 이용한 최적화에 대해 배웠고

앞으로 조금 더 효율적인 웹과 앱을 만들 수 있을 거란 생각이 들었다.

 


참고 자료 

https://reactjs.org/docs/react-api.html#reactmemo - React 공식 문서

https://velog.io/@yejinh/useCallback과-React.Memo을-통한-렌더링-최적화 - yejinh.log(useCallback과 React.Memo을 통한 렌더링 최적화)

https://pks2974.medium.com/react-의-성능을-조금-이라도-올려보자-performance-optimize-f1a51b8c406c - 박성룡 ( Andrew park )(React 의 성능을 조금 이라도 올려보자 (Performance Optimize))

 

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

[React] 리액트 파일 확장자를 jsx로 하는 이유  (0) 2022.05.04
[React] redux 정리  (0) 2021.09.03
[React] React - useCallback 사용하기  (0) 2021.07.05