> For the complete documentation index, see [llms.txt](https://yamoo9.gitbook.io/webpack/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yamoo9.gitbook.io/webpack/babel/babel-plugins.md).

# Babel 플러그인

## 클래스 필드 선언 <a href="#proposal-class-properties" id="proposal-class-properties"></a>

ES 표준에 제안 된 [클래스 필드 선언(class field declarations)](https://github.com/tc39/proposal-class-fields) 구문을 사용하면 클래스 문법 사용 시 편리하게 스태틱, 인스턴스 멤버를 추가해 사용할 수 있습니다. 하지만 이 기능을 현재 제안된 기술로 [@babel/preset-env 사전 설정](/webpack/babel/babel-cli-configure.md#babel-config)에는 포함되어 있지 않아 사용할 수 없습니다.

{% tabs %}
{% tab title="Button.js" %}

```javascript
class Button {
  constructor(props) {
    this.props = { ...this.constructor.defaultProps, ...props };
  }
  
  // 클래스 멤버
  static defaultProps = {
    type: 'button'
  };
  
  // 인스턴스 멤버
  displayProps = () => {
    console.log(this.props);
  };
}
```

{% endtab %}
{% endtabs %}

클래스 필드 선언을 사용하기 위해 [@babel/plugin-proposal-class-properties](https://www.npmjs.com/package/@babel/plugin-proposal-class-properties) 플러그인 패키지를 설치합니다.

{% tabs %}
{% tab title="패키지 설치" %}

```bash
npm i -D @babel/plugin-proposal-class-properties
```

{% endtab %}
{% endtabs %}

설치한 플러그인을 사용하기 위한 설정을 `babel.config.json` 파일에 추가합니다.

{% tabs %}
{% tab title="babel.config.json" %}

```javascript
{
  "plugins": [
    "@babel/plugin-proposal-class-properties"
  ]
}
```

{% endtab %}
{% endtabs %}

`start` 명령을 실행해 컴파일 하면, 클래스 필드 선언 구문을 호환 가능한 코드로 출력해줍니다.

{% tabs %}
{% tab title="NPM 명령 실행" %}

```bash
npm start
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="컴파일 된 출력 코드" %}

```javascript
"use strict";

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

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

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

var Button = function Button(props) {
  var _this = this;

  _classCallCheck(this, Button);

  _defineProperty(this, "displayProps", function () {
    console.log(_this.props);
  });

  this.props = _objectSpread(_objectSpread({}, this.constructor.defaultProps), props);
};

_defineProperty(Button, "defaultProps", {
  type: 'button'
});

```

{% endtab %}
{% endtabs %}

## 비공개 멤버 <a href="#plugin-proposal-private-methods" id="plugin-proposal-private-methods"></a>

ES 표준에 제안 된 [비공개 멤버(private methods)](https://github.com/tc39/proposal-private-methods) 구문을 사용하면 클래스 문법 사용 시 편리하게 비공개 멤버를 추가해 (JAVA의 private 접근 제어자처럼) 사용할 수 있습니다. 하지만 이 기능을 현재 제안된 기술로 [@babel/preset-env 사전 설정](/webpack/babel/babel-cli-configure.md#babel-config)에는 포함되어 있지 않아 사용할 수 없습니다.

{% tabs %}
{% tab title="Button.js" %}

```javascript
class Button {
  constructor(props) {
    this.props = props ?? { ...this.constructor.defaultProps, ...props };
  }
  
  // 비공개 멤버 (클래스 외부에서 접근 불가능)
  #API_TOKEN = 'token-fkjw2jicjx8kjvwdijf3';

  static defaultProps = {
    type: 'button'
  };

  fetchData() {
    // 클래스 또는 인스턴스 멤버는 비공개 멤버에 접근 가능
    fetch(`https://api.dev?token=${this.apiToken}`)
      .then((res) => console.log(res))
      .catch((error) => console.error(error.message));
  }

  displayProps = () => {
    console.log(this.props);
  };
}
```

{% endtab %}
{% endtabs %}

클래스 필드 선언을 사용하기 위해 [@babel/plugin-proposal-private-methods](https://www.npmjs.com/package/@babel/plugin-proposal-private-methods) 플러그인 패키지를 설치합니다.

{% tabs %}
{% tab title="패키지 설치" %}

```bash
npm i -D @babel/plugin-proposal-private-methods
```

{% endtab %}
{% endtabs %}

설치한 플러그인을 사용하기 위한 설정을 `babel.config.json` 파일에 추가합니다.

{% tabs %}
{% tab title="babel.config.json" %}

```javascript
{
  "plugins": [
    "@babel/plugin-proposal-private-methods"
  ]
}
```

{% endtab %}
{% endtabs %}

`start` 명령을 실행해 컴파일 하면, 클래스 필드 선언 구문을 호환 가능한 코드로 출력해줍니다.

{% tabs %}
{% tab title="NPM 명령 실행" %}

```bash
npm start
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="컴파일 된 출력 코드" %}

```javascript
"use strict";

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _classPrivateFieldGet(receiver, privateMap) { var descriptor = privateMap.get(receiver); if (!descriptor) { throw new TypeError("attempted to get private field on non-instance"); } if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }

var _API_TOKEN = new WeakMap();

var Button = /*#__PURE__*/function () {
  function Button(props) {
    var _this = this;

    _classCallCheck(this, Button);

    _API_TOKEN.set(this, {
      writable: true,
      value: 'token-fkjw2jicjx8kjvwdijf3'
    });

    _defineProperty(this, "displayProps", function () {
      console.log(_this.props);
    });

    this.props = props !== null && props !== void 0 ? props : _objectSpread(_objectSpread({}, this.constructor.defaultProps), props);
  }

  _createClass(Button, [{
    key: "apiToken",
    get: function get() {
      return _classPrivateFieldGet(this, _API_TOKEN);
    }
  }, {
    key: "fetchData",
    value: function fetchData() {
      fetch("https://api.dev?token=".concat(this.apiToken)).then(function (res) {
        return console.log(res);
      }).catch(function (error) {
        return console.error(error.message);
      });
    }
  }]);

  return Button;
}();

_defineProperty(Button, "defaultProps", {
  type: 'button'
});

```

{% endtab %}
{% endtabs %}

## 참고

살펴본 Babel 플러그인 외에도 다양한 플러그인을 사용할 수 있습니다.

{% embed url="<https://babeljs.io/docs/en/plugins>" %}

&#x20;
