React

namezin·2020년 4월 23일
0

Front-End

목록 보기
1/21
post-thumbnail

We built React to solve one problem: building large applications with data that changes over time.
번역: 우리는 지속해서 데이터가 변화하는 대규모 애플리케이션을 구축하기 위해 React를 만들었습니다

React 란

  • React는 페이스북에서 제공하는 자바스크립트 UI 프론트엔드 라이브러리
  • Angular가 프레임워크인 데 반해 React는 라이브러리
  • 컴포넌트 기반

왜 만들었을까?

이전에도 많은 프론트엔드 프레임워크/라이브러리가 존재했지만 대부분 작동방식은 양방향 바인딩을 통하여 모델에 있는 값이 변하면 뷰에서도 이를 변화하는 MVC패턴을 사용했다. 여기서 핵심적인 부분은 변화시켜준다라는 것이다. 일단 첫 화면을 보여주고, 변화에 따라 필요한곳을 바꿔주는 것이다. 변화는 어플리케이션이 방대해질수록 매우 복잡한 작업이 되었다. 페이스북 고질적인 문제였던 읽었던 페이지에도 숫자표시가 줄어들지 않은 이 부분이 MVC패턴에 대표되는 문제로 야기됐었다.

규모가 큰 어플리케이션에서 변화(Mutation)는 상당히 복잡한 작업이다. 특정 이벤트가 발생하면 모델에 변화를 일으키고 그 변화로 인해 어떤 DOM 을 가져와서 어떠한 방식으로 뷰를 업데이트 해줄 지 로직을 정해야 한다. 페이스북에서는 이 문제를 해결하기 위해 다음과 같은 개념으로 출발한다.

데이터가 바뀌면 그냥 뷰를 날려버리고 새로 만들어버리면 어떨까?

그러나, DOM 기반으로 작동하는 페이지는 매번 새로 뷰를 만들어버리라고 하면 성능적으로 엄청난 문제가 발생할 것이다.

여기서 나온 중요한 개념이 Virtual DOM 이다.

막연하게 생각했을 땐 느릴거 같긴한데 왜 성능적으로 엄청난 문제가 되는거지?

browser and DOM

browser에서 DOM이 어떤방식으로 나타나는지 확인해보면 알 수 있지 않을까?

  1. DOM Tree 생성 / Style Rules 생성
    browser가 HTML 을 전달받으면,
    render 엔진이 이를 파싱하고
    DOM 노드(Node) 로 이뤄진 트리를 생성(노드(Node) = HTML element)
  2. Attachment
    노드의 스타일을 처리하는 과정
    DOM 트리의 모든 노드들은 ‘attach’ 라는 메소드가 있어서 스타일 정보를 계산해서 객체형태로 반환
    동기(synchronous) 작업
    DOM 트리에 새로운 노드가 추가되면 그 노드의 attach 메소드가 실행
    렌더 트리를 만드는 과정에서 요소들의 스타일이 계산
    계산되는 과정에서 다른 요소들의 스타일 속성들을 참조하기도 함
  3. Render Tree 생성
    DOM Tree <- (attachment) -> Render Tree
    Style Rules를 사용하여 DOM Tree에 따라 새로운 Tree(Render Tree)를 생성
  4. Layout (reflow)
    각 노드들은 스크린의 좌표가 주어지고, 정확히 어디에 나타나야 할 지 위치가 주어진다.
  5. Painting
    렌더링 된 요소들에 색을 입히는 과정
    트리의 각 노드들을 거쳐가면서 'paint' 메소드를 호출
    그리고 스크린에 원하는 정보가 나타남

DOM에 변화가 생기면, Render Tree를 재생성하고 (그러면 모든 요소들의 스타일이 다시 계산됨) Layout, Painting을 하는 과정이 다시 반복됨

복잡한 SPA(싱글 페이지 어플리케이션) 에서는 DOM 조작이 많이 발생한다.
그 뜻은 그 변화를 적용하기 위해 브라우저가 많이 연산을 해야한단 소리고, 전체적인 프로세스를 비효율적으로 만든다.

React 특징

Virtual DOM

DOM 조작의 실제 문제는 각 조작이 레이아웃 변화, 트리 변화와 렌더링을 일으킨다는 것.
예를 들어 여러분이 30개의 노드를 하나 하나 수정하면, 그 뜻은 30번의 (잠재적인) 레이아웃 재계산과 30번의 (잠재적인) 리렌더링을 하게 된다.

Only One Rendering

