Leon Chaewon Kong's dev blog

리액트(React)란 무엇인가

목차

1.React란 무엇인가
  1.1 왜 React를 사용하는가?
  1.2 React의 작동방식
  1.3 왜 Virtual DOM인가?
2. React의 특징
  2.1 Flux 패턴과 단방향 데이터 바인딩
  2.2 Component 기반 구조
  2.3 Virtual DOM
  2.4 JSX 문법
3. 언제 React를 써야 하는가
마치며
출처

1.React란 무엇인가

React는 페이스북에서 제공하는 자바스크립트 UI 라이브러리다. 즉 React 프론트엔드 라이브러리다. Angular가 프레임워크인 데 반해 React는 라이브러리다. 즉, 웹을 만드는 데 꼭 필요한 도구들이 전부 기본적으로 제공되지 않는다. 그런만큼 가볍고, 선택의 폭이 넓다.

React는 컴포넌트 기반이다. 컴포넌트에 데이터를 흘려보내면 설계된 대로 UI가 조립되어 사용자에게 보여진다.

1.1 왜 React를 사용하는가?

웹페이지를 만들기 위해서 굳이 프론트엔드 라이브러리를 사용해야 할 필요는 없다. HTML과 CSS, 그리고 순수 자바스크립트 만으로도 웹페이지를 얼마든지 제작할 수 있다. 특히 단순한 정적 페이지를 만드는 것이 목적이라면 React와 같은 프론트엔드 라이브러리는 큰 이득이 되지 못한다.

하지만 요즘의 웹은 정적이고 단순한 페이지가 아니다. 웹앱 혹은 웹 어플리케이션이라 불릴 정도로 복잡하고 동적이다. 이런 웹 어플리케이션에서 UI를 동적으로 나타내기 위해서는 복잡하고 많은 상태를 관리해야 하는 부담이 생긴다.

만약 프로젝트 규모가 크고 다양한 UI와 상호작용이 필요하다면 DOM 요소 하나하나를 직접 관리하는 것은 힘든 일이다. 또, 복잡하게 늘어진 코드를 리팩토링 하는 것도 점점 힘들게 된다.

React를 사용하면 사용자와 상호작용할 수 있는 interactive한 UI를 쉽게 만들 수 있다. React를 사용하면 기능과 UI 구현에 집중하고 불필요한 주의력 분산을 줄일 수 있게 된다.

또, React를 사용하면 브라우저 전체를 새로고침 하지 않고도 컨텐츠를 빠르게 변경할 수 있다.

1.2 React의 작동방식

React는 이벤트로 인해 데이터를 관리하는 Model에 변화가 생기면 Virtual DOM을 생성한다. 이후 Virtual DOM과 실제 DOM을 비교하고, 변화가 발생한 부분만 업데이트 한다.

1.3 왜 Virtual DOM인가?

복잡한 SPA에서는 DOM 조작이 많이 발생한다. 그 때마다 브라우저가 연산을 해야 하므로 전체적인 프로세스가 비효율적으로 되기 쉽다.

하지만 Virtual DOM을 사용하면, 실제 DOM에 적용시키기 전 가상의 DOM을 만들어 적용시키고, 최종 완성된 결과만을 실제 DOM으로 전달한다. 이를 통해 브라우저가 진행하는 연산의 양을 줄일 수 있어 성능이 개선된다. Virtual DOM은 렌더링도 되지 않기 때문에 연산 비용이 적다. 모든 변화를 Virtual DOM을 통해 묶고 이를 실제 DOM으로 전달한다.

2. React의 특징

2.1 Flux 패턴과 단방향 데이터 바인딩

React는 양방향 바인딩이 전제되는 MVC 패턴과는 다른 특징을 보인다. 페이스북에서 Flux라고 부르는 패턴이 적용되어 있는데, 단방향 바인딩이 특징이다.

위 도표는 MVC 패턴과 Flux 패턴의 차이를 보여준다. Flux 패턴은 일방통행이다. 따라서 단방향 바인딩이라고 한다.

그렇다면 React에서는 왜 MVC 패턴을 사용하지 않고 Flux 패턴을 사용하는 것일까? 다음 인용문을 읽어보면 답을 알 수 있다.

문제는 페이스북과 같은 대규모 애플리케이션에서는 MVC가 너무 빠르게, 너무 복잡해진다는 것이다. 페이스북 개발팀에 따르면 구조가 너무 복잡해진 탓에 새 기능을 추가할 때마다 크고 작은 문제가 생겼으며 코드의 예측이나 테스트가 어려워졌으며 새로운 개발자가 오면 적응하는데만 한참이 걸려서 빠르게 개발할 수가 없었다. 소프트웨어의 품질을 담보하기가 힘들어졌다는 뜻이다. 이 같은 문제의 대표적인 사례가 바로 페이스북의 안 읽은 글 갯수(unread count) 표시이다. 사용자가 읽지 않았던 글을 읽으면 읽지 않은 글 갯수에서 읽은 글 수만큼 빼면 되는 일견 단순해보이는 기능인데도, 페이스북 서비스에서 이를 MVC로 구현하기는 어려웠다고 한다. 어떤 글을 ‘읽음’ 상태로 두면, 먼저 글을 다루는 thread 모델을 업데이트 해야하고 동시에 unread ​count 모델도 업데이트 해야한다. 대규모 MVC 애플리케이션에서 이 같은 의존성과 순차적 업데이트는 종종 데이터의 흐름을 꼬이게 하여 예기치 못한 결과를 불러일으킨다. (출처: Flux와 Redux, Webframeworks.kr )

