본문 바로가기
Front-end Framework/React (Reactjs)

1. React?

by kellis 2020. 10. 19.

React는 페이스북에서 개발한 자바스크립트 라이브러리입니다. 이 글에서는 React의 개요에 대해 다루겠습니다.

 

React에 대한 내용을 이해하기 위해서는 다음과 같은 사전 지식이 필요합니다.

 

1. React 란?

 

React는 조합형 인터페이스를 제작하기 위한 오픈소스 라이브러리로서,  페이스북이 개발하고 관리하고 있습니다. 정식 명칭은 React이나 ReactJS라고도 합니다. 

 

"React는 UI를 구축하기 위한 선언적이고 효율적이며 유연한 자바스크립트 라이브러리"

"지속해서 데이터가 변화하는 대규모 어플리케이션을 구축하기 위해 React를 만들었습니다."

 

더보기

React는 프레임워크가 아닌 라이브러리입니다. 그럼 프레임워크와 라이브러리가 어떻게 다른지 아래에서 설명하도록 하겠습니다.

 

프레임워크 : 뼈대나 기반구조를 의미합니다. 어플리케이션의 틀과 구조를 결정하고, 개발자는 틀 내에서 개발합니다. 보통 하나의 프레임워크를 사용하며 여러 프레임워크를 사용할 경우 충돌이 일어날 수 있습니다.

라이브러리 : 단순 활용가능한 도구들의 집합을 말합니다. 필요한 곳에 넣어 사용하면 되고, 충돌이 일어날 가능성이 낮습니다.

프레임워크와 라이브러리의 차이점은 제어 흐름에 대한 주도성이 누구에게/어디에 있는가에 달려 있습니다. 즉, 애플리케이션의 플로우를 스스로 쥐고 있으며(이것을 제어의 역전이라고 합니다), 사용자는 그 안에서 필요한 코드를 짜넣는 것이 프레임워크이고, 반대로 사용자가 전체적인 흐름을 만들며 기능을 가져다 쓰는 것이 라이브러리입니다.

 

주요 특징

(1) 컴포넌트 기반

React에서는 모든 것이 컴포넌트입니다. React는 복잡하고 다량의 요소를 가지고 있는 UI를 작고 분리된 코드의 조각인 컴포넌트로 구성하는데, 여기서 컴포넌트란 속성(props)을 입력받아 브라우저에 어떻게 렌더링할 지 정의하는 React의 요소입니다.  말이 어렵지만,  일단 컴포넌트란 UI를 재사용 가능한 조각으로 나눈 것이라 이해하면 될 것입니다. 이렇게 컴포넌트 단위로 개발하게 되면 기능의 재사용성의 증가하여 애플리케이션의 유연성이 높아집니다. 

React 어플리케이션의 전체 구조는 위와 같이 컴포넌트의 트리 형태로 이루어집니다.

 

(2) 대규모 어플리케이션에 적합

템플릿에 기반한 다른 프레임워크 기술들은 상태를 간단하게 바꿀 수 있고, 빠르게 경량의 애플리케이션을 만들 수 있도록 도와줍니다. 반면에 React는 상태를 immutable로 관리하기 때문에 상대적으로 느려 보이거나 배우기 어렵다고 느낄 수 있지만, 애플리케이션의 규모가 커질수록 유리합니다. 템플릿은 런타임 에러가 발생하기 쉽고 테스트가 어려우며 재구조화하기 어려운 반면 React는 재사용성이 높고, 상태를 불변으로 관리하기 때문에 테스트와 투명도 측면에서 뛰어납니다.  

 

(3) UI만을 위한 라이브러리

React는 MVC 프레임워크에서 뷰 부분에만 관심이 있고, 이 뷰를 컴포넌트화하는데에 집중되어 있는 것이 콘셉트입니다.  즉 개발자가 DOM을 직접 다루지 않고 React가 데이터 상태에 따라 자동으로 UI를 관리하므로 개발자는 단순히 특정 상태에 대한 뷰의 변화만 구현하면 됩니다. 다른 여타 많은 프레임워크들이 MVC를 모두 다루겠다는 목표를 가진 것에 비해 React는 뷰에만 집중하고 있기 때문에 라우팅이나 데이터 모델링 등 많은 기능이 포함되어 있지 않으므로 완전 경량입니다. 

 

