JavaScript

React v16 무엇이 바뀌었나

La.place 2017. 10. 8. 13:46

 React의 새로운 버전이 Fiber란 코드 네임으로 개발 된 지 꽤 시간이 지났다. 대략 한달 전 v16의 RC버전이 릴리즈 된 후 이제 정식버전이 출시되었다. 최근 저작권 이슈를 겪으면서 한번 위기를 맞이 했던 React. 과연 v16에서는 어떤것이 바뀌었을까. 하나씩 알아보도록 하자. 

 먼저 React v16(이하 v16)을 만들게 된 이유는 무엇일까? 가장 먼저 생각나는건 Virtual DOM의 성능이다. 초창기 V-DOM을 도입한 프레임워크였던 React는 최근에 V-DOM을 사용하는 프레임워크들(예를들면 vue)에 대해 벤치마크 성능이 떨어진다. 이에 문제를 느꼈던 페이스북 개발자들은 React의 Core 알고리즘을 다시 짜야 할 필요성을 느꼈을 것이다. 이렇게 핵심 코드가 다시 만들어진게 React Fiber인데 아래 영상은 Redux를 만든 Dan Abramov가 올린 홍보 동영상이다.

 위 동영상에서 React Fiber는 복잡한 DOM조작에 대해 Virtual Stack Frame(또 뭔가 Virtual이 추가되었다!)을 이용해서 해결했다고 한다. VSF는 "더 중요한 일을 먼저 실행하고 덜 중요한 일은 나중에 실행한다" 라는 개념인 것 같은데 자세한 건 다음 아티클을 참고하면 도움이 될 것이다. 남다른 개선방법을 다시 보여준 페이스북의 React Fiber.

 이처럼 페이스북 개발자들은 v16에서 render성능 개선에 초점을 맞춘것 같다. 실제 Release Node를 보면 render 함수 개선에 많은 공을 들였다는 것을 찾아볼 수 있다. 또 rendering logic 개선 말고도 유용한 부가기능이 많이 추가되었는데 하나 하나 어떤 점이 바뀌었는지 디테일하게 알아가 보도록 하자.

render 새로운 타입

 이제 Component의 render Method에 Array를 사용할 수 있게 되었다. 따라서 리스트를 만들 때 <div>태그를 사용할 필요가 없어 졌다. 사실 이 <div>태그를 사용해서 불필요한 depth를 추가해야하는 번거로움이 있었는데, 이 부분을 개선해주니 사용하는데 한층 더 편해질 것이란 생각이 든다.
render() {
// No need to wrap list items in an extra element!
return [
// Don't forget the keys :)
<li key="A">First item</li>,
<li key="B">Second item</li>,
<li key="C">Third item</li>,
];
}

 물론 String도 사용할 수 있다.

render() {
return 'Look ma, no spans!';
}

Error Handling

 과거 React에서는 특별한 예외처리 기법을 제공하지 않았다. 따라서 개발자는 window.onerror나 try ~ catch문 등을 사용해서 예외처리를 하곤 했는데 v16에서는 새로운 Handling Component를 추가하였다. 개발자는 ComponentDidCatch Method를 사용해서 로그를 추적하거나 Fallback UI를 보여줄 수 있다. 아래 공식 가이드에서 제공한 코드를 보도록 하자.
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}

componentDidCatch(error, info) {
// Display fallback UI
this.setState({ hasError: true });
// You can also log the error to an error reporting service
logErrorToMyService(error, info);
}

render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}

 다음 과 같이 클래스를 생성 한 후 에러를 처리할 컴포넌트를 한번 감싸주기만 하면 된다.

<ErrorBoundary>
<MyWidget />
</ErrorBoundary>

 ErrorBoundray아래에 있는 모든 컴포넌트 트리에 대해 미리 정의한 에러처리를 실행하게 된다. 에러처리를 Component로 만들어서 직관적이고 유연성 있는 구조로 개발 할 수 있도록 도와준다. 관심이 있는 사람은 Live DEMO를 참고하도록 하자.

Portals

 Portal은 ReactDOM에 새로 추가된 Method인데, parent component의 DOM 구조 밖에 존재하는 DOM Node를 render할 때 자식으로 추가 할 수 있도록 도와준다.