페이스북에서는 Flux라는 새로운 패턴을 만들어냈다. 이를 통해 복잡한 앱에서도 데이터 흐름에서 일어나는 변화가 보다 더 예측가능해지게 되었다.

React의 아키텍쳐는 기존 MVC 패턴에서 View에 집중한 형태이다. 여기서 View는 스토어에서 데이터를 가져오는 한편, 자식 뷰로 데이터를 전달하기도 하므로 단순 View라기 보다는 View-controller에 가깝다.

React에서는 State가 View를 업데이트 한다. 그러나 View는 State를 직접 업데이트 할 수 없다. View가 State의 정보를 업데이트하기 위해서는 callback을 통해 state를 바꿔야 하며, 이렇게 바뀐 Staterk View를 업데이트해 새롭게 정의한다. 실제로는 setState()를 통해 state를 업데이트 하며, State가 업데이트 되면 View는 다시 렌더링된다.

2.2 Component 기반 구조

React는 UI(혹은 View)를 여러 컴포넌트(Component) 쪼개서 만든다. 한 페이지 안에서도 Header, Footer 등 각 부분을 독립된 컴포넌트(Component)로 만들고, 컴포넌트들을 조립해 화면을 구성한다.

컴포넌트 기반이라는 점은 React의 큰 장점이다. 여러 화면에서 재사용되는 코드를 반복해 입력할 필요 없이 컴포넌트만 임포트해 사용하면 된다. 또, 기능단위, UI단위로 쪼개어 코드를 관리하므로, 어플리케이션이 복잡해져도 코드의 유지보수가 용이하다.

<html>
  <head>
    <title>블로그</title>
  </head>
  <body>
    <header>
       <!-- 헤더 내용 -->
    </header>
    <div class="post-list">
       <!-- 콘텐츠 리스트 -->
    </div>
    <footer>
      <!-- 푸터 내용 -->
    </footer>
  </body>
</html>

위와 같은 어플리케이션이 있다고 하자. 이를 React로 만들게 되면 대략 다음과 같다.

import React, { Component } from "react";
import Header from "./component/Header";
import Footer from "./component/Footer";
import PostList from "./component/PostList";

class App extends Component {
  render() {
    return(
      <div>
        <Header />
        <PostList />
        <Footer />
      </div>
    )
  }
}

export default App;

Header나 Footer PostList 등은 컴포넌트로 만들고, 이를 조립해서 루트 컴포넌트를 만드는 방식이다.

2.3 Virtual DOM

DOM은 Document Object Model의 약자이다. DOM은 html, xml, CSS 등을 트리 구조로 인식하고 데이터를 객체로 간주해 관리한다. html 코드를 브라우저에서 열게 되면 DOM이 브라우저에서 보이는 View를 만드는 식이다.

JavaScript는 DOM을 조작할 수 있다. 이를 통해 눈에 보이는 값을 변경하는 등 웹을 동적으로 만든다.

앞서 살펴보았듯이, 이벤트가 발생할 때마다 Virtual DOM을 만들고 실제 DOM과 비교하여 변경사항만 실제 DOM에 반영하여 앱의 효율성을 개선하게 된다. React가 여러 Component로 View를 쪼갠 이유도 이런 부분 업데이트를 원활하게 하기 위함이다.

Virtual DOM과 실제 DOM의 차이는 Tree Diff Algorithm을 통해 계산된다. 일반적으로 트리를 다른 트리로 바꾸는 알고리즘은 O(n^3)의 시간복잡도를 가지게 된다. React는 그들만의 휴리스틱한 알고리즘을 만듦으로써 시간복잡도를 O(n)으로 개선하였다.

React Diff Algorithm

React DOM diff 알고리즘

2.4 JSX 문법

JSX는 과거 페이스북이 PHP를 개량해 만들었던 XHP에 기원을 두고 있는 새로운 자바스크립트 문법이다. React는 JSX로 짜여진다. JavaScript가 아니다.

JSX의 특징은 기본적으로 html과 유사하다. 다만 약간의 원칙이 더 존재한다.

a. 두개 이상의 엘리먼트는 무조건 하나의 엘리먼트로 감싸져 있어야 한다.

<div>
  <p>first line</p>
  <p>second line</p>
</div>
<div>
  <p>second block</p>
</div>

위 태그처럼 두개의 div가 병렬로 존재한다면 새로운 div 태그로 감싸거나 fragment를 React를 임포트 하는 라인에서 같이 임포트해서 fragment 태그로 감싸줘야 한다. fragment 태그는 React에서 div를 추가해 감싸고 싶지는 않지만 다른 태그를 감쌀 필요성이 있을 때 사용할 수 있도록 React에서 제공하는 태그이다.

