프로그래밍 기술을 이해하고 잘 활용하기 위해서는 이 기술이 왜 만들어졌는지, 어떤 특징을 가졌는지 알 필요가 있습니다. 따라서 이번 절에서는 리액트의 탄생 배경과 그 특징에 대해 좀 더 깊이 들여다 보겠습니다. 일정 정도는 설명 위주의 내용이 되겠지만, 리액트의 특징을 제대로 알아 두면 앞으로 진행할 예제 실습과 프로젝트 수행에 중요한 밑거름이 됩니다.
리액트의 탄생
리액트는 복잡한 웹 서비스를 쉽고 빠르게 개발할 수 있는 Node.js의 라이브러리 가운데 하나입니다. 페이스북, 인스타그램, 넷플릭스 등 이름만 들어도 고개가 끄덕여지는 서비스를 개발한 기술이며, 지금도 전 세계 개발자들의 사랑을 듬뿍 받는 개발 도구입니다.
StateOfJavaScript에서는 리액트가 2016년부터 2021년까지 가장 많은 프로그래머가 사용하는 프론트엔드 기술이라는 통계를 공개한 바 있습니다.

StateOfJavaScript는 2016 년부터 꾸준히 전세계 자바스크립트 개발자들을 대상으로 설문 조사를 하며 그 결과를 매년 통계로 공개하는 서비스 입니다.
리액트는 페이스북 개발팀이 만들어 2013년 오픈소스로 세상에 공개되었습니다. 출시 초기부터 페이스북은 동시대에 나온 웹 서비스 중 유독 인터렉션(Interaction)이 많았습니다. 여기서 인터렉션은 상호작용, 소통이라는 뜻으로, 좋아요 버튼이나 채팅처럼 사용자와 웹 서비스 간에 양방향으로 소통하는 기능을 지칭합니다.
당시 대다수 기술은 정적인 웹을 구축하는 데 초점을 두고 있었기 때문에 페이스북이 원하는 다양한 인터렉션을 구현하기 힘들었습니다. 그래서 페이스북 개발팀은 서비스의 변화가 많고 사용자와 상호작용이 원활한 대규모 웹 애플리케이션을 쉽게 구축할 수 있는 기술이 필요했습니다. 그래서 이 기술을 직접 만들기로 하였고, 그 결과로 탄생한 것이 리액트입니다.
리액트는 변화가 자주 일어나는 대규모 애플리케이션을 구축할 때 필요한 여러 기능을 구비하고 있습니다. 이번 절
에서는 이러한 리액트의 3가지 특징을 살펴보겠습니다.
컴포넌트 기반의 유연성
리액트는 유연성이 있기 때문에 새로운 기능을 추가하거나 기능을 업그레이드할 때 코드를 많이 수정하지 않아도 됩니다. 유연성이 없을때 어떤 문제가 발생하는지 그리고 리액트가 채택한 ‘컴포넌트’ 개념이 유연성 문제를 어떻게 해결하는지 살펴보겠습니다.
중복 코드와 유연하지 못한 구조
다음은 두 페이지로 구성한 아주 간단한 홈페이지의 소스 코드입니다. 이 코드를 굳이 따라 작성할 필요는 없습니다.
코드를 불러오는 중 입니다 ...코드를 불러오는 중 입니다 ...index.html은 index 페이지, about.html은 about 페이지입니다. 이 두 페이지의 구성은 매우 유사하며, <header> 태그는 내용이 완전히 똑같습니다.
홈페이지에서 앞으로 추가할 페이지 또한 이 페이지들과 동일한 내용의 헤더 요소가 있다고 가정해 보겠습니다.
예를 들어 other.html 페이지를 하나 더 추가해 보겠습니다.
코드를 불러오는 중 입니다 ...other.html 역시 똑같은 내용의 헤더 요소가 있습니다. 따라서 앞으로 새 페이지를 추가할 때 <header> 태그 요소는 기존 페이지의 소스 코드에서 복사하여 붙여 넣고, <article> 태그에서 해당 페이지에 필요한 요소만 새롭게 작성하면 됩니다.
이 홈페이지의 <header> 태그처럼 동일한 내용을 여러 번 작성해야 하는 코드를 흔히 중복 코드라고 합니다. 코드의 중복은 유연성을 크게 헤칩니다. 만약 이 홈페이지 <header> 태그에서 수정이 생기면, 모든 페이지에서 이 태그를 변경해야 하기 때문입니다.

