1. 리액트 성능 최적화에 관하여..

Hyunjun Kim
akiakma
Published in
4 min readNov 2, 2020

리액트가 실행될때 가장 많은 CPU자원을 사용하는 것은 렌더링이다.
리액트는 UI라이브러리이기 때문에 프로그램이 실행되는 동안에 화면을 그리는 역할을 하는데, 데이터와 컴포넌트 함수로 화면을 그린다. (여기서 리액트 데이터란 컴포넌트의 속성값과 상태값을 의미한다. ) 이 과정에서 대부분의 연산은 컴포넌트 함수의 실행과 가상돔에서 발생한다.

React.Memo

컴포넌트는 리액트 memo함수를 이용하여 랜더링이 필요한지 판단 할 수 있다. 속성값의 변경사항이 없다면 이전 렌더링 결과를 재사용 할 수 있다. 원래는 부모로부터 props를 받을때, 부모의 상태값이 변경되면 그 자식 컴포넌트도 재랜더링이 되는데 memo함수를 이용하면 자식에게 전달하는 속성값에 변동이 없다면 불필요한 랜더링을 방지하는 것이다.

위에서 말했듯이, 컴포넌트 속성값이나 상태값이 변경되면 리액트는 그 컴포넌트를 다시 그릴 준비를 한다. 위에 코드처럼 memo함수를 감싸면 속성값 비교 함수가 호출이 되는데, 속성값 비교를 통하여 랜더링 결과를 재사용할지 컴포넌트 함수를 실행해서 가상돔을 업데이트하고 변경된 부분을 실제돔에 반영할지 결정한다. 만약 속성값 비교 함수를 입력하지 않으면(isEqual부분) , 얕은 비교를 수행하는 기본 함수가 사용이 된다. isEqual을 사용하면, 이전상태값과 이후 상태값을 비교하는데 참을 반환하면 컴포넌트를 재사용하고 거짓을 반환하면 컴포넌트를 다시 랜더링한다. 즉, React.memo함수를 감싸지 않으면 항상 거짓을 반환한다고 생각 할 수 있다.

isEqual함수가 false반환하기때문에 value1,value2값이 변경될때마다 재랜더링이 되는것을 볼수 있다. 반대로 true를 반환한다면?

isEqual의 반환값이 true일 경우에는 아무런 변화가없다. 즉 랜더링 되지 않는 것이다.

function isEqual(prevProps, nextProps) {
return prevProps.value1 === nextProps.value1;
}

만약 위와 같이 value1만 비교하면 아래 와 같이 작동한다. value2값이 바뀌어도 랜더링이 되지않다가, value1값이 변동되면 랜더링되고 변동값도 그때되서 반영이되는것이다.

value1때는 바로반영되지만, value2는 눌러도 랜더되지않음

상태값을 불변객체로 관리하면 렌더링 성능에 도움이된다.

React.memo()함수에서 속성값 비교함수(두번째 매개변수)를 입력하지 않았을때 리액트가 기본으로 갖고있는 속성값 비교 함수가 동작하는데 그 동작원리는 얕은 비교를 통해서 한다. 예를들어서 prevProps=[1,2,3]에 prevProps.push(4)를 넣어서 변경사항을 체크한다면 참조값이 하나이니까 1부터 4까지 하나하나 비교를하고 length비교를 해야할 것이다 이정도는 단순하지만 구조가 복잡해질경우 하나하나 비교하는데 불필요한 자원낭비가 있을것이다. 그래서 새로운 객체를 생성해주는데 그러면 reference값이 달라지므로 얕은 비교를통해 그 값이 바뀌었는지 확인 할 수 있고 성능에도 좋아진다. (얕은비교 => 참조값비교)

--

--