React v16 무엇이 바뀌었나
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 새로운 타입
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
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
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 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).
Async Rendering
Ever wonder what "async rendering" means? Here's a demo of how to coordinate an async React tree with non-React work https://t.co/3snoahB3uV pic.twitter.com/egQ988gBjR
— Andrew Clark (@acdlite) 2017년 9월 18일
어떻게 구현되어있는지 코드를 찾아보고 있는데 아직 공개되진 않은 듯 하다. (아시는분 있으시면 개인적으로 연락해주길 바랍니다.) https://gist.github.com/acdlite/f31becd03e2f5feb9b4b22267a58bc1f thread에서 아직 논의중인 API이긴 한데 아마 곧 추가되지 않을까 생각한다.
Dependencies
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);
};
마치며
Reference
- React Official Guide v16
- Error Handling in React
- Portals
- What’s New With Server-Side Rendering in React 16
- Facebook Engineering Blog
- React Release Note
- 남다른 개선방법을 다시 보여준 페이스북의 React Fiber