어제(9월 10일)자로 React 0.14 rc 버전이 발표되었다.
0.13에서 0.14로 마이너 버전이 판올림 되는데도 변화가 꽤 많이 생겼기에 이에 대해 요약해보고자 한다.
React DOM 분리
처음 React를 발표할 때만 해도 React는 어쨌든 웹 브라우저 환경을 기반으로 두고 있는 라이브러리였다. 하지만 현재에 와서는 react-native, react-art, react-canvas, react-three의 예에서 보듯 React에서 DOM과 상관없는 부분만 필요로 하는 사례가 늘어났다. 그래서 React 개발팀은 아예 React의 핵심 라이브러리만 react
패키지에 남기고 DOM에 해당하는 부분은 react-dom
이라는 패키지로 분리해냈다. 앞으로 React는 가상 DOM을 다루는 부분까지만 담당하고 실제 렌더링은 React DOM이 담당하게 되며 웹 브라우저 환경이 아닌 다른 환경에서는 다른 렌더러를 사용해야 한다.
예를 들어, 다음과 같은 컴포넌트가 있다고 가정해보자.
var React = require('react');
var MyComponent = React.createClass({
render: function() {
return <div>Hello World</div>;
}
});
이 컴포넌트를 웹 브라우저 환경의 DOM을 사용해 렌더링하려면 다음과 같이 react-dom
패키지를 사용해야 한다.
var ReactDOM = require('react-dom');
ReactDOM.render(<MyComponent />, targetNode);
만약 서버 사이드에서 렌더링하고 싶다면 다음과 같이 react-dom/server
패키지를 사용해 결과를 문자열로 저장한 후 사용한다.
var ReactDOMServer = require('react-dom/server');
var output = ReactDOMServer.renderToString(<MyComponent />);
이 때문에 웹 브라우저 환경에서는 react
와 react-dom
파일을 둘 다 불러와야 하는 번거로움이 생겼지만, 반대로 서버 사이드 환경에서는 굳이 DOM 에뮬레이션 라이브러리를 사용하지 않아도 돼서 더 편해진 면이 있다. 개인적으로는 서버 사이드 렌더링을 할 때 jsdom
같은 외부 라이브러리를 반드시 사용해야 한다는 점이 찝찝하기도 하고 불만이기도 했던 터라 이번 변화를 반기고 있다. 게다가 앞으로 더 다양한 방법으로 React가 사용될 것을 기대해봐도 좋을 만한 출발점이라 생각한다.
DOM 노드 참조
컴포넌트에 ref
를 추가하여 DOM 노드를 참조하던 방식이 달라졌다. 브라우저에 내장된 DOM 컴포넌트라면 기존에는 this.refs.giraffle.getDOMNode()
와 같이 참조하던 방식 대신 이제는 getDOMNode()
없이 바로 this.refs.giraffle
과 같이 DOM 노드를 참조하고 사용할 수 있다. 단, 커스텀 엘리먼트는 기존대로 동작하되 위에서 말했다시피 DOM 관련 기능이 별도 패키지로 분리되었기 때문에 this.refs.giraffle.getDOMNode()
대신 ReactDOM.findDOMNode(this.refs.giraffle)
을 사용해야 한다. 이 때 ReactDOM
은 바로 윗 절의 내용처럼 react-dom
패키지를 로드한 객체이다. 사실 DOM 노드 참조 방식이 바뀐 덕분에 getDOMNode()
를 호출해야 할 일이 상당히 줄어들었다. 만약 이미 작성된 코드가 너무 많아서 대량 수정이 필요하다면 React 개발팀에서 마련해 놓은 자동 코드 수정 스크립트를 사용해보는 것도 좋은 방법이다.
함수 컴포넌트
State가 필요하지 않은 단순한 컴포넌트라면 함수를 컴포넌트처럼 호출해서 사용할 수도 있다.
react-tools 폐지 예정
react-tools
패키지와 브라우저 환경의 JSXTransformer가 폐지 예정되었다. JSXTransformer는 브라우저 환경에서 JSX 문법을 자바스크립트 코드로 변환하는 역할이었는데, 이제는 Babel의 사용을 권장하고 있다. 그 외 몇 가지 변경 사항과 더불어 보건대 이번 버전부터 JSX 변환은 아예 Babel로 이관한 것처럼 보인다.
props
동결
props
객체가 동결된다. 따라서 이제는 명시적으로 수정할 수 없는 객체가 되었다. 코드 레벨에서는 ES5에서 추가된 Object.freeze()
를 사용해 props
객체를 동결시키는데, 이렇게 되면 이 객체에 새로운 프로퍼티를 추가할 수 없고, 기존에 있던 프로퍼티의 값도 변경할 수 없다. 이 때문에 부모 컴포넌트에서 자식 컴포넌트의 props
을 수정하려면 React.cloneElement
를 사용해 아예 자식 노드를 복제하면서 새 props
를 설정해주는 수밖에 없다. 같은 맥락에서 컴포넌트의 메소드인 setProps
, replaceProps
그리고 React.addons.cloneWithProps
는 폐지 예정 상태가 되었다. React.cloneElement
는 설령 className
이나 style
이라 하더라도 props
에 포함된 프로퍼티의 값을 병합하지 않고 설정 혹은 대체만 하므로 주의해야 한다.
기타
classSet
이 없어졌다. classnames라는 외부 라이브러리를 사용해야 한다. 공식 문서에서 추천했으므로 찝찝함은 조금 덜어도 될 듯.CSSTransitionGroup
에 타임아웃 설정이 가능해졌다. 오히려 잘 동작하지 않는 transition 이벤트를 리스닝하지 않고 타임아웃만 지원하기로 한 모양. 타임아웃은 props를 사용해transitionEnterTimeout={500}
처럼 설정할 수 있다.CSSTransitionGroup
에서 각 트랜지션 단계에 사용할 이름을 설정할 수 있다.- 지원하는 HTML 어트리뷰트와 SVG 어트리뷰트,
audio
/video
엘리먼트의 이벤트가 늘었다. SVG의image
엘리먼트도 지원한다.