React-memo-와-Children
2023-04-25
뭐가 다를까
리엑트에서 컴포넌트의 불필요한 랜더링 방지를 위해서 대표적으로 2가지 방법이 있다
React memo와 Children 이 두가지 이 두개가 정확히 뭐가 다른지 비교 해보자
React memo
React memo higher-order component(HOC) 한국어로 고차 컴포넌트라 불리며
컴포넌트 로직을 재사용 하기위해 컴포넌트를 받아 컴포넌트를 반환 하는
간단히 말하면 컴포넌트를 인자로받는 함수를 말한다
그중에서도 React memo는 재랜더링을 스킵하기 위해 사용된다
사용법
사용법도 간단하다 React 라이브러리에서 memo를 불러와 불필요한 재랜더링을 막고자 하는 컴포넌트를 감싸면 된다
만약 이러한 memo를 쓰지 않았다면 count state가 변경되면 부모 컴포넌트를 포함해 그 아래에 있는 자식 컴포넌트까지 모두 재랜더링 하게 되지만 React memo를 쓰게 되면 props로 전달된 값들을 비교해 바뀐게 없다면 랜더링을 스킵한다
React memo의 정체
그렇다면 React memo는 앞서 적었다싶이 props를 비교해 불필요한 랜더링을 방지한다
이러한 상태값 비교방식에는 shallow comparison 즉 얕은 비교를 사용 한다고 한다
이 얕은 비교에 대해 알아보면 검색을 해보면 react는 참조값을 가지는 변수 즉 array, obejct 같은 변수들을
비교할때 참조값만 비교하는게 아닌 key : value 값들 또한 비교한다고 하는 포스트들이 많이 보이고
공식문서에서도 React memo는 얕은 비교를 통해 상태값들을 비교한다고 써있다
그렇기에 test값의 참조값이 매번 달라지는 이러한 코드도 문제없이 불필요한 랜더링을 막을거 같지만
결과는 다음과 같다
결론적으론 React memo는 참조값 까지만 비교하는 것이다
이 내용은 영어로된 문서로 보면 더 자세히 볼 수 있다.
Troubleshooting 부분 을 보면 된다
Children
React memo 외에도 컴포넌트의 불필요한 랜더링을 방지할 방법이 있는데
그 중 하나가 children이다 사용법도 간단하다
코드의 결과는 이렇다
이 코드의 경우 직접적으로 Test 컴포넌트를 넣어준게 아닌 children을 통해 간접적으로 선언후
불필요한 랜더링을 방지해 최적화를 달성했다
Children의 정체
Children은 어떻게 불필요한 렌더링을 피할 수 있었을까?
먼저 react 에서 JSX를 어떤식으로 처리해야 하는지 알아야한다
이와 같은 코드는
아래와 같이 컴파일 되고
다음과 같은 객체 형태로 바뀐다
이는 React.createElement 를 직접 실행해 보면 알 수 있다
우리가 작성한 JSX는 결론적으로 Object 즉 객체가 된다는것을 알 수 있다
이를 알았으니 다시 본론으로 돌아가 보자
다음과 같은 코드에서
이 부분에만 집중해보자
우리가 자식 컴포넌트를 불러올때 props.children 을 사용을 하기에 위와 같은 방식은 다음과 같다는 결론이 나온다
결국 children을 사용했을때 불필요한 재랜더링이 줄었던 이유는 자식 컴포넌트가 객체로서 props로 전달되기 때문이다 이 상황에서 ParentComponent가 재랜더링 되어도 자식 컴포넌트의 상태값이 바뀌지 않는한 재랜더링 되지 않는다
React Memo의 함정
만약 memo와 children을 같이쓰게되면 어떤일이 발생할까?
다음 코드를보자
count 상태값의 변경으로 재랜더링 되고 그 과정에서 Test 컴포넌트도 재랜더링되는데 이를 막기위해
memo를 사용 했었다 하지만 여기에 children을 추가하면 어떻게 될까
앞서 설명했듯 memo 는 객체의 참조값까지만 비교하며 JSX는 객체라는 사실을 떠올려 봤을때
count 상태값이 변경됨에 따라 MemoTest의 props값인 children도 재랜더링되고