Community

리액트의 안정된 값에 대해 깊이 이해하기

쇼피파이 기술 블로그의 Mastering React’s Stable Values(https://shopify.engineering/master-reacts-stable-values)를 요약-번역한 글입니다. 저의 부연이 구별없이 섞여 있다는 것에 유의해주세요: --- "안정된 값"이란 여러 번의 렌더 동안 같은 값을 유지하는 값을 말합니다. 예를 들면 useState 에서 반환된 업데이트 함수, useRef에서 반환된 값, useCallback으로 감싸진 함수는 안정된 값이고, useMemo, useCallback 으로 감싸지지 않은 객체, 배열, 인라인 함수는 "불안정한 값"입니다. "불안정한 값"은 다르게 말하면 매 렌더마다 항상 변화하는 값입니다. useEffect, useCallback, useMemo는 의존성 배열이 어떻게 변화하는지에 따라 다르게 동작합니다. 의존성 배열이 매 렌더마다 항상 바뀐다면 원하지 않는 결과를 낳습니다. 리액트 요소를 반환하는 함수(사실상 컴포넌트와 같습니다)가 컴포넌트 내부에 useCallback 없이 인라인으로 정의되면, 이 함수는 불안정한 값입니다. 따라서 이 함수를 {renderSomething()}이 아닌 처럼 호출하면, 리액트는 매 렌더마다 과 처럼 "전혀 다른" 컴포넌트로 을 인식합니다. 따라서 리액트는 "매 렌더마다 항상" 의 모든 자식 컴포넌트를 지우고, 새 컴포넌트 트리를 처음부터 다시 만듭니다. 이 문제를 해결하는 방법은 renderSomething() 을 호출하는 것 말고도 반환되는 값을 useMemo 로 감싸는 것도 있지만, 컴포넌트를 useMemo 로 메모이제이션하는 것은 React.memo로 메모이제이션하는 것과 다르기 때문에(The mystery of React Element, children, parents and re-renders 아티클 참조. 댓글에 링크하겠습니다) 원하는 만큼의 렌더링 퍼포먼스를 얻지 못할 수도 있습니다. 쉽게 생각하기 위한 원칙은: 컴포넌트는 전역 공간에 존재해야 한다는 것입니다. 컴포넌트가 다른 컴포넌트의 바디에 정의되었을 때 좋을 게 없습니다. 왜냐하면 컴포넌트를 다른 컴포넌트 내에 정의했을 때, 매 렌더마다 항상 새로운 함수 개체가 생성되는데, 리액트는 이 새로운 개체가 이전 렌더의 개체와 어떤 공통점이라도 있는지(따라서 불필요한 렌더를 줄일 수 있는지)에 대해 어떤 짐작도 할 수 없기 때문입니다(따라서 최적화가 불가능합니다). --- * 여기서 언급된 모든 컴포넌트는 함수형 컴포넌트입니다. ** 한편 저자는 리액트 컴포넌트(리액트 요소를 반환하는 함수) 와 컴포넌트에서 반환된 리액트 요소를 혼용해서 사용하는 것으로 보입니만 우선 최대한 그대로 적었습니다.

알림

알림이 없습니다