render() {
// React does *not* create a new div. It renders the children into `domNode`.
// `domNode` is any valid DOM node, regardless of its location in the DOM.
return ReactDOM.createPortal(
this.props.children,
domNode,
);
}

 이걸 어디다 써야할까. 보통 개발 하다보면 부모에서 독립적으로 존재하는 Component가 몇가지 존재한다. 예를 들면 Modal, Hover, Dialog, Tooltip등이 있을 수 있다. 이러한 Component는 Portal을 이용하면 특정 Component의 자식으로 넣어 줄 수가 있다. 또 Portal을 사용하면 하위 컴포넌트에서 Event Bubbling을 Catch할 수 있는데, 이를 이용하면 Common Modal을 만들고 필요에 따라 하위 Component를 바꿔넣는 유연한 구조를 만들 수가 있다. vue 경험자라면 Slot같이 구현이 가능하다 생각하면 이해가 쉬울 것이다. LIVE DEMO.

Server-Side Rendering

 React Fiber에서도 SSR의 큰 변화가 일어났다. 바로 Streaming을 지원한다는 것이다! vue SSR에서는 지원하던 기능이 React에서는 없어서 아쉬었는데, 이번에 추가되어서 초기 화면을 빠르게 보여줘야 하는 어플리케이션의 경우 보다 빠른 사용자 경험을 제공할 것이라 생각한다. 또 기존 v15보다 서버 렌더링 속도가 3배는 빠르다고 하니 기대해도 좋을 것 같다.

작아진 용량

 기존 React의 단점중 하나였던 큰 Library Size. 이번 v16버전이 나오면서 상당부분 개선되었다. 총 용량이 기존 대비 32% 줄었다고 한다. 세세한 내용은 다음과 같다.

  • react is 5.3 kb (2.2 kb gzipped), down from 20.7 kb (6.9 kb gzipped). 
  • react-dom is 103.7 kb (32.6 kb gzipped), down from 141 kb (42.9 kb gzipped). 
  • react + react-dom is 109 kb (34.8 kb gzipped), down from 161.7 kb (49.8 kb gzipped).
React로 Mobile Application 개발할 때 용량이 고민거리가 되었는데, 이젠 그 부담을 덜어 줄 수 있을 것 같다.

Async Rendering

 아래 동영상은 React Core 개발자인 Andrew Clark이 공개한 동영상이다. React App을 Rendering할 때 오른쪽 위 사각형이 멈추는걸 볼 수 있다. 그러나 Async를 Check한 후 Rendering하면 끊김없이 그려지는 모습을 볼 수 있다. 하지만 파란색 영역이 나타나고 초록색 영역이 나타나는 문제점이 있다. 다음으로 Coordinate commit phase를 Check하면 이번엔 Aync 하지만 파란색 영역과 초록생 영역이 동시에 나타난다. LIVE DEMO

어떻게 구현되어있는지 코드를 찾아보고 있는데 아직 공개되진 않은 듯 하다. (아시는분 있으시면 개인적으로 연락해주길 바랍니다.) https://gist.github.com/acdlite/f31becd03e2f5feb9b4b22267a58bc1f thread에서 아직 논의중인 API이긴 한데 아마 곧 추가되지 않을까 생각한다.

Dependencies

 v16 버전부터는 Map과 Set 그리고 requestAnimationFrame에 의존성을 갖는다. 따라서 core-js의 support가 필요하다.
import 'core-js/es6/map';
import 'core-js/es6/set';

import React from 'react';
import ReactDOM from 'react-dom';

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

global.requestAnimationFrame = function(callback) {
setTimeout(callback, 0);
};

마치며

 React v16에 추가된 Feature들을 중요한 정보 위주로 정리해 보았다. 이것 말고도 자잘하게 바뀌점이 많으니 공식 페이스북 문서를 참고하면 도움이 될 것이다. 이번에 v16이 나오면서 잠시 쉬었던 React를 이용한 개발을 다시 시작해볼까 한다. 개인적으로 좋아하는 아키텍쳐와 철학을 가진 Library다 보니 평소 보다 관심이 많이 갔지만, 여러 이슈들 때문에 공부해도 써먹을 수 있을까 하는 생각이 많이 들긴 했다. 하지만 라이센스도 MIT로 바뀌었고 성능향상과 기능도 많이 추가된 듯 하니 새로운 React의 세계를 경험해 보자.

Reference


'JavaScript' 카테고리의 다른 글

Javascript Iterator  (1) 2018.10.12
알아두면 쓸만한 Chrome Console 기능  (0) 2017.12.31
Currying in Javascript  (0) 2017.07.23
Functional Programming in Javascript  (8) 2017.07.22
TDD & Mocha - Javascript Test Framework  (0) 2017.05.14