리액트가 렌더링하는 방식

메론맛캔디·2021년 10월 28일
0

기술면접

목록 보기
11/30
post-custom-banner

언제 렌더링을 할까?

  1. props가 변할 때
  2. state가 변할 때
  3. forceUpdate()를 실행할 때
  4. 부모 컴포넌트가 렌더링될 때

컴포넌트에서 렌더링 결과에 전혀 영향을 미치지 않는 변화가 일어나면 불필요한 렌더링이 발생하게 된다.

렌더링 과정에서 수행하는 로직이 많을수록 더 많은 컴포넌트를 출력할 수록 악영향을 끼칠 확률이 높아진다.


인라인 스타일링

인라인 스타일을 사용하면 코드도 깔끔하지 않고 불필요한 리렌더링을 발생시킨다.

객체의 메모리 주소값은 항상 다르다. 따라서 가상돔에 변화가 일어났다고 인식을 하게되고, 불필요한 리렌더링이 발생하게 된다.

{} === {} // false 

불필요한 리렌더링을 방지하기 위해서는

  • styled-components를 사용할 수 있다.
    Antd와 같은 UI라이브러리를 사용할 때 보통 커스텀을 해서 사용하게 되는데, 인라인 스타일로 원래의 CSS 속성을 덮어씌우면 불필요한 리렌더링이 발생하게 된다.
    craco.config.js를 만들어서 클래스명을 가져와 덮어씌우는 방법도 있지만, styled-components를 사용하면 인라인 스타일을 사용하지 않고 쉽게 커스텀할 수 있다.
import React from 'react';
import styled from 'styled-components';
import { Button } from 'antd';

const StyledBtn = styled(Button)`
  color: red;
`;


const App = () => {
  return <StyledBtn type='submit'>버튼</StyledBtn>
}
export default App;

또는

  • useMemo를 사용할 수 있다.
    useMemo훅을 이용해서 이전에 한 번 사용한 값을 재사용할 수 있다. 필요한 스타일 객체를 캐싱해놓고 재사용 하면 이미 기억하고 있는 객체이기 때문에 메모리 주소값이 변하지 않아 불필요한 리렌더링이 일어나지 않는다.
import React, { useMemo } from 'react';
import { Button } from 'antd';

const App = () => {
  const buttonStyle = useMemo(() => ({ color: 'red' }), [])

  return (
    <>
      <Button style={buttonStyle}>버튼</Button>
    </>
  )
}
export default App;


DOM 조작을 한다는 것은 각 조작이 레이아웃 변화, 트리 변화 그리고 렌더링을 일으킨다. 그러면 그 변화를 적용하기 위해서 브라우저는 연산을 많이 해야하고, 성능이 안 좋아진다.

virtual DOM (가상 돔)은 무엇일까?

실제 돔을 만들 수 있는 리액트 요소 트리를 가상 돔이라고 한다.
가상 돔은 UI에서 변경된 부분을 빨리 찾기 위한 개념이므로 컴포넌트의 리액트 요소도 가상 돔의 일부라고 생각할 수 있다.



렌더링 과정

  1. 데이터가 업데이트 되면, 전체 UI를 가상 DOM에 리렌더링을 한다.
  2. 이전 가상 DOM에 있던 내용과 현재 가상 DOM을 비교해 변경된 부분만 실제 돔에 반영한다.

가상 돔 트리는 렌더링 되지 않기 때문에 연산 비용이 적다. 연산이 끝난 후 최종적인 변화를 실제 DOM에 하나로 묶어서 던져준다. 리렌더링 규모는 커질 수 있지만 렌더 트리 재생성, 레이아웃, 페인팅과 같은 과정이 한번만 일어나기 때문에 효율적이다.



참고

https://velog.io/@syj9484/React-%EB%A6%AC%EB%A0%8C%EB%8D%94%EB%A7%81%EA%B3%BC-%EA%B4%80%EB%A0%A8%ED%95%98%EC%97%AC-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-%ED%95%98%EA%B8%B0

https://velopert.com/3236

https://meetup.toast.com/posts/110

post-custom-banner

0개의 댓글