리액트가 실행될 때 가장 많은 CPU 리소스를 사용하는 것은 렌더링이다.
최초 렌더링 이후 속성값이나 상태값의 이전 이후 값을 비교하고 렌더링이 필요하다고 생각하면 컴포넌트 함수를 호출한다.
새로운 가상 돔을 만들고 이전에 만들었던 가상 돔과 비교해서 변경된 부분을 실제 돔에 반영한다.
렌더링 결과 재사용하기
const MyComponent = (props) => {
// ...
}
const ifEqual = (prevProps, nextProps) => {
// true or false
}
React.memo(Mycomponent, isEqual);
이전, 이후 속성값을 매개변수로 받아서 참을 반환하면 렌더링을 멈추고, 거짓을 반환하면 컴포넌트 함수를 실행하여 가상 돔을 업데이트 한다.
속성값을 불변 객체로 관리하면 단순 비교만으로 컴포넌트 속성값이 변경된 것을 알 수 있기 때문에 렌더링 성능에 큰 도움이 된다.
컴포넌트 내부에서 함수나 객체를 정의해서 자식 컴포넌트의 속성값으로 입력하면, 자식 컴포넌트는 변경되지 않은 값에 대해서도 속성값이 변경되었다고 인식한다.
렌더링과 무관하게 항상 같은 값을 가지도록 관리해야 한다.
const discountPrice = () => {
let needPrice;
if (0 <= cartPrice && cartPrice < 50000)
needPrice = { discount: 10, price: 50000 - cartPrice };
if (50000 <= cartPrice && cartPrice < 100000)
needPrice = { discount: 13, price: 100000 - cartPrice };
if (100000 <= cartPrice && cartPrice < 200000)
needPrice = { discount: 15, price: 200000 - cartPrice };
if (cartPrice > 200000) needPrice = { discount: 15, price: 10000000000 };
return needPrice;
};
// cartPrice가 변할 때에만 needPrice가 변경되도록 하기!
const needPrice = useMemo(discountPrice, [cartPrice]);
무조건 useCalback, useMemo, React.memo를 사용하는 것은 좋지 않다.
-> 가독성이 안좋고 유지보수 비용을 증가 시키기 때문에, 성능 이슈가 발생했을 때 해당하는 부분의 코드만 최적화 하는 것이 좋다!
요소의 타입을 변경하면 해당 요소의 모든 자식 요소도 같이 변경된다. 자식 요소의 내용이 변경되지 않아도 돔에서 삭제되고 추가되므로 비효율적이다.
같은 key를 가지는 요소끼리 비교해서 변경점을 찾는다.
중간에 요소를 추가하거나 중간에 있던 요소를 삭제하면, 리액트는 뒤에 있는 요소가 변경되지 않았다는 것을 알지 못한다.
중간에 요소를 추가할 경우 중간에 변경된 부분만 실제 돔에 반영하고, 뒤에 있는 요소는 없다가 생겼으므로 돔에 추가한다.
- key값은 데이터의 ID값으로 입력한다.
- 배열 내에서의 순서(Index)를 입력할 수도 있다.
-> 배열의 끝에서만 원소를 추가하거나 순서를 변경하지 않는 경우에 적합하다.
실전 리액트 프로그래밍 / 이재승 / 인사이트