React
리액트는 사용자 인터페이스(UI)를 더 쉽고 효율적으로 개발하기 위해 탄생한 자바스크립트 라이브러리입니다. 핵심적인 특징은 선언형 프로그래밍 방식을 채택했다는 점입니다.
- 명령형 프로그래밍 (JavaScript): 자바스크립트는 명령형 프로그래밍 방식으로 원하는 결과를 얻기 위한 모든 과정을 세세하게 코드로 작성해야 합니다.
- 선언형 프로그래밍: 반대로 선언형 프로그래밍은 과정은 생략하고 목적만 간결히 명시해서 결과를 얻는 방식입니다. 마치 음식점에서 주문을 하면 음식을 먹을 수 있는 것과 비슷합니다.
그럼 왜 많은 개발자들이 리액트를 선택할까요?
사람들이 리액트를 많이 이용하는 건 리액트만에 장점에서 있습니다.
1. 컴포넌트를 기반으로 UI를 표현
리액트의 가장 핵심적인 개념은 컴포넌트(Component)입니다. 컴포넌트는 웹 페이지를 구성하는 독립적인 요소로 마치 레고 블록처럼을 모아서 하나의 작품을 완성합니다.
2. 화면 업데이트 구현이 쉽다
기존 자바스크립트 방식에서는 사용자 행동의 따라 UI를 변경하기 위해 페이지를 다시 로드하거나 DOM을 직접 조작해야 했습니다. 리액트는 UI를 컴포넌트 단위는 특징을 이용해 컴포넌트의 state(상태)가 변경되면 해당 컴포넌트를 다시 렌더링합니다. 리액트의 첫번째 장점인 헤더, 푸터, 내비게이션 바 등 각각의 요소를 컴포넌트로 특징을 이용해서 화면 업데이트 코드 구현이 쉽습니다.
브라우저 렌더링 과정 (Critical Rendering Path)
리액트에 화면 업데이트가 빠른 이유에 대해서 알려면 브라우저 렌더링 과정에 대해서 알아야 되서 먼저 설명하겠습니다.
- HTML -> DOM, CSS -> CSSOM 변환: 브라우저는 HTML 코드를 이해하고 해석하여 DOM (Document Object Model)이라는 객체로 변환합니다. 마찬가지로 CSS 코드는 CSSOM (CSS Object Model)으로 변환됩니다.
- 렌더 트리(Render Tree) 생성: DOM과 CSSOM을 결합하여 실제로 화면에 표시될 요소들의 정보(위치, 크기, 스타일 등)를 담는 렌더 트리를 만듭니다. 이는 웹 페이지의 설계도와 같습니다.
- 레이아웃(Layout) 작업: 렌더 트리를 기반으로 각 요소들의 정확한 위치와 크기를 계산하는 레이아웃 작업이 수행됩니다.
- 페인팅(Painting) 작업: 계산된 레이아웃 정보를 바탕으로 각 요소들을 실제로 브라우저 화면에 그리는 페인팅 작업이 이루어집니다.
3. 화면 업데이트가 빠르게 처리된다.
기존 자바스크립트 방식에서는 UI 변경이 필요할 때마다 실제 웹 페이지의 구조인 DOM(Document Object Model)을 직접 조작해야 했습니다. 하지만 이 DOM 조작은 생각보다 많은 비용을 소모(특히 레이아웃, 페인팅)하며, 특히 불필요한 렌더링 과정을 반복적으로 일으켜 성능 저하의 주된 원인이 되곤 합니다.
나쁜 예시
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>비효율적인 DOM 업데이트 예시</title>
</head>
<body>
<ul id="list">
<li id="item-0">Item 1</li>
</ul>
<script>
const list = document.getElementById("list");
console.time("inefficient-dom-update");
for (let i = 1; i < 2000; i++) {
list.innerHTML += `<li>Item ${i + 1}</li>`;
}
console.timeEnd("inefficient-dom-update");
</script>
</body>
</html>
좋은 예시
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>효율적인 DOM 업데이트 예시</title>
</head>
<body>
<ul id="list">
<li id="item-0">Item 1</li>
</ul>
<script>
const list = document.getElementById("list");
let newItemsHTML = "";
console.time("efficient-dom-update");
for (let i = 1; i < 2000; i++) {
newItemsHTML += `<li>Item ${i + 1}</li>`;
}
list.innerHTML += newItemsHTML;
console.timeEnd("efficient-dom-update");
</script>
</body>
</html>
자바스크립트가 DOM을 직접 수정하면 브라우저의 렌더링 과정(레이아웃, 페인팅)이 반복적으로 발생하여 성능이 저하될 수 있습니다. 리액트는 이러한 비효율성을 해결하기 위해 가상 DOM(Virtual DOM)이라는 개념을 도입했습니다.
가상 DOM은 실제 DOM의 복사본 역할을 하는 자바스크립트 객체입니다. 리액트는 컴포넌트의 상태가 변경되면 실제 DOM을 즉시 수정하는 대신 변경 사항을 가상 DOM에 먼저 반영합니다. 그 후 이전 가상 DOM과 변경된 가상 DOM을 비교하여 실제 DOM에 적용해야 할 최소한의 변경 사항을 찾아냅니다. 마지막으로 찾아낸 변경 사항들을 모아서 실제 DOM에 한 번에 반영함으로써 불필요한 렌더링 과정을 최소화하고 성능을 최적화합니다.