Virtual DOM 은 DOM 차원에서의 더블 버퍼링이라고 보면 된다.
변화가 일어나면 그걸 Virtual DOM 트리에 적용한다. Virtual DOM 트리는 렌더링도 되지 않기때문에 연산 비용 적다. 연산이 끝나고나면 그 최종적인 변화를 실제 DOM 에 적용한다.
모든 변화를 하나로 묶어서 딱 한번만 적용
하나로 묶어서 적용시키는것이, 연산의 횟수를 줄이는 것이다.

단지 이 이유에서만 Virtual DOM 을 사용하는 것은 아니다.

DOM Fragment Auto management

사실, 위 과정은 Virtual DOM 이 없이도 있다. 변화가 있을 때, 그 변화를 묶어서 DOM fragment 에 적용한 다음에 기존 DOM 에 던져주면 되는 것이다.

그러면, Virtual DOM 이 해결 하려고 하는건 무엇이냐?
DOM fragment를 관리하는 과정을 수동으로 하나하나 작업 할 필요 없이, 자동화하고 추상화하는 것이다.
그 뿐만 아니라, 만약에 이 작업을 직접 한다면, 기존 값 중 어떤게 바뀌었고 어떤게 바뀌지 않았는지 계속 파악하고 있어야하는데 (그렇지 않으면 수정 할 필요가 없는 DOM 트리도 업데이트를 하게 될 수도 있다), 이것도 Virtual DOM이 어떤게 바뀌었는지 ,어떤게 바뀌지 않았는지 알아내어 이걸 자동으로 해준다.

Simple DOM management

마지막으로, DOM 관리를 Virtual DOM 이 하도록 함으로써, 컴포넌트가 DOM 조작 요청을 할 때 다른 컴포넌트들과 상호작용을 하지 않아도 되고, 특정 DOM 을 조작할 것 이라던지, 이미 조작했다던지에 대한 정보를 공유 할 필요가 없다.
즉, 각 변화들의 동기화 작업을 거치지 않으면서도 모든 작업을 하나로 묶어줄 수 있다.

Flow

데이터가 바뀌어서 변화가 일어나면,

  1. 자바스크립트로 이뤄진 가상 DOM 에 한번 렌더링을 하고
  2. 기존의 DOM 과 비교를 한 다음
  3. 정말 변화가 필요한 곳에만 업데이트를 해주는 것

거짓: React가 DOM 보다 빠르다.
사실: 유지보수 가능한 어플리케이션을 만드는것을 도와주고 대부분의 경우에 ‘충분히 빠르다’
-Redux 창시자이자 React 개발팀원인 Dan Abramov 의 트윗-

Flux

Flux 패턴의 핵심은 어플리케이션 데이터가 단방향으로 흐른다는 것이다.

Facebook에서 클라이언트-사이드 웹 어플리케이션을 만들기 위해 사용하는 어플리케이션 아키텍쳐다. 단방향 데이터 흐름을 활용해 뷰 컴포넌트를 구성하는 React를 보완하는 역할을 한다.

구성요소

Action
새로운 데이터를 포함하고 있는 간단한 객체로 type 프로퍼티로 구분 가능
  • 요청하는 데이터 묶음을 Action이라 하고, 전달할 액션 객체는 Action 생성자라는 함수를 통해 만들어진다.
  • View에서 Action 생성자를 통해 전달할 메세지을 생성하고, Dispatcher에 전달하여 Store에 저장되어 있는 상태를 변경한다.
Dispatcher
모든 데이터를 관리하는 Control 역할이며 Action 이 시작될 때 어떻게 Store가 업데이트되어야 하는지 결정(Callback 모음 요소)
  • Flux 애플리케이션의 모든 데이터 흐름을 관리하는 허브 역할
  • Action이 발생하면 Dispatcher로 메세지나 액션 객체가 전달되고 Dispatcher에서는 등록된 콜백함수를 통해 이 메세지를 Store에 전달
  • 다른 구성요소와 달리 Dispatcher는 전체 애플리케이션에서 한 개의 인스턴스만 사용
Store
APP의 모든 데이터를 저장
  • 애플리케이션 상태를 저장
  • MVC의 Model과 유사하지만 애플리케이션의 특정 도메인에 해당하는 Status를 다룬다
  • Status를 다루기 때문에 무엇이든 저장할 수 있고 단순한 Object로 구성
  • 마치 정부관료와 같다고 표현하기도 하는데 모든 Status변경은 Store에 의해서 결정되어야만 하며,
  • 상태변경을 위한 요청을 Store에 직접 보낼 수 없다.
  • 즉 무조건 Action 생성자를 통해 Dispatcher를 통해 Action을 보내야먄 수정이 가능