이런 식의 페이지 구성은 유연하지 못합니다. 페이지의 수가 많고, 기능 수정 또는 추가가 잦은 대규모 애플리케이션을 구축할 때는 적합하지 않습니다.
컴포넌트 기반의 유연한 구조
리액트는 모듈화를 이용해 중복 코드를 제거합니다. 즉, 여러 페이지에서 공통으로 사용하는 코드를 ‘컴포넌트’ 단위의 모듈로 만들어 놓고 필요할 때 호출해 사용합니다.
컴포넌트는 리액트를 대표하는 중요 개념 중 하나인데, 이 개념에는 ‘페이지를 구성하는 요소’라는 의미가 포함되어 있습니다. 앞에서 문제의 원인이었던 <header> 태그를 컴포넌트로 만들면 다음과 같습니다.
코드를 불러오는 중 입니다 ...주의하세요!
이 코드는 컴포넌트의 이 해를 돕기 위한 예제입니다.
따라서 실제로 동작하지는 않습 니다. 참고로
<!-- -->
는 HTML의 주석 표현입니다.자바스크립트 함수 MyHeader는 <header> 태그를 반환합니다. 이렇게 HTML 요소를 반환하는 함수를 리액트에서는 ‘컴포넌트’라고 합니다.
만약 <header> 태그가 필요한 페이지가 있다면 언제든지 이 컴포넌트를 불러와 사용하면 됩니다.
코드를 불러오는 중 입니다 ...① MyHeader 컴포넌트를 불러와 사용합니다.
index.html 외에 다른 페이지에서도 이 컴포넌트를 불러와 위와 같은 방식으로 똑같이 사용할 수 있습니다. 만약 Header 컴포넌트에 변경 사항이 있어 코드를 수정하면, 일괄적으로 모든 페이지에 자동으로 반영되므로 기능 하나를 수정하기 위해 모든 페이지를 수정할 필요가 없습니다.
컴포넌트를 더 자세히 이해하기 위해 리액트로 개발한 간단한 서비스를 살펴보겠습니다. [그림 4-3]은 그날의 감정과 함께 일기를 기록하는 서비스인 [감정 일기장]입니다. [감정 일기장]은 여러분이 실제로 구현하게 될 이 책의 최종 프로젝트입니다.
[감정 일기장]은 리액트로 개발하기 때문에 다음과 같은 컴포넌트로 구성되어 있습니다.
![[감정 일기장]의 컴포넌트](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fd28568f6-7ee0-4a52-bb29-87d48d310a89%2FUntitled.png?table=block&id=7dcdbe47-ebb0-48e2-8f39-247b2c4b3040&cache=v2)
상단에 헤더가 있고 중간에는 필터 그리고 여러 개의 일기 아이템 컴포넌트가 있습니다. 헤더는 현재 날짜를, 필터는 일기 아이템의 필터링을, 아이템 컴포넌트는 여러 개의 일기 정보를 각각 표시합니다. 각각의 컴포넌트는 독립적인 기능을 수행하면서도 조화롭게 하나의 페이지를 구성합니다.
리액트의 컴포넌트는 어떤 페이지에서도 불러올 수 있습니다. 예를 들어 A 페이지에서 헤더 컴포넌트가 필요하면 해당 페이지로 불러오면 되고, B 페이지에서 필요하면 똑 같은 방식으로 불러와 사용하면 됩니다. 필요가 없어지면 삭제하면 그만입니다. 이렇듯 리액트에서는 컴포넌트를 마치 조립용 레고 블록처럼 다룰 수 있어 매우 유연하게 페이지를 구성합니다.
쉽고 간단한 업데이트
업데이트란 웹 페이지의 정보를 교체하는 일입니다. 업데이트의 좋은 예로 오늘날 대표적인 SNS로 자리 잡은 인스타그램(Instagram)의 ‘좋아요’ 기능이 있습니다.

