[기술 세미나] core-js

이승준·2025년 1월 30일

JS

목록 보기
5/5
post-thumbnail

core-js(Polyfill)이란?

우선 폴리필이란 단어의 뜻은 충전솜이란 말을 의미한다.

  • 즉, 우리가 바벨을 이용해 구버전 코드로 트랜스파일링을 하지만, 아직 부족한 부분이 있다.
  • Promise, Array.prototype.includes() 같은 새로운 문법이 아닌 새로운 기능들은 바벨을 통해 트랜스파일링 되지 못한다.
  • 따라서, 전역객체에 해당 메서드나 객체를 추가해줘야 하는데 이게 마치 충전솜과같은 역할을 한다고 해서 polyfill 이라고 부른다.

7.4버전 이후부터는 @babel/plugin이 지원되지않아, core-js라는 써드파티 라이브러리를 사용한다.

폴리필의 문제점

  • 기본적으로 전역공간에 폴리필이 만든 함수나 객체를 채워넣는 방식으로 구동된다.

  • 이는,곧 전역공간이 오염되고, 다른 코드들까지 영향을 준다는 의미이다.

  • 폴리필에서 Promise를 정의해서 채워넣었는데 다른 코드에서는 이미 ES6에서 정의된 Promise를 참조해서 사용하는경우 충돌의 예시가 된다.

  • @babel/plugin-transform-runtime 폴리필을 사용하면 전역객체에 충돌을 방지하기 위해 바벨이 es6+의 문법들을 자체 구현한 함수로 트랜스파일링 해준다.

@babel/plugin-transform-runtime 사용시 문제점

  1. [1,2,3].includes와 같이 인스턴스의 메소드는 제대로 트랜스파일링 되지 않는 이슈가 있다.
  2. 전역객체에 의존성이 있는 함수가 있다면?
    • axios는 전역공간에 선언된 Promise가 있어야 제대로 동작하는데 이 플러그인은 트랜스파일링 과정에서 자체 구현된 함수로 변경되기 때문에 전역공간에 Promise를 채우지 않는다. 그래서 아래처럼 node_modules내부에 있는 axios가 런타임에 트랜스파일 될 수 있도록 웹팩 설정을 커스텀해줘야 한다.
    • include: [
      	/src\/js/,
      	/node_modules\/axios/
      ],

이 런타임 폴리필 방식은 제한사항이 있으므로 완벽하게 폴리필을 넣어주고 싶은 경우 다른 방식을 사용해야 한다.

core-js를 활용해 개선된 폴리필 적용해보기

core-js는 기존 @babel/polyfill의 전역 공간 오염 문제와 @babel/plugin-transform-runtime의 인스턴스 메서드 문제를 모두 해결한 최신 폴리필 방식입니다.

🔍 1. 기존 문제점 다시보기

@babel/plugin-transform-runtime만 사용하면?

  • 전역 객체(Promise 등)는 폴리필되지만, 인스턴스 메서드(Array.includes())는 변환되지 않음.
  • → TypeError: arr.includes is not a function 오류 발생

@babel/polyfill 사용하면?

  • 전역 공간을 오염시킴 (모든 Promise, Symbol 등이 글로벌하게 변경됨)

core-js를 사용하면?

  • 전역 공간 오염 없이 필요한 폴리필만 추가
  • 인스턴스 메서드(includes() 등)도 정상적으로 변환됨!



원본 ES6 코드 (script.js)

// 최신 ES6+ 기능
const arr = [1, 2, 3];

console.log(arr.includes(2)); // ✅ ES7 기능 (IE11 미지원)
console.log(Promise.resolve("완료!")); // ✅ ES6 Promise

class Person {
    constructor(name) {
        this.name = name;
    }
}

const person = new Person("홍길동");
console.log(person.name);

core-js@3 설치

npm install --save core-js

babel.config.json 설정

{
  "presets": [
    ["@babel/preset-env", {
      "useBuiltIns": "entry",
      "corejs": 3
    }]
  ],
}

📌 useBuiltIns: usage 옵션 설명

  • 이 옵션을 사용하면, 코드에서 실제로 사용된 기능만 골라서 폴리필됩니다.
  • 즉, 필요한 폴리필만 추가하므로, 번들 크기가 줄어듭니다.
  • enty 옵션을 사용하면 모든 기능이 폴리필됩니다.



Babel 변환 실행

npx babel script.js --out-file lib/script.js



core-js 적용 후 변환된 ES5 코드

"use strict";

function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
// 최신 ES6+ 기능
var arr = [1, 2, 3];
console.log(arr.includes(2)); // ✅ ES7 기능 (IE11 미지원)
console.log(Promise.resolve("완료!")); // ✅ ES6 Promise
var Person = /*#__PURE__*/_createClass(function Person(name) {
  _classCallCheck(this, Person);
  this.name = name;
});
var person = new Person("홍길동");
console.log(person.name);

브라우저에서도 잘 동작한다.

그렇다면 core-js가 어떻게 인스턴스 메서드 미변환 문제와 전역 오염 문제를 해결한걸까?

  • useBuiltIns: "usage" 옵션은 코드에서 실제로 사용된 기능만 골라서 폴리필을 추가.
  • includes를 사용하면 core-js/modules/es.array.includes.js만 추가됨 => 필요한 기능만 core-js가 동적으로 추가해주기 때문에, 오염을 방지할 수 있다.

번외

  • Babel이 변환할 때 core-js/modules/es.array.includes.js 같은 모듈을 추가하는데,이 폴리필이 실제로 어떻게 동작하는지 직접 확인해보자.
cat node_modules/core-js/modules/es.array.includes.js

core-js/modules/es.array.includes.js 코드

  • 이렇게는 잘 모르겠지만, internals/array-includes.js라는 코드를 import해서 구현하는것같다.

internals/array-includes.js 코드

  • internals/array-includes.js를 확인해보니 간단한 while문과 if문 만으로 include 기능을 구현하는것을 확인할 수 있다!
profile
들은것은 잊어버린다 본것은 기억된다 해본것은 내것이 된다

0개의 댓글