View(+ Contoroller view)
Store가 변경된 경우같이 변경, 사용자의 상호작용에 응답하기 위해 새로운 action을 만들어 시스템에 전파
  • 상태를 가져와서 보여주고 입력받을 화면을 보여줄 역할
  • Controller view는 Store와 View 사이의 중간관리자같은 역할을 하며, 상태가 변경되었을 때 Store가 그 사실을 Controller view에게 알려주면 자신 아래에 있는 모든 View에게 새로운 상태를 넘겨줌(cf, Flux에서는 정보를 넘겨주려면 Action 생성자를 Disapatcher에 전달해야함)

이러한 구조는 함수형 반응 프로그래밍(functional reactive programming) 이나 더 세부적으로 데이터-흐름 프로그래밍(data-flow programming) 또는 흐름 기반 프로그래밍(Flow-based programming) 을 연상하게 한다는 사실을 쉽게 떠올리게 한다.

어플리케이션의 상태는 store에 의해 어플리케이션의 다른 부분들과 결합도를 극히 낮춘 상태로 유지될 수 있다. store의 사이에서 의존성이 생긴다고 해도 dispachter에 의해 엄격한 위계가 유지되어 동기적으로 갱신되는 방식으로 관리된다.

동작

준비단계(the Setup)
먼저 애플리케이션이 초기화할 때 딱 한번 준비과정을 가진다.
  1. Store는 Dispatcher에 액션이 들어오면 알려달라고 말해둔다.
  2. Controller view는 Store에게 최신 상태를 묻는다.
  3. Store가 Controller view에게 상태를 주면 렌더링하기 위해 모든 자식 View에게 상태를 넘겨준다.
  4. Controller view는 Store에게 상태가 바뀔 때 알려달라고 다시 부탁한다.(subscribe)
데이터 흐름(the data flow)
준비과정이 끝나면 애플리케이션은 유저 입력을 위한 준비가 완료된다.
  1. View는 Action 생성자에게 Action을 준비하라고 함
  2. Action 생성자는 Action을 포멧에 맞게 만들어서 Dispatcher에 전송
  3. Dispatcher는 들어온 Action의 순서 따라 알맞은 Store로 보냅니다. 각 Store는 모든 Action을 받게 되지만 필요한 Action만을 골라서 상태를 필요하게 맞게 변경
  4. 상태 변경이 완료되면 Store는 자신을 구독(subscribe)하고 있는 Controller view에게 그 사실을 알림
  5. 연락 받은 Controller view들은 Store에게 변경된 상태를 요청
  6. Store가 새로운 상태를 넘겨주면, Controller view는 자신 아래의 모든 View에게 새로운 상태에 맞게 랜더링하라고 알림

참고: 그런데 Flux가 MVC중 하나라는데?

"Flux는 새로운 것이 아닌 MVC의 새로운 이름이다"
"MVC를 제대로 알지 못했거나 이벤트 기반으로 조금 변형 형태이다."
-Reddit 글 중에서-

JSX

JavaScript XML
HTML 마크업을 개발하듯이 JavaScript 내에서 사용할 수 있게 만들어진 JavaScript확장언어

과거 페이스북이 만들었던 PHP의 개량판 XHP에 그 만들어진 배경이 있음

React는 별도의 파일에 HTML마크업과 JavaScript로직을 분리하는 대신, 둘 다 포함하는 “컴포넌트(Component)”라고 부르는 느슨하게 연결된 유닛으로 관심사를 분리(SoC)한다.

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('root')
);

특징

  • JSX는 템플릿 언어처럼 보일 수 있겠지만 JavaScript의 모든 기능을 제공
  • React.js 는 일반 JavaScript 문법이 아닌 JSX 문법을 사용하여 UI를 템플릿화 한다.
  • babel을 통해 JavaScript로 변환된다.

장점

  • JSX는 컴파일링 되면서 최적화 되므로, 빠르다
  • Type-safe : 어떠한 연산도 정의되지 않은 결과를 내놓지 않는것, 즉 예측 불가능한 결과를 나타내지 않는 것 그래서 컴파일링 과정에서 에러를 감지 할 수 있다.
  • HTML에 익숙하다면, JSX를 사용하여 더 쉽고 빠르게 템플릿을 작성 할 수 있다.

And?

  • SPA(Single Page Application) : 단 하나의 html 이후 모든 페이지는 router를 이용해 js로 render
  • Hook : Functional Component에서 상태들을 변화, 사용할 수 있는 기능
  • ES6
  • ...

Reference

https://ko.reactjs.org/docs
https://velopert.com/3612
https://blog.gaerae.com/2016/04/hello-react.html
https://velopert.com/3236
https://lemontia.tistory.com/637
https://bestalign.github.io/2015/10/06/cartoon-guide-to-flux/

profile
개발관심자

0개의 댓글