● 리액트란 왜 탄생했을까?
옛 시절,, 넷스케이프라는 브라우저에서 다양한 브라우저가 생긴 뒤 큰 혼돈을 겪고 ECMAscript가 이 혼돈을 잠재운 뒤, 지금의 자바스크립트가 되었습니다. 자바스크립트는 오로지 웹브라우저에서 간단한 연산과 시작적인 효과만 주는 언어에 불과했지만 현재는 웹 어플리케이션에서 가장 핵심적인 역할을 하게 되었습니다. 이제는 자바스크립트 만으로도 규모가 큰 어플리케이션 개발이 가능하게 된 것이죠.
하지만 오로지 '자바스크립트' 만으로 대규모 어플리케이션을 개발할 수 있을까요? 그건 좀 어려워 보입니다. 그래서 생긴 것이 다양한 프레임워크인데요. Angular, Backbone.js, Derby.js, Ember.js, Ext.js, Knockback.js, Sammy.js, PureMVC, vue.js 등이 생겨났습니다. 대부분의 프레임 워크들은 주로 MVC(Model-View-Controller) 아키텍처, MVVM(Model-View-View-Model) 아키텍처를 사용합니다. AngularJS 같은 경우 MVW(Model-View-Whatever) 아키텍처로 애플리케이션을 구조화합니다.
대부분의 아키텍처의 공통점은 Model, View가 있다는 점입니다. 도대체 Model 과 View가 뭘까요?
모델은 애플리케이션에서 사용하는 데이터 관리 영역을 말합니다. 뷰(view)는 사용자에게 보여지는 영역이며, 컨트롤러(controller)는 사용자가 어떤 작동을 한다면(클릭, 입력 등) 모델, 즉 데이터를 조회하거나 수정하고 변경된 사항을 뷰에 반영합니다.
예를 들어, 인스타그램의 좋아요를 들어보겠습니다. 인스타에서 좋아요를 누르면 좋아요의 개수가 바뀌겠죠?
그러면 컨트롤러는 모델에서 좋아요 데이터가 담긴 곳을 확인하고 데이터를 수정할 것입니다. 그리고 사용자에게 바뀐 데이터 대로 보여주겠죠. 이렇게 어떤 부분을 찾고, 수정하고 다시 보여주는 것은 간단한 일이지만. 만약에 데이터의 수도 많아지게 된다면 이 데이터를 관리하는 것은 매우 힘든일이 될 것입니다. 또한 변해야할 부분을 일일이 찾아야합니다. 동시에 여러 군데의 데이터가 바뀌었다면 바뀐 부분을 찾아야한다는 것이죠. 이는 매우 복잡해지며 성능이 떨어질 수 있습니다. 따라서 효율적인 방법을 찾기 위해 페이스북 개발팀은 이 뷰를 아예 없애버리고 새로 만드는 방식을 생각했습니다.
또한 바뀐 부분을 다시 보여준다..라?.. DOM 트리를 재구성하고 다시 렌더를 해야하는데.. 만약 데이터가 끊임없이 바뀌여야하는 상황이라면 어떡해야할까요? 예를 들어 실시간마다 코인의 가격이 바뀌는 웹 어플리케이션을 만들어야한다면? 이건 어떻게 구현해야할까요?
● 리액트의 이해
리액트는 MVC, MVW 아키텍처를 가진 프레임워크와 다르게 오로지 View 에만 신경을 쓰는 라이브러리 입니다. 리액트에서 어떤 특정부분이 어떻게 생길지 신경쓰는 것을 정하는 선언체가 있는데, 이것을 컴포넌트라고 합니다. 컴포넌트는 수많은 API 기능을 내장할 수 있으며 컴포넌트 하나에서 해당 컴포넌트의 생김새와 작동방식을 정의합니다.
리액트는 그렇다면 어떻게 성능의 부담 없이 리렌더링이 가능한 걸까요? 이는 컴포넌트가 최초로 실행한 '초기 렌더링' 과 컴포넌트의 데이터 변경으로 다시 실행되는 '리렌더링' 개념을 이해해야합니다.
⚬ 초기 렌더링
리액트에는 처음에 어떻게 보일지 결정하는 render 함수가 있습니다. 이는 렌더링을 해주는 것이죠.
이 함수는 컴포넌트가 어떻게 생길지를 결정합니다. render 함수를 실행하면 뷰가 어떻게 생겼고 어떻게 작동하는지에 대한 정보를 담은 객체를 반환합니다. 컴포넌트 내부에는 또 다른 컴포넌트가 들어갈 수 있습니다. 이 render 함수를 실행하면 그 내부에 있는 컴포넌트들도 렌더링 됩니다. 이렇게 최상위 컴포넌트의 렌더링 작업이 끝나면 지니고 있는 정보들을 가지고 HTML 마크업을 만들고, 이를 실제 페이지 DOM 요소 안에 주입합니다.
⚬ 조화 과정
컴포넌트의 데이터에 변화가 있을 때, 리렌더링의 과정이 생기게 됩니다. 이때 우리가 보기에는 뷰에 변화가 생기는 것처럼 보이지만, 실제로는 뷰를 새로 갈아끼우는 것입니다.
이 작업 또한 render 함수가 합니다. 컴포넌트는 데이터를 업데이트 했을 때 단순히 업데이트한 값을 수정하는 것이 아니라, 새로운 데이터를 가지고 render함수를 다시 호출합니다. 그럼 데이터를 기반한 새로운 뷰를 만들어냅니다. 하지만 바로 DOM 요소에 추가하지 않습니다. 이전 render함수가 만들었던 컴포넌트의 정보와 현재 정보를 비교합니다.
자바스크립트를 사용하여 두 가지 뷰를 최소한의 연산으로 비교한 뒤, 최소한의 연산으로 DOM 트리를 업데이트 하는 것입니다.
전체 컴포넌트를 다시 렌더링하는 것처럼 보이지만 사실 최적의 자원을 활용해 이를 수행하는 것입니다.
● 리액트의 특징
우리는 리렌더링을 할 때 웹페이지가 매우 버벅이고 느려지는 것을 경험할 수 있습니다. 그렇다면 DOM은 느린 것일까요? DOM은 느린 것이 아니라, 리렌더링을 할 때마다, DOM트리를 다시 구성하고, CSS를 다시 연산하고, 레이아웃을 계산하고 페이지를 리페인트하는 과정때문에 시간이 허비되는 것입니다.
하지만 그렇다고 DOM 조작을 아예 안할 순 없습니다. 정적인 페이지만 만들어야할까요? 아닙니다..!!
따라서 리액트는 Virtual DOM 방식을 사용하여 DOM 업데이트를 추상화 하여 DOM 처리 횟수를 최소화 하여 효율적으로 관리합니다.
⚬ Virtual DOM
Virtual DOM은 실제 DOM 조작에 접근하는 대신, 이를 추상화한 자바스크립트 객체를 구상하여 사용합니다.
- 데이터를 업데이트 하면 전체 UI를 Virtual DOM에 리렌더링합니다.
- 이전 Virtual DOM과 현재 내용을 비교합니다.
- 바뀐 부분만 실제 DOM에 적용합니다.
따라서 아까 예시에서 '새로운 DOM 트리' 가 바로 오른쪽이 Virtual DOM 입니다.
⚬ 기타 특징
일부 웹 프레임 워크인 MVC, MVW 등의 구조와 달리 리액트는 오로지 뷰만 신경씁니다. 따라서 리액트는 프레임워크가 아닌 라이브러리입니다. 리액트는 정말 뷰만 신경쓰는 라이브러리이기 때문에, 기타 기능은 직접 구현해서 사용해야합니다.
따라서 다른 개발자들이 만든 라이브러리, 즉 라우팅에는 리액트 라우터, Ajax 처리에는 fetch, axios가 있고 상태관리에는 redux와 MobX를 사용할 수 있습니다. 자신의 취향대로 스택을 설정할 수 있다는 장점이 있지만 또 너무 많은 라이브러리를 접해야한다는 단점이 있습니다.