(4) 단방향 데이터 바인딩

부모 컴포넌트에서 하위 컴포넌트로 전달하는  단순한 데이터 흐름으로, 이해하기 쉽고 데이터 추적과 디버깅이 쉽습니다. 양방향 데이터 바인딩은 데이터의 변경을 프레임워크에서 감지하고 있다가 변경되는 시점에 DOM 객체에 렌더링 해주거나, 페이지 내에서 모델의 변경을 감지하여 자바스크립트 실행부에서 변경합니다. 이 방식은 코드의 사용면에서 코드량을 크게 줄여주는 장점이 있지만, 변화에 따라 DOM 객체 전체를 렌더링 해주거나 데이터를 바꾸는 등의 행위로 인해 성능이 감소되는 경우가 생깁니다. 하지만 단방향 데이터 바인딩은 실행부 자체 내에서 데이터의 변화를 감지하지 않으며 데이터에 변화가 오게 되면 특정 함수를 실행시킴으로써 DOM 객체를 갱신합니다. 따라서 데이터 변화에 따른 성능 저하 없이 DOM객체를 갱신해 줄 수 있습니다. 

 

(5) Virtual DOM

웹 브라우저는 DOM을 활용하여 객체에 자바스크립트와 css를 적용합니다. 그러나 DOM은 동적 UI에 최적화되어 있지 않습니다. 그래서 수많은 데이터를 로딩하고, 이 데이터를 표현하는 요소들이 몇 백, 몇 천개씩 존재하는 큰 규모의 웹 애플리케이션(트위터나 페이스북과 같은)의 경우 DOM에 직접적인 변화를 주다 보면 성능상의 이슈가 조금씩 발생하기 시작합니다.

브라우저는 HTML을 전달받으면 위와 같은 과정을 통해 페이지에  렌더링합니다. 한눈에 봐도 많은 과정을 거친다는 것을 알 수 있습니다. 그런데 브라우저단에서 DOM에 변화가 생긴다면 이 모든 workflow가 다시 실행되게 됩니다. 이는 매우 비효율적이며 그러한 이유로 virtual DOM을 사용하게 됩니다. 변화가 생겼을 때 실제 DOM에 접근하여 조작하는 것이 아닌 DOM 작업을 가상화하여 미리 처리한 다음, 최종적인 결과를 한꺼번에 DOM에 전달해 주는 것입니다.  최소한의 돔 조작을 통해 workflow가 다시 실행되지 않도록 처리하는 것입니다. 

 

참고. 그림에서의 용어는 webkit엔진에서 사용하는 용어들로 작동방식은 대부분 브라우저에서 비슷합니다. 약간의 차이가 있을 뿐입니다. 
DOM Tree 생성 - 브라우저는 HTML을 전달받으면 브라우저의 렌더 엔진이 이를 파싱하여 DOM 노드로 이루어진 트리를 만듭니다. 각 노드는 HTML 엘리먼트들과 연관이 있습니다. 
Render Tree 생성 - 외부 CSS 파일과 각 엘리먼트의 inline 스타일을 파싱합니다. 스타일 정보를 이용하여 DOM 트리에 따라 새로운 렌더 트리를 만듭니다. 렌더 트리를 만드는 과정에 각 요소들의 스타일이 계산되고, 이 계산되는 과정에 서 다른 요소들의 스타일 속성을 참조합니다. (attachment : 노드의 스타일을 처리하는 과정)
Layout - 렌더트리가 다 만들어지고 나면 레이아웃 과정을 통해, 각 노드들에게 스크린의 좌표가 주어지고, 정확히 어디에 나타나야 할지 위치가 주어집니다.
Painting - 렌더링된 요소들에 색을 입히는 작업입니다. 트리의 각 노드들을 거쳐가면서 paint() 메서드를 호출하고, 스크린에 원하는 정보가 나타나게 됩니다. 
 