인스타그램에서는 다른 사람이 올린 게시물에서 하트 모양 아이콘을 클릭해 ‘좋아요’ 를 표시할 수 있습니다. 좋아요 아이콘을 클릭하면 아이콘은 붉은색으로 변합니다.
웹에서 페이지를 업데이트하려면 문서 객체 모델(Document Object Model, DOM)을 조작해야 합니다. 문서 객체 모델은 줄여서 돔(Dom)이라고 부릅니다. 앞으로는 문서 객체 모델을 돔이라고 하겠습니다. 돔은 HTML 코드를 트리 형태로 변환한 구성물입니다.
돔은 웹 브라우저가 직접 생성하며, HTML 코드를 렌더링하기 위해 만듭니다. 렌더링(Rendering)이란 브라우저가 웹의 3가지 언어 HTML, CSS, 자바스크립트를 해석해 페이지의 요소를 실제로 그려내는 과정입니다.
간단한 돔의 예를 보면 쉽게 이해할 수 있습니다.
[그림 4-5]의 왼쪽 HTML 코드는 오른쪽의 돔으로 변환됩니다. 돔은 돔 API(DOM API)를 제공하는데, 자바스크립트는 이 API로 돔에 접근해 요소를 수정, 추가, 삭제할 수 있습니다.

API란?
API(Application Program-ming Interface)는 특정 대상을 손쉽게 사용하거나 제어할 목적으로 사용하는 도구입니다.
돔 API는 자바스크립트를 이용해 돔을 조작하는 다양한 기능을 지원하는 도구입니다.
다음은 자바스크립트로 돔에 접근해 요소를 수정하는 예입니다.
코드를 불러오는 중 입니다 ...① 버튼을 클릭하면 함수 onClickButton이 실행됩니다. ② document는 돔을 의미합니다. getElementById 메서드는 돔에서 인수로 전달한 태그의 id 요소 를 찾아 반환합니다. 결론적으로 태그 <h1 id='h1'>이 상수 h1Elm에 저장됩니다. ③ innerText는 돔 요소의 텍스트입니다. h1Elm에 저장된 요소의 텍스트를 "반가워요!"로 변경합니다.
이 코드를 실행하면 제목과 버튼이 있는 페이지가 나타나고, 버튼을 클릭하면 자바스크립트 함수가 실행되어
돔을 수정합니다. 그 결과 제목의 문구가 안녕하세요!에서 반가워요!로 바뀝니다.
다음은 페이지에서 버튼을 클릭하면 일어나는 과정을 그림으로 표현한 내용입니다.

자바스크립트로 돔을 조작하면 페이지를 새롭게 렌더링하여 업데이트합니다.
그런데 돔에서 원하는 요소를 찾고 수정 사항을 반영하는 일은 언제나 간단하지 않습니다. 돔은 트리 구조
로 이루어져 있기 때문에 구성이 복잡하면 정확히 원하는 요소를 찾기 어렵습니다.
리액트는 이 문제를 아주 파격적인 방식으로 해결합니다. 사용자의 특정 행동(예를 들어 좋아요 버튼 클릭)이 일어나거나 데이터가 바뀌어 업데이트가 필요하면, 어떤 요소를 어떻게 업데이트할지 고민하지 않습니다. 교체가 필요한 요소는 삭제하고, 새롭게 수정 사항을 반영한 요소를 다시 만들어 통째로 업데이트합니다. 리액트의 이런 동작 방식은 마치 자동차가 고장 나면 일일이 망가진 부품을 찾아내 수리하기보다 아예 새 차로 바꾸는 행위와 비슷합니다.
따라서 리액트를 이용하면 어떤 부분을 어떻게 업데이트할지 고민하지 않아도 간단하게 페이지를 업데이트할 수 있습니다. 그래서 복잡한 인터렉션을 지원하는 웹 서비스 개발에 더 집중할 수 있습니다.
빠른 업데이트
빠른 업데이트는 웹 서비스의 성능을 좌우하는 중요한 요소입니다. 만약 사용자가 버튼을 클릭할 때마다 페이지를 업데이트하는 데 5초 이상 걸린다면 매우 짜증이 날 겁니다.
리액트는 빠른 업데이트를 제공합니다. 이번에는 리액트가 빠르게 페이지를 업데이트하기 위해 어떤 기능을 지원하는지 살펴보겠습니다.
브라우저는 어떻게 페이지를 표시할까?
업데이트는 결국 브라우저가 페이지를 다시 렌더링하는 행위입니다. 예를 들어 버튼을 클릭했을 때 버튼의 색상을 파란색에서 빨간색으로 바꾸려면 브라우저가 페이지를 다시 렌더링해야 합니다. 따라서 리액트가 어떻게 빠르게 업데이트하는지 알려면 브라우저의 렌더링 과정을 먼저 이해할 필요가 있습니다.
브라우저의 렌더링 과정은 [그림 4-7]처럼 크게 4단계로 구분할 수 있습니다.

