스터디/모던 리액트 Deep Dive(24.07-24.10)

2.4-2.5 : 리액트 핵심 요소 (렌더링, 메모이제이션)

minseokiim 2024. 8. 19. 19:40

 

4. 렌더링

- 브라우저에서의 렌더링 : HTML과 CSS 리소스를 기반으로 웹페이지에 필요한 UI를 그리는 과정

- 리액트에서의 렌더링 : 브라우저가 렌더링에 필요한 DOM트리를 만드는 과정,

리액트 애플리케이션 트리안에 있는 모든 컴포넌트들이 가진 props와 state의 값을 기반으로 어떻게 UI를 구성하고, 이를 바탕으로 어떤 DOM결과를 브라우저에게 제공할 지 계산하는 일련의 과정

만약, props와 state의 값이 없다면 오직 해당 컴포넌트가 반환하는 JSX값에 기반한 렌더링

 

 

i) 리액트의 렌더링이 일어나는 경우

- 최초 렌더링

- 리렌더링 : 클래스 컴포넌트의 setState/forceUpdate 실행, 함수 컴포넌트의 useState 두번째 배열요소 setter 실행/ useReducer 두번째 배열요소 dispatch 실행, 컴포넌트 key props 변경, props변경, 부모 컴포넌트 렌더링

 

+ 배열에 key 를 쓰는 이유

key는 리렌더링이 발생하는 동안 형제 요소들 사이에서 동일한 요소를 식별하는 값,

리액트 파이버 구조에서 curent트리와 workInProgress 트리사이에 어떠한 컴포넌트가 변경이 있는지 구별하게 해줌.

리렌더링이 필요한 컴포넌트를 최소화 해야하므로 key는 필수인 것.

key가 없으면 파이버 내부의 sibling인덱스 기준으로 판단.

 

+ key에 index 쓰면 안되는 이유

key는 각 항목을 고유하게 식별해야하므로, 불변한 값을 가져야 함.

index 는 배열의 위치를 기준으로 하기 때문에, 배열의 항목이 추가/삭제되면 변경되므로 key에 index를 쓰면 안됨.

 

 

ii) 리액트의 렌더링 프로세스

- 리액트는 컴포넌트 루트에서부터 아래쪽으로 내려가면서 업데이트가 필요하다고 지정된 모든 컴포넌트를 찾음.

- 컴포넌트를 찾으면 클래스 컴포넌트인 경우에는 render()실행, 함수 컴포넌트는 FunctionComponent() 호출 후 결과물 저장.

- 렌더링 결과물은 JSX 문법으로 구성, 자바스크립트로 컴파일 되며 React.createElement()를 호출하는 구문으로 바뀜.

createElement는 브라우저 UI 구조를 설명할 수 있는 일반적인 자바스크립트 객체 반환

- 각 컴포넌트의 렌더링 결과물을 수집하고, 가상 DOM과 비교해 실제 DOM에 반영하기 위한 모든 변경사항 차례대로 수집 -> 재조정 과정

 

- 재조정이 끝나면 모든 변경사항을 하나의 동기 시퀀스로 DOM에 적용.

 

 

iii) 렌더와 커밋

- 렌더 단계 : 컴포넌트를 렌더링하고 변경사항을 계산하는 작업

컴포넌트 실행해 이전 가상 DOM을 비교하는 과정 거쳐 변경이 필요한 컴포넌트 체크

여기서 비교하는 것은 prop

 

- 커밋 단계 : 렌더 단계의 변경 사항을 실제 DOM에 적용해 사용자에게 보여주는 과정

커밋 단계가 끝나야 브라우저의 렌더링이 발생함

-> 리액트의 렌더링이 일어난다고 DOM업데이트가 무조건 일어나는 것은 아님!

( 변경사항을 계산했는데 감지되지 않는다면, 커밋단계는 생략)

 

리액트의 렌더링은 항상 동기식으로 동작. 따라서, 렌더링 과정이 길어지면 성능이 저하되는 것.

이유 : 순서가 보장되지 않는다면, 하나의 상태에 대해 여러가지 UI를 보여주게 됨.

리액트 18부터는 의도된 우선순위로 컴포넌트를 최적화 렌더링 할 수 있음(비동기 렌더링)

 

 

5. 메모이제이션

useMemo, useCallback, 고차 컴포넌트 memo가 있음.

최적화를 위해 렌더링을 최소한으로 줄여줌.

 

* 의견

1. 메모이제이션을 필요한 곳에만 추가하기

메모이제이션 자체도 비용이 든다.

일단 만들고 니사 개발자도구나 useEffect를 사용해 실제 렌더링이 일어나는지 확인하고 필요한 곳에서만 이용.

 

2. 메모이제이션을 모두에 적용

렌더링 비용은 비싸기 때문, 

또, 모두 감싸면 참조의 투명성을 유지할 수 있음.