[TIL] React 알아가기 (4) : 선언형, 렌더링, 가상 DOM

invisibleVoice·2025년 1월 21일

리액트

목록 보기
5/14
post-thumbnail

선언형 프로그래밍

컴포넌트란 UI 요소를 표현하는 최소한의 단위이며 화면의 특정 부분이 어떻게 생길지 정하는 선언체다. 우리는 보여주고자 하는 UI 요소를 컴포넌트 내부의 JSX를 통해 선언만 하면 리액트가 화면에 그려준다.

명령형 프로그래밍과 비교

바닐라 JS를 이용하면 UI를 표현하기 위해 모든 절차를 일일히 코드로 작성해주어야 한다.

// 명령형
const root = document.getElementById('root'); 
const header = document.createElement('h1'); 
const headerContent = document.createTextNode(
	'Hello, World!'
);

header.appendChild(headerContent); 
root.appendChild(header);

반면 리액트는 JSX로 UI를 선언하면 리액트가 알아서 절차를 수행해 화면에 출력해준다. 어떻게 화면에 그리는지는 리액트 내부에서 알아서 한다. 내부 동작이 어떻게 돌아가는지 외부에서 알 필요없고, 무엇을 하는지만 알면 되는 것을 추상화라고 한다.

// 선언형
const header = <h1>Hello World</h1>; // jsx
ReactDOM.render(header, document.getElementById('root'));

렌더링

리액트에서 렌더링이란, 컴포넌트가 현재 props와 state의 상태에 기초하여 UI를 어떻게 구성할지 (리액트가) 컴포넌트에게 요청하는 작업을 의미한다.

렌더링을 식당으로 비유하자면 :
클라이언트는 손님, UI는 음식, 리액트는 웨이터, 컴포넌트는 주방장이라 할 수 있다.

렌더링의 프로세스는 크게 3단계로 나누어진다.
1. Trigger : 렌더링을 일으키는 것. 음식(UI)을 주문하여 주방으로 전달하는것과 같다.

2. Render : 렌더링 과정. 주방에서 컨포넌트가 UI를 만들고 준비하는 것과 같다.

3. Commit : 렌더링 결과를 실제 DOM에 적용하는 것. 리액트가 준비된 UI를 손님(클라이언트) 테이블(DOM)에 올려놓는 것과 같다.

렌더링 트리거

렌더링은 크게 두 가지 상황에서 발생한다.

  • 첫 리액트 앱을 실행했을 때 :
    리액트 애플리케이션이 실행되고 첫 렌더링이 일어나면 리액트는 컴포넌트의 루트부터 시작해서 끝까지 훑으며 컴포넌트가 반환하는 JSX를 DOM 요소에 반영한다.

  • 현재 리액트 내부에 어떤 state에 변경이 생겼을 때

    • 컴포넌트 내부 state가 변경될 경우

    • 컴포넌트에 새로운 props가 들어올 경우

    • 상위 부모 컴포넌트에서 위 두 가지 이유로 렌더링이 발생할 경우 :
      이 경우에는 렌더링이 발생한 컴포넌트의 모든 자손 컴포넌트가 렌더링 된다.

리렌더링

첫 렌더링은 자동으로 일어난다. 그 이후에 렌더링 되는 상황은 state가 변할 때이다. (참고로 state를 변하게 하는 방법은 setState말고도 몇 가지가 더 있다.)

state가 여럿 변할 경우 리액트는 이것들을 queue에 넣어 순서를 관리한다.

리렌더링의 프로세스도 위 처럼 3단계로 나누어 보면 :
1. 손님이 추가로 음식을 주문하거나 처음 받은 음식을 다른 음식으로 교체해달라 한다.

2. 이런 새로운 UI 주문, 즉 리렌더링이 일어나면 리액트는 변경된 내용을 컴포넌트에게 전달한다. 컴포넌트는 새로운 주문을 토대로 새로운 UI를 만든다.

3. 리렌더링된 결과는 리액트가 손님 테이블에 다시 올려놓는다. = Commit

브라우저 렌더링은 리액트의 렌더링과 아예 다른 개념이다. 렌더링이 완료되고 DOM이 업데이트 되면 브라우저가 이를 토대로 화면을 그리는데, 이 프로세스가 브라우저 렌더링이다. 페인팅 이라고도 한다.


DOM과 Virtual DOM

React나 Vue는 가상 돔을 지원한다. 가상 돔은 자체적으로 상당히 효율적인 알고리즘을 사용하기 때문에 속도가 어마무시하게 빠르다!

DOM

DOM은 이전 포스트에서도 수없이 많이 나온 용어다.

웹 페이지는 문서(Document)라고 하고, 이 문서는 여러 요소(Element)들로 이루어져 있다. 이 요소 하나하나를 노드로 만들어 문서를 트리 형태의 객체로 표현한 것. 이것이 DOM이다!

DOM은 DOM API를 통해 접근과 제어가 가능한데, 실제 DOM을 조작하는 일은 리소스를 많이 잡아먹는 무거운 작업이다. 그래서 효율적인 문서 수정을 위해 새로운 개념이 필요하게 되었다.

Virtual DOM

그것이 바로 가상 DOM이다. 가상 DOM은 실제 DOM과 구조가 똑같은 객체 형태로 메모리에 저장되기 때문에 실제 DOM을 조작하는 것 보다 훨씬 빠르게 조작이 가능하다. 즉, 실제 DOM의 가벼운 복사버전이라고 할 수 있다.

문서의 일부가 변경되었을 때 가상 DOM을 이용하여 실제 DOM을 바꾸는 과정을 살펴보자.

리액트의 DOM 조작 과정

1. state change 상태 변화
리액트는 2가지 버전의 가상 DOM을 가지고 있다.

  • 화면이 갱신되기 전 구조를 가진 가상 DOM
    현재 화면에 보이는 실제 DOM의 구조와 같은 상태다.
  • 화면이 갱신된 후 보여야 할 가상 DOM
    state가 변경되면 리렌더링이 되고, 그 때 이 가상 DOM이 만들어진다.

2. Diffing 변경점 계산
state가 변경된 두 번째 가상 DOM과 기존의 첫 번째 가상 DOM을 비교하여 어떤 부분에서 변화가 일어났는지 빠르게 파악한다.

3. Reconciliation 재조정
변경이 일어난 그 부분만 실제 DOM에 적용 시킨다. 적용시킬 부분이 많을 경우, 하나씩 차례대로 변경되는 것이 아니라 변경 사항을 모두 모아 한 번만 적용을 시켜 한꺼번에 변경한다. 이를 Batch Update라고 한다.

이후의 브라우저 렌더링

리액트가 실제 DOM을 업데이트하면, 브라우저의 렌더링 엔진에 의해 변경 사항들이 화면에 반영된다. 다음 세 단계를 거친다 :
1. 스타일 계산: HTML과 CSS를 분석해 각 요소의 스타일을 계산
2. 레이아웃: 각 요소의 위치와 크기 계산
3. 페인팅: 게산된 요소들을 화면에 그린다.

profile
내배캠 React 9기 수료 후 Wecommit 풀스택 개발자로 근무중

0개의 댓글