# 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;


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yamoo9.gitbook.io/webpack/babel/babel-plugins.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