- HTML 코드를 해석해 돔으로 변환합니다. 마찬가지로 CSS 코드도 해석해 스타일 규칙(Style Rules)으로 변환합니다.
- 페이지에 어떤 요소가 있고 어디에 있는지를 아는 돔과 돔 각각의 요소에 스타 일을 정의하는 스타일 규칙을 합쳐 렌더 트리(Render Tree)를 만듭니다.
- 렌더 트리 정보를 바탕으로 요소의 위치를 픽셀(px) 단위로 계산합니다. 이 과정을 레이아웃이라고 합니다. 레이아웃은 렌더링 과정에서 가장 많은 연산을 요구하는 작업입니다.
- 레이아웃 작업을 거치면 해당 정보를 바탕으로 요소를 실제로 페이지에 그립니다. 이 과정을 페인팅이라고 합니다. 페인팅 역시 레이아웃과 더불어 렌더링 과 정에서 가장 많은 연산을 요구하는 작업입니다.
돔이 변경되면 브라우저는 업데이트를 위해 렌더링 과정을 다시 반복합니다. 앞서 살펴본 렌더링 과정에서 요소의 위치를 결정하는 레이아웃과 요소를 실제로 페이지에 표시하는 페인팅 과정은 많은 연산을 동반합니다. 따라서 돔의 업데이트가 필요 이상으로 많아지면 브라우저의 성능을 떨어뜨리게 됩니다. 브라우저의 성능이 떨어지면 소위 랙(lag) 현상이 일어나거나 심할 경우 응답 불능 상태에 빠집니다
랙(lag)은 컴퓨터 통신이 일시 적으로 지연되는 것을 나타낼 때 사용하는 용어지만, 웹에서 페이지의 응답이 느려지는 현상을 지칭하기도 합니다.
버추얼 돔을 이용한 효율적인 업데이트
페인팅과 레이아웃을 여러 번 수행하지 않으려면 여러 번의 업데이트를 모았다가 업데이트가 필요할 때 한 번에 처리하는 편이 효율적입니다. 리액트는 이를 위해 버추얼 돔(Virtual DOM)을 활용합니다. 버추얼 돔은 가상의 돔이라는 뜻으로, 실제 돔의 사본입니다.
리액트에서는 페이지에서 변경 사항이 발생하면 먼저 버추얼 돔을 업데이트하는 식으로 변경 사항을 모았다가 한 번에 실제 돔을 업데이트합니다.
다음 그림은 3번의 업데이트가 버추얼 돔에서 발생한 상황과 실제 돔의 업데이트 과정을 묘사한 그림입니다.

버추얼 돔을 3번 변경할 동안 실제 돔에는 아무런 변화가 없습니다. 변경 사항이 모두 종료되면, 변경 사항을 모았다가 한 번에 실제 돔을 업데이트합니다.
결과적으로 리액트에서는 여러 번의 업데이트를 모아 한 번에 수행 하므로, 업데이트가 잦아도 브라우저의 성능을 떨어뜨리지 않습니다.