React_Deep_Dive_6_렌더링

조용환·2024년 2월 18일
0

React_Deep_Dive

목록 보기
6/12

브라우저에서도 랜더링은 있다. HTML과 CSS 리소스를 기반으로 웹페이지에 필요한 UI를 그리는 과정을 의미한다.
리액트에서의 랜더링은 조금 다르다.

리액트의 렌더링

리액트에서의 렌더링이랑 리액트 에플리케이션 트리 안에 있는 모든 컴포넌트들이 현재 자신들이 가지고 있는 props와 state의 값을 기반으로 어떻게 UI를 구성하고 이를 바탕으로 어떤 DOM 결과를 브라우저에 제공할 것인지 계산하는 일련의 과정을 의미한다. 만약 props와 state같은 상태값이 없다면 해당 컴포넌트가 반환하는 JSX 값에 기반해 렌더링이 일어나게 된다.

  • 최초 렌더링 : 처음 애플리케이션 진입 시 진행
  • 리렌더링 : 최초 이후 모든 레더링을 의미
    - 클래스 컴포넌트의 setState 실행시
    - 클래스 컴포넌트의 forceUpdate 실행 시(shouldComponentUpdate는 무시하고 건너 뜀) render 내에서 사용시 무한 루프
    - 함수 컴포넌트의 useState()의 두 번째 배열 요소인 setter가 실행되는 경우
    - 함수 컴포넌트의 useReducer()의 두 번째 배열 요소인 dispatch 실행되는 경우
    - 컴포넌트의 key props 변경
    -> 리렌더링시 current 트리와 workInProgress 트리 사이에 컴포넌트 변경 구별해야 하는데, 이 때 사용하는 것이 key.

리액트 렌더링 프로세스

업데이트가 필요한 컴포넌트를 발견 시 클래스 컴포넌트는 render() 함수 실행, 함수 컴포넌트의 경우는 FunctionComponent() 그 자체를 호출한 뒤, 결과물을 저장
이 렌더링 결과물을 수집 후 새로운 트리인 가상 DOM과 비교해 실제 DOM에 반영하기 위한 모든 변경 사항을 차례차례 수집함. -> 리액트의 재조정
이 단계는 렌더 단계와 커밋 단계 총 두 단계로 분리되어 실행 됨.

렌더와 커밋

렌더 단계

렌더 단계(Render Phase)는 컴포넌트 렌더링 및 변경 사항을 계산하는 모든 작업을 말함.
비교하는 것은 크게 세 가지로 type, props, key.

커밋 단계

렌더 단계의 변경 사항을 실제 DOM에 적용해 사용자에게 보여주는 과정을 말함. 이 단계가 끝나야 비로소 브라우저의 렌더링이 발생.


이 뒤 리액트 내부 참조를 업데이트. 그 뒤 생명주기 개념이 있는 클래스 컴포넌트에서는 componentDidMount, componentDidUpdate 메서드를 호출하고, 함수 컴포넌트에서는 useLayoutEffect 훅을 호출. **리액트 렌더링이 일어난다고 해서 무조건 DOM 업데이트가 일어나는 것은 아님** 렌더링 과정 중 첫 번째 단계인 렌더 단계에서 변경 사항을 감지할 수 엇다면 커밋 단계가 생략되어 브라우저의 DOM 업데이트가 일어나지 않을 수 있다.

컴포넌트와 함수의 무거운 연산을 기억해 두는 메모이제이션

메모이제이션 최적화는 오랜 논쟁의 주제이다.

1. 섣부른 최적화는 독이다. 꼭 필요한 곳에만 메모이제이션을 추가하자.

메모이제이션 역시 리소스를 쓰는 작업이므로, 무엇이 이득일지 고민해봐야한다.

2. 렌더링 과정의 비용은 비싸다. 모조리 메모이제이션 하자.

기본적으로 리액트는 이전 렌더링 결과를 다음 렌더링과 구별하기 위해 저장해 둔다. 따라서 추가적으로 드는 것은 prop에 대한 얕은 비교 정도 이다.
반면 memo를 하지 않았을 때 발생할 수 있는 문제는 다음과 같다.

  • 렌더링을 함으로써 발생하는 비용
  • 컴포넌트 내부의 복잡한 로직의 재실행
  • 위 두 가지 모두가 자식 컴포넌트에서 반복해서 일어남
  • 리액트가 구 트리와 신규 트리를 비교

책의 결론

시간을 투자할 여유가 있다면 1번, 시간을 투자할 여유가 없다면 의심스로운 곳에는 일단 다 적용해 볼 것을 권장함.

profile
practice react, javascript

0개의 댓글