b. class 대신 className을 사용한다.

c. 스타일 속성은 중괄호({}) 안에 객체 형태로 표시하며 단어 사이의 ‘-‘를 없애는 대신 카멜케이스(Camel Case)를 사용해 CSS 프로퍼티를 나타낸다.

<div className="container" style={{backgroundColor: "red", fontSize: 16}} />

d. 모든 태그는 반드시 닫혀 있어야 한다. 인풋 태그의 경우 html에서는 닫지 않고 사용하는 경우도 있으나, JSX에서는 단축문법으로라도 반드시 닫아야 한다.

<input />

e. JSX 안에서 JavaScript 값을 사용할 때엔 중괄호를 사용한다. 중괄호 안에 변수명을 입력하거나 JavaScript 계산식, 값 등을 넣을 수 있다.

<div>
{name}
</div>

f. 주석은 {/**/}로 내용을 감싼다.

3. 언제 React를 써야 하는가

웹 기반 계산기를 만든다고 가정하자. 2+2의 답을 사용자에게 알려주는 데에는 굳이 서버를 거쳐야 할 이유가 없다. 브라우저도 충분히 연산을 해낼 수 있다. 따라서 계산의 내용을 서버로 보내고, 서버가 이를 기록한 후 계산 결과를 반환하는 방식은 비효율적이게 된다.

한편, 블로그처럼 순수하게 정적인 사이트를 만든다면 서버에서 html을 일괄 생성하고 이를 클라이언트에게 전달하는 것이 단순하고, 로딩 속도를 개선할 수 있다.

React는 정적인 사이트보다는 동적인 사이트에 필요하고 어울린다. 정적인 사이트에서도 React를 사용할 수 있지만 보일러 플레이트 코드를 구현하고, 서버 사이드 렌더링을 통한 SEO나 라우팅 등을 구현하는 것은 몸에 맞지 않는 큰 머리처럼 비효율적이다.

반면, 사이트의 규모가 커지고 동적인 요소가 많아지면 단순 JavaScript나 jQuery로 상태(state)를 모두 관리하는 것은 거의 불가능에 가까워 진다. 예를들어, Netflix는 수많은 영상을 가지고 있고, 각 영상별로 특정 사용자의 취향과 일치할 확률을 계산한다. 이를 바탕으로 사용자가 선호할 영상들을 우선적으로 리스트업(list-up) 해 보여준다. 즉, 사용자마다 전부 다른 ‘개인화된’ 페이지를 가지게 된다. A와 B가 취향이 다르다면 메인페이지에서, 카테고리별 페이지에서, 심지어 영화 검색시에도 보여지는 결과물이 각각 다르다. 이로 인한 복잡한 상태들을 jQuery로 전부 관리한다는 것은 불가능하지는 않지만 엄청나게 비효율적이다. 유지보수가 어렵고 버그를 야기한다. 반면 React를 사용하면 Redux 등의 상태관리 도구를 이용해 상태를 모아 관리할 수 있다. 또, Component에 data가 흘러들어가 개인화된 웹페이지를 생성하게 되는 방식으로 플로우가 이해하기 쉽고 직관적이다. 유지보수에도 용이하다. 따라서 React는 프로젝트가 복잡하고 동적일수록 빛을 발한다.

아쉽게도, 대부분의 웹은 계산기와 블로그의 어쩡쩡한 중간에 위치해 있을 것이다. 따라서 선택은 개발자 개개인의 몫이다. 완벽하게 정적인 웹도 완벽하게 동적인 앱도 존재하지 않으니 말이다. 다만, React는 웹 어플리케이션을 구축하는 접근방법을 새롭게 하고, 더 많은 생각할거리를 제공한다. React와 함께하는 웹개발은 더 역동적이고, 더 많은 즐거움을 준다(지극히 개인적인 감정이다).

마치며

React가 2018년에도 가장 핫한 프론트엔드 라이브러리/프레임워크에 등극했다. stateofjs.com 설문 결과에 따르면 64.8%가 React를 사용했고, 다시 사용할 것이라고 응답했다. Vue.js에서 같은 질문에 28.8%, Angular.js에서 23.9%가 같은 응답을 한 것으로 본다면 매우 강력한 호감이다. Angular의 경우 사용해봤지만 다시는 사용하지 않겠다는 응답이 33.8%였다.

출처: stateofjs.com

React는 단연컨데 가장 인기 있는 프론트엔드 라이브러리다. Vue가 가파르게 성장하고 있긴 하지만. Angular에 비해 러닝커브도 낮고, Vue에 비해 사용하는 곳도 많다. React와 함께하는 프론트엔드 개발은 편리하고 즐겁다. JSX 문법은 우아하고 직관적이며, Redux를 활용한 상태 관리는 예술에 가깝다.

React를 시작하면 React를 사랑하게 될 것이다.

출처