virtual DOM의 동작방식에 대해 더 알고 싶으시다면  https://hashnode.com/post/the-one-thing-that-no-one-properly-explains-about-react-why-virtual-dom-cisczhfj41bmssp53mvfwmgrq 에서 자세한 내용을 볼 수 있습니다.
리액트를 사용하는 것이 항상 빠르고 좋은 퍼포먼스를 내는 것은 아닙니다. 적절한 곳에, 최적화 작업이 잘 이루어졌을 때 사용해야 하는 것입니다.
리액트를 사용하지 않아도 코드 최적화를 열심히 하면 dom 작업이 느려지는 문제를 개선할 수 있고 또 매우 간단한 작업(단순 라우팅 정도만 있는 정적 웹페이지)의 경우 오히려 리액트를 사용하지 않는 편이 더 나은 성능을 보이기도 합니다. 

 

(6) JSX

자바스크립트의 확장 문법으로 Javascript Xml의 약자입니다. UI 표현의 편의를 위해 xml형태의 구문을 자바스크립트 구문 사이에 사용할 수 있게 만들어준 문법입니다. jsx를 사용하면 기존에 어려웠던 중첩 요소 표현도 더 쉽게 할 수 있습니다. jsx 문법을 사용한 파일은 일반적으로 *.jsx 확장자로 저장하고 배포 전에 트랜스파일을 통해 js로 변환됩니다. 

var React = require('react');
 
var Hello = React.createClass({
  render: function() {
    return (
      <div className="container">Hello {this.props.name}</div>
    );
  }
});
 
React.render(<Hello name="React" />, document.getElementById("app"));

여기서 사용된 div, a등과 같은 html태그는 사실 html태그가 아닌 React의 컴포넌트입니다. 기본 html 태그를 React에서 미리 컴포넌트로 작성해 제공합니다. jsx로 작성되는 모든 요소는 React 컴포넌트입니다.

이 코드를 아래와 같이 jsx없이 React로만 작성할 수도 있습니다. 

var React = require('react');
 
var Hello = React.createClass({
  render: function() {
    return React.DOM.div({className: 'container'}, 'Hello ' + this.props.name);
  }
})
 
React.render(
  React.createFactory(Hello)({name: 'React'}), document.getElementById("app")
);

참고. 리액트에서는 jsx를 사용하는 것을 권고하고 있습니다.

 

더보기

ES6,7문법

ES6와 ES7이란 ECMAScript6, 7의 약어로써 자바스크립트 표준단체인 ECMA가 제정하는 자바스크립트 표준입니다. 즉, 자바스크립트 내에 자체 내장된 모듈입니다. 이는 복잡해진 웹 애플리케이션 개발에 적합한 스펙들을 지원합니다(class, inheritance, module, promise generator 등)

jsx의 transform에는 harmoney 옵션이 있습니다. 이 옵션을 켜면 es6, 7의 문법을 일부 사용할 수 있습니다. es6의 문법인 arrow function은 map, filter 등과 조합해 사용하면 정말 편리합니다. 

