React 간단 복습

Ocean·2023년 10월 15일
1

공식 문서 중 React의 내부 구조 및 동작을 추정할 수 있는 부분 위주로 살펴보자

Hello World!

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(<h1>Hello, world!</h1>);
  • JSX 사용
  • 위 코드는 JavaScript 엔진이 이해할 수 있는 순수 JavaScript 코드로 변환될 것이라는 것을 알 수 있음

엘리먼트 렌더링

const element = <h1>Hello, world</h1>;

브라우저 DOM 엘리먼트와 달리 React 엘리먼트는 일반 객체이며(plain object) 쉽게 생성할 수 있습니다. React DOM은 React 엘리먼트와 일치하도록 DOM을 업데이트합니다.

여기서 두 가지 정보를 알 수 있다.

  1. JSX로 선언된 표현식은 React 엘리먼트라는 객체로 치환된다.
  2. React 엘리먼트는 일반 객체이다. (클래스 인스턴스가 아님)

또한, React 엘리먼트는 JSX 표현식이 치환된 객체이므로 태그 이름, 어트리뷰트 및 값 등의 정보가 있을 것이라고 유추해 볼 수 있다.

DOM에 엘리먼트 렌더링하기

const root = ReactDOM.createRoot( document.getElementById('root') ); 

const element = <h1>Hello, world</h1>; root.render(element);

여기서도 두 가지 정보를 알 수 있다.

  1. native DOM에 React 엘리먼트를 렌더링하기 위해서는 우선 루트를 생성해야 한다.
  2. React 엘리먼트는 바로 native DOM에 렌더링할 수 없고, 루트를 통해 렌더링해야 한다.

렌더링 된 엘리먼트 업데이트하기

const root = ReactDOM.createRoot( document.getElementById('root') );

function tick() {
	const element = ( 
		<div>
			<h1>Hello, world!</h1>
			<h2>It is {new Date().toLocaleTimeString()}.</h2>
		</div>
	); 
	root.render(element); 
} 

setInterval(tick, 1000);
  • 업데이트 시에도 생성과 유사하게 JSX 표현식을 통해 새로운 React 엘리먼트를 생성하고 루트를 통해 렌더링해야 함

변경된 부분만 업데이트하기

React DOM은 업데이트 시 변경된 부분만 native DOM에 반영하도록 되어 있다.

  • React 내부에서 비교 알고리즘을 통해 변경된 부분만 반영
  • DOM 트리 변경을 줄여 퍼포먼스 향상

리스트와 키

React에서는 형제의 태그 이름이 동일하다면 key 어트리뷰트를 선언하도록 권장한다.

  • React 엘리먼트는 태그 이름이 동일한 형제 중 key가 동일할 때 이전과 같은 React 엘리먼트라 추단하고 비교 및 렌더링을 시도한다

재조정(Reconciliation)

n개의 엘리먼트가 있는 트리를 다른 트리로 변환하는 알고리즘은 최소 O(n^3)으로 알려져 있다.

React는 아래 두 조건을 전제로 시간 복잡도가 O(n)인 휴리스틱 알고리즘을 재조정에 사용한다.
1. 서로 다른 타입의 두 엘리먼트는 서로 다른 트리를 만들어낸다.
2. 개발자가 key prop을 통해, 여러 렌더링 사이에서 어떤 자식 엘리먼트가 변경되지 않아야 할지 표시해 줄 수 있다.

즉, 다음과 같은 가정을 통해 O(n)의 휴리스틱을 달성했다.

  • 이전과 다른 타입의 React 엘리먼트로 교체되었다면 하위 트리는 더 이상 비교하지 않고 전체를 교체한다.
  • key가 동일한 React 엘리먼트는 이전과 동일한 엘리먼트로 취급한다.

Ref와 DOM

Ref의 바람직한 사용 사례

  • 포커스, 텍스트 서택 영역, 혹은 미디어의 재생을 관리할 때
  • 애니메이션을 직접 실행시킬 때
  • 서드 파티 DO< 라이브러리를 React와 같이 사용할 때

셋 모두 React에서 컨트롤 가능한 영역인 태그 이름, 어트리뷰트 등이 아니라 native DOM API 등을 직접 컨트롤해야 하는 경우이다.

반대로 말하자면 React가 제어 가능한 부분은 선언형 API를 통해 조작하라는 것!

이를 권고하는 이유

  • React는 JSX 표현식이 치환된 React 엘리먼트의 prop, states를 통해 React DOM을 갱신
  • Ref를 통해 native DOM을 직접 조작하면 이 변경 사항을 React가 유지하기 어렵다

virtual DOM과 Internals

virtual DOM (VDOM)은 UI의 이상적인 또는 “가상”적인 표현을 메모리에 저장하고 React DOM과 같은 라이브러리에 의해 “실제” DOM과 동기화하는 프로그래밍 개념입니다. 이 과정을 재조정이라고 합니다.

React 내부에는 native DOM과 동기화하기 위한 가상의 virtual DOM이 있다는 것을 알 수 있다.

“virtual DOM”은 특정 기술이라기보다는 패턴에 가깝기 때문에 사람들마다 의미하는 바가 다릅니다. React의 세계에서 “virtual DOM”이라는 용어는 보통 사용자 인터페이스를 나타내는 객체이기 때문에 React elements와 연관됩니다. 그러나 React는 컴포넌트 트리에 대한 추가 정보를 포함하기 위해 “fibers”라는 내부 객체를 사용합니다. 또한 React에서 “virtual DOM” 구현의 일부로 간주할 수 있습니다.

위 글에 따르면 virtual DOM은 React 내부에 실존하는 어떤 구체적인 인스턴스나 value라기보다는 React가 React 엘리먼트와 native DOM을 동기화하기 위한 패턴의 이름을 의미하며 문맥에 따라 지칭하는 실체가 다르다는 것을 알 수 있다. React 내부를 충분히 파악하지 않은 개발자들은 이 부분을 헷갈리기 쉬운데 React 내부에선 실제로 virtual DOM이라는 이름을 가진 개념이 존재하지 않는다.

profile
chick! chick!

0개의 댓글