React와 함께 ES6 & ES* 사용하기

Babel은 React의 일부가 아닙니다. 사실 Babel의 목적은 심지어 JSX 변환기 같은 것이 아니었습니다. Babel은 무엇보다 JavaScript 컴파일러입니다. Babel은 ES* 코드를 가지고 ES* 코드를 지원하지 않는 브라우저에서도 돌릴 수 있게끔 변환해줍니다. 현재를 기준으로, Babel은 주로 ES6와 ES7 코드를 ES5 코드로 변환합니다. 이런 ECMAScript 변환을 할 때, JSX 표현을 React.createElement() 호출로 변환하는 것은 간단합니다. 이것들이 우리가 지난 섹션에서 살펴본 것들입니다.

그래서 Babel이 JSX를 변환하는 메카니즘이라는 것을 고려한다면, Babel은 ES*의 이후 버전에서도 작동하는 코드를 적게끔 도와주는 도구라고 할 수 있습니다.

아래의 HTML 페이지에서는 익숙한 HelloMessage 컴포넌트가 ES6 클래스장점을 이용하도록 다시 작성되었습니다. Babel은 JSX 문법을 변환할 뿐만 아니라, ES6 클래스 문법을 ES5 문법으로도 변환해 ES5 브라우저 엔진이 해석할 수 있도록 해줍니다.

<!DOCTYPE html>
<html>
    <head>
        <script src="https://fb.me/react-15.2.0.js"></script>
        <script src="https://fb.me/react-dom-15.2.0.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
    </head>
<body>
    <div id="app"></div>
    <script type="text/babel">

        class HelloMessage extends React.Component { //React.Component가 사용되었다는 점 확인
            render(){
                return <div>Hello {this.props.name}</div>;
            }
        };

        ReactDOM.render(<HelloMessage name="John" />, document.getElementById('app'));

        /*** 이전 코드 ***/
        /* var HelloMessage = React.createClass({
         *    render: function() {
         *        return <div>Hello {this.props.name}</div>;
         *    }
         * });
         *
         * ReactDOM.render(<HelloMessage name="John" />, document.getElementById('app'));
         */
    </script>
</body>
</html>

위의 HTML 문서에서 Babel은 이 부분을 가지고:

class HelloMessage extends React.Component {
    render(){
        return <div>Hello {this.props.name}</div>;
    }
};

ReactDOM.render(<HelloMessage name="John" />, document.getElementById('app'));

이렇게 변환시킵니다:

"use strict";

var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();

var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var HelloMessage = (function (_React$Component) {
    _inherits(HelloMessage, _React$Component);

    function HelloMessage() {
        _classCallCheck(this, HelloMessage);

        _get(Object.getPrototypeOf(HelloMessage.prototype), "constructor", this).apply(this, arguments);
    }

    _createClass(HelloMessage, [{
        key: "render",
        value: function render() {
            return React.createElement(
                "div",
                null,
                "Hello ",
                this.props.name
            );
        }
    }]);

    return HelloMessage;
})(React.Component);

;

ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), document.getElementById('app'));

몇몇 경고가 붙어 있는 대부분의 ES6 기능들은 Bebel 5.8.23 (예: https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.js)에 의해 변환된다면 JavaScript를 쓸 때 사용할 수 있습니다.

메모

  • 분명히 하자면, Babel은 JSX를 사용하지 않더라도 원래 의도된 목적(예: 보다 새로운 버전의 JavaScript 코드를 이전 버전의 JavaScript 코드로 컴파일하기)을 위해 얼마든지 사용할 수 있습니다. 하지만, React를 사용하는 대부분의 사람들은 지원되지 않는 ES* 기능들과 JSX 변환 둘 다를 위해 사용하고 있습니다.

  • Babel handbook을 읽고 Babel에 대해 더 많이 배워보세요.

results matching ""

    No results matching ""