var items = this.props.items.map((item) => {
  return <div>{item.name}</div>;
});
jsx와 es6문법을 사용하려면 별도의 변환 과정이 필요하며(모든 브라우저가 Jsx와 ES6를 지원하는 것은 아님) 이를 위해서는 Babel(react-tools와 JSXTransformer는 Babel로 옮겨졌습니다. 이에 관련된 내용은 https://reactjs.org/blog/2015/06/12/deprecating-jstransform-and-react-tools.html에서 확인해 주십시오) 트랜스파일러(인터프리터)가 필요합니다. Babel은 최신 자바스크립트를 ES5버전에서도 돌아갈 수 있도록 변환해줍니다. Babel 인터프리터를 사용하려면 webpack과 같은 번들링 도구가 필요합니다. Babel, webpack을 사용하기 위해서는 관련된 npm 모듈들을 모두 설치해야 하고 몇몇 설정 파일들을 하나하나 작성해야 하는 번거로운 작업을 수행해야 하는데 리액트에서는 이와 같은 과정을 한 번에 처리해 주는 create react app라는 npm 모듈을 제공하고 있습니다. 
create-react-app 명령어 하나로 로컬 서버 실행부터 자동 번들링까지 지원하는 개발환경을 정말 쉽게 구성할 수 있습니다. 자세한 내용은 2. React 개발 설정에서 다루도록 하겠습니다.
React를 사용하는 것으로 알려진 회사들 : https://github.com/facebook/react/wiki/Sites-Using-React

2. React의 탄생 배경

 

React의 개발사인 페이스북은 자사 제품들에 PHP를 사용하기로 알려져 있습니다. 페이스북의 PHP사랑은 유명한데, PHP를 C++로 컴파일한 후 빌드하는 Hiphop for PHP라는 프로젝트를 진행하여(현재는 HHVM으로 대체) PHP 자체의 성능을 개선하기도 했고, PHP 엔진 자체를 수정한 HHVM(hack과 그 애플리케이션을 실행하는 힙합가상머신)을 개발하여 발표하기도 했습니다. 페이스북은 PHP라는 언어 자체에 대해 고민하고 Hack이라는 PHP의 문법 개정판과 같은 언어를 개발하기도 했는데, 2010년에 발표한 XHP 역시 PHP 언어의 문법 구조를 바꾸려는 노력의 하나였습니다. XHP는 HTML 출력이 많은 PHP 언어 특성에 맞춰 XML 또는 HTML을 더 빠르고 편하게 출력하는 데 목적이 있는데, 바로 아래와 같이 사용이 가능합니다. 

<?php
    if($_POST['name']){
?>
        <span> this is <?=$_POST['name']?> block. </span>
<?php
    } else {
?>
        <span>this is else block</span>
<?php
    }
?>

위 코드가 일반적인 php를 사용할 때의 코드라면 XHP를 사용하게 되면 아래와 같이 표현이 가능하게 됩니다.

<?php
    if($_POST['name']){
        echo <span>this is {$_POST['name']}</span>;
    }else{
        echo <span> this is else block</span>
    }
?>

echo 명령어를 통해 간단하게 HTML 출력이 가능합니다. 페이스북은 이 아이디어를 브라우저로 옮기고자 했고, 이것이 바로 React가 된 것입니다.

JSX라는 자바스크립트의 확장 문법을 통해 XHP와 유사한 기능을 React라는 이름으로써 제공하게 된 것이 React의 탄생 배경입니다. 

 

그렇다면 페이스북의 큰 그림은 무엇이었을까요? 페이스북이 React를 만들기 이전의 시장에는 이미 앵귤러, 백본, 녹아웃.js, 엠버 등 수많은 프런트엔드 프레임워크들이 존재했습니다. 그리고 이 프레임워크들은 데이터단을 담당하는 Model, 사용자 화면에서 보이게 되는 뷰, 사용자가 발생시킨 이벤트를 처리해주는 컨트롤러로 이루어진 MVC 패턴, 그리고 MVC에서 파생된 MVVM , MVW 등 패턴들로 이루어져 있습니다. 여기서 공통점은 모델입니다. 언급한 프레임워크들의 모델은 대부분 양방향 바인딩을 통해 모델에 있는 값이 변하면 뷰에서도 이를 변화시켜줍니다. 여기서 핵심은 변화시킨다는 점입니다. 변화라는 것은 상당히 복잡한 작업이라, 특정 이벤트가 발생했을 때 모델에 변화를 일으키고, 변화를 일으킴에 따라 어떤 DOM을 가져와서 어떤 방식으로 뷰를 업데이트해줄지 로직을 정해주어야 합니다. 페이스북은 React를 만들기 전에 이런 발상을 했습니다. 

"Mutation을 하지 말자. 그 대신 데이터가 바뀌면 View를 날려버리고 새로 만들면 되지 않을까?"

그러면 변화를 만드는 복잡한 작업 없이 간단하게 화면이 변경될 것입니다. 하지만, 브라우저가 DOM 기반으로 작동하는 이 페이지를 그때그때 새로운 뷰를 만들어내라고 한다면 성능적인 문제가 발생할 것입니다. 그래서 사용되는 것이 위에서 설명했던 virtual DOM입니다.

React와 virtual DOM 사이의 이해를 도와주는 유명한 영상이 있어 링크를 기재합니다.
https://www.youtube.com/watch?v=muc2ZF0QIO4\

 


3. Pros an Cons

 

React의 주요 특징들은 곧 React의 장점이자 단점이라고 할 수 있습니다. 요약하자면 아래와 같습니다.

 

[Pros]

  • 큰 개발 생태계 : 많은 레퍼런스, 툴, 확장 라이브러리들을 가지고 있음을 의미합니다. 또한 페이스북에서 유지 관리하므로 지속적인 버전업을 신뢰할 수 있습니다. 

  • 배우기 쉽다 : React는 구문이 단순하기 때문에 배우기 쉽습니다.  개발자들은 단지  HTML 작성 스킬만 알고 있으면 됩니다. 
  • Virtual DOM으로 빠른 렌더링 : 웹 애플리케이션의 다양한 구성요소들을 파싱 하는 동안, HTML, XHTML, XML 등의 형식의 문서를 웹 브라우저들이 더 잘 받아들일 수 있는 트리 형태로 정렬해주는 가상 DOM
  • ES6/7과 결합 : 고부하의 작업을 쉽게 처리할 수 있습니다.
  • 하위 데이터 바인딩(단방향 데이터 바인딩) : 하위 요소가 상위 부모 데이터에게 영향을 미치지 않습니다.
  • 완전 경량 : 사용자 측에서 수행되는 데이터는 동시에 서버 측에서도 쉽게 표현될 수 있습니다. 데이터 모델링, 라이팅 등 기능이 없으므로 상대적으로 가볍습니다.
  • 버전 간 마이그레이션이 일반적으로 매우 쉽다 : 페이스북이 프로세스 대부분을 자동화하는 "codemodes"를 제공하여 매우 쉽습니다.
  • 다른 프레임워크나 라이브러리와 혼용이 쉽다 : 이미 개발이 완료된 서비스에도 적용이 쉽다.
  • 반응형 렌더링 : 개발자가 컴포넌트의 모양과 동작을 선언식으로 정의하면 리액트가 데이터 변경을 감지하고 인터페이스를 다시 렌더링 합니다.
  • 서버 사이드 렌더링 & 클라이언트 사이드 렌더링 : 서버 사이드 렌더링과 클라이언트 사이드 렌더링 모두 지원합니다. 
서버 사이드 렌더링이 필요한 이유
1. 초기 구동 딜레이 문제
클라이언트 렌더링만 할 경우, 페이지가 로드된 이후에 ajax와 같은 처리를 통해 데이터를 가져옵니다. 이렇게 되면 처음에는 아무 데이터가 나타나지 않고, 자바스크립트 처리가 끝난 후에 원하는 UI가 나타나게 됩니다. 이는 초기 구동 딜레이를 만들게 되고, 초기 렌더링을 서버 사이드 렌더링 하게 하면 해결할 수 있습니다. 서버 측에서 html을 미리 생성하고 문자열 형태로 브라우저에 띄워주면, 그 이후부터는 클라이언트 사이드 렌더링을 하게 됩니다.

2. SEO(Search Engine Optimization)
클라이언트 렌더링만 하게 되면, 검색엔진봇이 사이트를 수집할 때 실질적으로 얻는 정보는 사이트의 데이터가 아닌 빈 요소가 되게 됩니다. (단, 구글 검색엔진의 경우 봇 자체에서 사이트 내의 자바스크립트를 실행하게 하기 때문에 문제 되지 않습니다.) 서버 사이드 렌더링을 지원하지 않는 프론트 프레임워크의 경우 3rd Party 라이브러리를 통해 이 기능을 구현할 수 있으나, 서버 자원을 많이 사용하게 된다는 점을 감안하여야 합니다.

[cons]

  • JSX와 ES6에 의존하는 편
  • View only : 보이는 부분만 관여. 데이터 모델링, 라우팅, ajax 등의 기능은 지원하지 않음. 별도의 라이브러리를 사용하여 구현해야 한다. 
  • IE8 이하 지원하지 않음 : 아예 불가능한 것은 아님. 리액트 version 14 이하를 사용하고 이를 호환시켜주는 폴리필을 사용한다면 지원하게 만들 수 있다. 
폴리필(polyfill)?
HTML5 마크업뿐만 아니라 HTML5 API는 웹 표준을 향해 가고 있지만, 실제로 모든 브라우저에서 이를 지원하고 있지는 못합니다. 최신 브라우저라고 하더라도, 브라우저 버전 혹은 브라우저 벤더에 따라 지원하는 것이 다르고 이로 인해 브라우저 파편화(특정한 기능이 어떤 브라우저에서는 되고, 어떤 브라우저에서는 안 되는 문제)가 발생합니다. 폴리필은 이런 브라우저 파편화를 해소하기 위해 나타난 것으로, 비호환 엔진에 존재하지 않는 코드의 기능을 지원하기 위해 삽입하는 코드의 조각입니다. 예를 들어 폴리필을 사용하면 ES6를 ES5로 변환하여 브라우저에서 사용할 수 있도록 만들어줍니다.

Conclusions

 

이 글에서 React의 역사부터 특징까지 살펴보았습니다.  다음 글부터는 특징들에 대해 조금 더 들여다 보고, 실습을 통해 실제 익혀보는 작업을 진행하도록 하겠습니다. 

React의 라이선스 문제
2017년 7월 아파치의 프로젝트에서 "BSD(Berkeley Software Distribution. 자유 소프트웨어 저작권의 한 가지) + Parents 라이센스"(사용자의 지적재산권을 침해하더라도 페이스북을 고소할 수 없다는 조항이 포함되어 있다)를 사용하는 리액트의 사용이 금지된 적이 있었습니다. 아파치의 리액트 사용 금지 결정에도 페이스북이 리액트의 라이선스 정책을 변경하지 않자, 개발자들의 반발이 일어났고 리액트 사용이 주춤하는 시기가 되었는데요. 결국 2017년 9월 페이스북이 리액트의 라이선스를 MIT 라이선스로 변경하며 일단락되었습니다. 이에 관련된 내용은 https://wptavern.com/react-users-petition-facebook-to-re-license-react-js-after-apache-software-foundation-bans-bsdpatents-license-in-dependencies 에서 확인하실 수 있습니다.

 

 

[references]

 

react docs

 

Getting Started – React

A JavaScript library for building user interfaces

reactjs.org

react와 함께 사용하는 툴들

react 다운로드 그래프

 

Github Stars !== Usage: React is still blowing Vue and Angular Away

Last week there was a fairly momentous occurance in the JavaScript framework world: Vue.js passed React.js in the number of people who have 'starred' it on Github.

zendev.com

why virtual dom

 

JSTransform과 react-tools의 Babel Migrating

 

Deprecating JSTransform and react-tools – React Blog

Today we’re announcing the deprecation of react-tools and JSTransform. As many people have noticed already, React and React Native have both switched their respective build systems to make use of Babel. This replaced JSTransform, the source transformatio

reactjs.org

react and virtual DOM

sites using react

 

facebook/react

A declarative, efficient, and flexible JavaScript library for building user interfaces. - facebook/react

github.com

how browser work

 

How Browsers Work: Behind the scenes of modern web browsers - HTML5 Rocks

In this comprehensive primer, you will learn what happens in the browser between when you type google.com in the address bar until you see the Google page on the browser screen.

www.html5rocks.com

ECMAScript 6

 

lukehoban/es6features

Overview of ECMAScript 6 features. Contribute to lukehoban/es6features development by creating an account on GitHub.

github.com

ES6 compatibility table

 

ECMAScript 6 compatibility table

Sort by Engine types Features Flagged features Show obsolete platforms Show unstable platforms V8 SpiderMonkey JavaScriptCore Chakra Carakan KJS Other ⬤ Minor difference (1 point) ⬤ Small feature (2 points) ⬤ Medium feature (4 points) ⬤ La

kangax.github.io

 

'Front-end Framework > React (Reactjs)' 카테고리의 다른 글

6. React의 이벤트 처리  (0) 2020.10.19
5. 컴포넌트 라이프사이클 이벤트  (0) 2020.10.19
4. 컴포넌트  (0) 2020.10.19
3. 리액트의 문법 (+JSX)  (0) 2020.10.19
2. React 개발 설정  (0) 2020.10.19

댓글