리액트는 페이스북에서 만든 자바스크립트 라이브러리 중 하나로 UI(사용자 인터페이스)를 만들기위해 사용됩니다.
A JavaScript library for building user interfaces
참조 : 리액트 공식 문서
현재 리액트는 프론트엔드 개발자에게 가장 많이 사랑받고 있는 라이브러리 중 하나이다. 많은 기업에서도 리액트를 다룰 줄 아는 사람들을 요구하고 있으며 프론트엔드 개발자에게 리액트는 소양하고 있어야할 기술 중 하나가 됬습니다.
그렇다면 많은 라이브러리, 프레임워크들이 있지만 리액트가 어떠한 장점들이 지니고 있길래 꾸준히 사랑받고 있는것일까?
기존 자바스크립트만 가지고 개발을 할 수 있는데 어떠한 필요에 의하여 리액트가 만들어진것일까?
기존 웹 페이지를 렌더링할 때에 정적인 웹을 만들 때에는 html, css만 가지고 만들 수 있습니다. 동적인 웹을 만들기위해서는 javascript를 사용하여 DOM API를 사용하여 동적인 UI를 형성합니다. 예를 들어, 클릭을 하여 숫자를 바뀌게 할 때, 클릭을 하여 다른 슬라이드를 넘길 때, nav bar을 펼칠 때 등 자바스크립트를 사용하여 동적으로 웹을 형성할 때가 많습니다.
정적인 웹을 형성할 때에는 html,css가 파싱되어 렌더트리를 형성하면 플로우,페인트 작업이 이루어지지만 javascript로 노드 객체를 생성,삭제,변경을 한다면 리플로우,리페인트 작업이 이루어집니다.
플로우 : html 요소의 레이아웃을 계산하는 작업
페인트 : html요소를 그리는 작업
리플로우 : 다시 플로우되는 작업
리페인트 : 다시 페인트되는 작업
javascript가 DOM API를 사용하여 노드 객체를 생성,제거,변경할 때 리플로우,리페인트가
되어 기존에 변경될 필요 없는 부분까지 변경이 되는 불필요한 리렌더링 작업이 발생하여
성능에 악영향을 줄 수 있다.
동적인 작업이 몇가지 없다면 이는 성능에 큰 영향을 미치지않지만 그러한 작업이 여러가지이며 잦게 된다면 잦은 리플로우,리페인트 작업으로 성능에 악영향을 미칠 수 있습니다. 즉, 웹 앱 규모가 커졌을 때, DOM을 직접 건드리면서 작업을 하면 성능이 떨어지게 되는 것입니다.
이러한 이유로 기존 자바스크립트로는 동적인 작업이 잦은 웹을 만들기에는 한계가 있었던 것입니다. 때문에 동적인 작업이 많아져도 성능에 문제가 없고 UX(사용자의 경험)도 향상시킬 수 있는 방법으로 등장한 것들이 프레임워크 , 라이브러리인 것이고 그 중하나가 리액트인 것입니다.
이러한 프레임워크, 라이브러리는 위와 같아 성능에 악영향을 줄 수 있는 상황을 개선시켜줍니다. 기존 자바스크립트로 웹을 제어할 때에는 전체적으로 리렌더링이 됬지만 이들은 바뀌는 데이터의 부분에 대하여서만 뷰를 바꿔줍니다. 즉, 변화에 따라 필요한 곳만 바꿔주는 것입니다.
이러한 장점으로 기존 자바스크립트만 사용할 때 보다 성능을 향상시켜줄 수 있는 것이지요.
기존의 몇몇 프레임워크(Angular,Backbone.js,Ember.js 등)은 주로 MVC패턴, MVVM패턴을 사용합니다.
MVC(Model-View-Controller)
Model : 앱에서 데이터를 관리하는 영역
View : 사용자에게 보이는 부분
동작원리 : 프로그램이 사용자에게 어떤 작업(예: 버튼 클릭, 텍스트 입력 등)을 받으면 컨트롤러는 모델 데이터를 조회하거나 수정하고, 변경된 사항을 뷰에 반영
즉, 데이터가 변경됨에 따라 변경되는 부분만 뷰가 변하게 됩니다.
데이터가 업데이트되는 항목에 따라 어떤 부분을 찾아서 변경할지 규칙을 정하는 작업은 간단하지만, 앱의 규모가 크면 복잡해지고 제대로 관리하지 않으면 성능도 떨어질 수 있습니다.
(MVC 패턴 등을 쓰고 있는 프레임워크 및 라이브러리들을 추후에 더 알아보며 공부해봐야겠다.)
그리하여 페이스북에서는 한가지 방법을 떠올렸습니다. 데이터가 변경됨에 따라 뷰를 변형시키는 것이 아닌 기존 뷰를 날려버리고 처음부터 새로 렌더링하는 방식을 떠올려냈습니다. 이러한 방법은 어떻게 변화를 줘야될 지 신경쓸 필요도 없어 뷰에 관하여만 생각하면 되니 앱의 구조가 간단해질 수 있겠다고 생각했습니다.
하지만 기존 뷰를 날리고 데이터가 변할 때마다 새롭게 렌더링한다는 것은 기존 프레임워크,라이브러리를 쓰지 않았을 때로 돌아가는것이 아닌가라는 의문이 들 것입니다.
기존 자바스크립트도 데이터가 변화되면 새롭게 렌더링됬으니깐요.
이에 대한 해답으로 리액트는 Virtual Dom을 제시하고 있습니다.
Virtual DOM을 알아보기전에 리액트의 렌더링 방식을 먼저 알아보겠습니다.
리액트 작업을 할 때에 제일 먼저해야하는 작업은 터미널을 통하여 npm create(init) react-app <폴더이름> 을 하는 것입니다.
설치가 다 끝난 뒤에 여러가지 리소스들을 볼 수 있는데 그 중 public폴더에 가보면 index.html문서가 있습니다.
html문서는 이러한 식으로 코드가 구성되있습니다.
보시다시피 실제로 뷰를 보여주는 영역인 body태그 안에 id가 root인 div태그를 제외하고는 영향을 주는 요소가 없습니다.
그렇다면 어떻게 div태그 하나로 페이지를 구성할 수 있을까요?
기존 렌더링 방식은 html문서를 먼저 서버로부터 받아와 css파일과 함께 렌더트리를 구성하여 뷰를 보여주는데 위같은 경우는 div요소 하나만을 보여줍니다. 그리고 html에서는 div요소안에 아무것도 쓰여있지 않습니다.
그렇다면 js파일에서 접근하여 dom을 통하여 div요소에 접근한다는 것입니다. 이것은 초기 뷰부터 js에서 dom을 조작하여 뷰를 만들어낸다는 것인데 어떠한 원리인지 알아봅시다.
npm create react-app을 한 결과 src폴더에는 index.js라는 파일이 있으며 코드는 아래와 같이 구성되있습니다.
나중에 React와 ReactDOM이라는 모듈을 알아보겠지만 일단은 ReactDOM.render() 함수는 뷰가 어떻게 생겼는지 정의하는 역할을 합니다.
반환하는 값이 html 문자열을 반환하는 것이 아닌 뷰에 대한 정보를 지닌 객체를 반환합니다.
이 정보들을 가지고 HTML 마크업을 만들고 html에 있는 아까 div요소에 주입하게 되는 것입니다.
HTML문서에 script 코드가 없어도 render함수가 div요소를 찾아 주입해줍니다.
즉, 자바스크립트에서 DOM요소를 생성하고 변경하고 제거하는 작업을 다 한다는 얘기입니다.
방금 얘기했던 내용은 ReactDOM.render()를 살펴보면 잘 알아볼 수 있습니다.
ReactDOM 패키지는 여러가지 메서드를 제공하는데 그 중 render()라는 메서드는 다음과 같이 생겼습니다.
Render a React element into the DOM in the supplied container and return a reference to the component (or returns null for stateless components).
참조 : ReactDOM/리액트 공식 문서
container : DOM을 주입할 자리
element : 주입할 DOM요소
즉, container 위치에 DOM을 주입하는 것이고 이 element들이 컴포넌트가 되는 것입니다.
또한 공식 문서를 보면 이 ReactDOM.render()가 반환하는 것은 html문자열을 바로 반환하는 것이 아닌 루트 컴포넌트에 대한 참조를 반환하고 있다고 말하고 있습니다.
ReactDOM.render() currently returns a reference to the root ReactComponent instance.
참조 : ReactDOM/리액트 공식 문서
즉, ReactDOM.render 메서드는 리액트(jsx/컴포넌트/element)를 DOM에 사용할 수 있도록 해주는 메서드라고 정리할 수 있을 것 같습니다.
위에서 봤다시피 ReactDOM.render메서드가 리액트 렌더링을 할 수 있게 하는 역할이라는 것을 알았습니다.
그럼 아까 전의 의문점으로 돌아가 렌더링을 해주는 것은 알겠지만 어떻게
element요소들이 생성되고 변경될 때마다 즉, 데이터가 변경될 때마다 뷰를 새롭게 보여줄 수 있는지(리렌더링)가 궁금해집니다.
이에 대한 해답으로 Virtual DOM을 제시할 수 있습니다.
자바스크립트에서 DOM요소를 생성,변경,제거를 하면 불필요한 요소를 포함하여 전체적으로 리렌더링이 이루어집니다.
하지만 Virtual DOM은 그렇지 않습니다.
바뀌는 요소가 있다면 이전 DOM요소와 새로 렌더링된 Virtual DOM을 비교하여 바뀐부분만 DOM요소만 변경하여 DOM트리에 적용해줍니다.
즉, 전체적으로 리렌더링되는 부분은 Virtual DOM이고 바뀐 요소만 DOM트리에 적용된다는 것입니다.
즉, Virtual DOM은 효율적으로 리렌더링하여 불필요한 요소가 렌더링될 필요없이 변경되는 부분만 렌더링할 수 있도록 해주는 가상 DOM입니다.
이러한 점이 기존 자바스크립트와 리액트를 비교했을 때 렌더링 효율성의 차이를 설명할 수 있는 것입니다.
이리하여, 변경되는 부분만 변경될 수 있도록 하여 UI 구성에 집중할 수 있도록 고안된 것이 바로 리액트입니다.
리액트는 Virtual DOM이라는 특징을 가지고 데이터가 변경될때마다 리렌더링을 해줌과 동시에 업데이트되는 내용만 변경해주는 효율적인 시스템을 가지고 있습니다.
이는 업데이트되는 데이터에 관하여 어떤 변화를 줄지 고민하지 않아도 되어 사용자에게 보여주는 View에 집중하여 개발할 수 있습니다.
이러한 장점때문에 많은 사람들이 리액트를 사용한다고 생각합니다.
첫 포스팅에는 리액트가 무엇인지 알아보았는데요.
다음 포스팅에는 npm create(init) react-app 을 하였을 때 리액트의 코드들이 어떤 역할을 하는지 알아보겠습니다.
본 포스팅은 여러 참조 문서와 필자의 분석을 바탕으로 기록한 포스트이며 필자의 공부 기록 과정이므로 내용이 정확하지 않을 수 있다는 점을 말씀드립니다.
참조 :
리액트를 다루는 기술 by velopert
리액트 공식 문서