CommonJS vs ES Modules

๋ฐฐ๊ฒฝ

ํ•จ์ˆ˜๋“ค๋ผ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ? ์ „์—ญ ์Šค์ฝ”ํ”„์— ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ๋‘”๋‹ค๋ฉด ๋‹ค๋ฅธ ๋‚ด๋ถ€ ์š”์†Œ์— ์˜ํ•ด ๋ง๊ฐ€์งˆ ์ˆ˜๋„ ์žˆ๊ณ , ์ˆœ์„œ๊ฐ€ ๋’ค์—‰์ผœ ์ „์—ญ ์Šค์ฝ”ํ”„์˜ ์š”์†Œ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋ชจ๋“ˆ์ด๋ผ๋Š” ๋ฐฉ์‹์„ ์ด์šฉํ•˜๋ฉด ๊ฐ๊ฐ ํ•„์š”ํ•œ ๋ชจ๋“ˆ์„ importํ•˜์—ฌ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์–ด๋””์—์„œ ์—๋Ÿฌ๊ฐ€ ๋‚˜๋Š”์ง€ ํŒŒ์•…ํ•˜๊ธฐ ์‰ฝ๋‹ค. ๋ชจ๋“ˆ์„ ๋งŒ๋“ค๊ณ  import, export ํ•˜๋Š” ์‹œ์Šคํ…œ์„ ๋ชจ๋“ˆ ์‹œ์Šคํ…œ์ด๋ผ ํ•˜๋Š”๋ฐ ํ˜„์žฌ 2๊ฐ€์ง€์˜ ๋ชจ๋“ˆ ์‹œ์Šคํ…œ์ด ํ™œ๋ฐœํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋‹ค.

  • CommonJS
  • ES modules

 


์ฐจ์ด์ 

๊ธฐ์ดˆ ๋ฌธ๋ฒ•

CommonJS

const module = require('์–ด์ฉŒ๊ตฌ');
const { func } = require('์–ด์ฉŒ๊ตฌ');

module.exports = '์–ด์ฉŒ๊ตฌ'; // default exports
module.exports.func = () => {}; // named exports

 

ES Modules

import a from '์–ด์ฉŒ๊ตฌ';
import {func} from '์–ด์ฉŒ๊ตฌ';

export const a = '์–ด์ฉŒ๊ตฌ'; // default exports
export default func = () => {}; // named exports

 

ํ˜ธํ™˜

ESM์™€ CJS๋Š” ํ˜ธํ™˜์ด ์•ˆ๋œ๋‹ค. ESM์—์„œ CJS๋ฅผ default importํ•˜๊ฑฐ๋‚˜ CJS์—์„œ ESM์„ require๋กœ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•๋งŒ์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์ด์กฐ์ฐจ๋„ ๋งŽ์€ boilerplate์™€ ๋ฒˆ๋“ค๋Ÿฌ๊ฐ€ ํ•„์š”ํ•˜๋ฉฐ ์ˆœ์„œ๊ฐ€ ๋ณด์žฅ๋˜์ง€ ์•Š๋Š”๋‹ค.

 

 

๋น„๊ต

<ES Modules>

  • ๋ชจ๋“ˆ์„ ๋น„๋™๊ธฐ ํ™˜๊ฒฝ์—์„œ ๋‹ค์šด๋กœ๋“œํ•˜๋ฉฐ, import export ๊ตฌ๋ฌธ์„ ์ฐพ์•„์„œ ํŒŒ์‹ฑํ•œ๋‹ค.
  • ๋”ฐ๋ผ์„œ ES modules๋Š” ์‹คํ–‰ํ•ด๋ณด์ง€ ์•Š์•„๋„ import, export ์—๋Ÿฌ๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • config๋ฅผ type="module" ๋กœ set ํ•ด์ฃผ์–ด์•ผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • top-level await๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

<Common JS>

  • require๊ฐ€ ๋™๊ธฐ๋กœ ์ด๋ฃจ์–ด์ง€๋ฏ€๋กœ promise๋ฅผ return ํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • ๋”ฐ๋ผ์„œ CommonJS๋Š” ์‹คํ–‰ํ•ด๋ณด์•„์•ผ import, export ์—๋Ÿฌ๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ธฐ๋ณธ ๊ฐ’์ด๋‹ค.
  • top-level await๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

 

๋™์ž‘ ๋ฐฉ์‹

ES Modules

๊ฐœ๋ฐœ์ž๊ฐ€ ์ง€์ •ํ•œ ํŒŒ์ผ์„ entry point๋กœ ํ•˜์—ฌ ๋‚˜๋จธ์ง€ ํŒŒ์ผ๋“ค์€ import๋ฌธ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ ์ฐพ๋Š”๋‹ค. ํŒŒ์ผ์„ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋ชจ๋“ˆ ๋ ˆ์ฝ”๋“œ ๋ผ๋Š” ๊ณผ์ •์ด ํ•„์š”ํ•˜๊ณ  ์ดํ›„ ๋ชจ๋“ˆ ๋ ˆ์ฝ”๋“œ๋ฅผ ๋ชจ๋“ˆ ์ธ์Šคํ„ด์Šค๋กœ ๋ณ€ํ™˜ํ•ด์•ผํ•œ๋‹ค. ๋ชจ๋“ˆ ์ธ์Šคํ„ด์Šค๋Š” ์ฝ”๋“œ์™€ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๊ฒฐํ•ฉํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

๋ชจ๋“ˆ์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ณผ์ •์€ entry ํŒŒ์ผ์ด ๋ชจ๋“ˆ ์ธ์Šคํ„ด์Šค ์ „์ฒด ๊ทธ๋ž˜ํ”„๋ฅผ ๊ทธ๋ฆฌ๋ฉด์„œ ์ง„ํ–‰๋˜๋Š”๋ฐ, ES ๋ชจ๋“ˆ ๋ช…์„ธ์— ๋”ฐ๋ฅด๋ฉด ๊ทธ ๊ณผ์ •์€ ํฌ๊ฒŒ ๊ตฌ์„ฑ, ์ธ์Šคํ„ด์Šค ํ™”, ํ‰๊ฐ€๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.

์ด๋ ‡๊ฒŒ ES modules๋Š” ๋น„๋™๊ธฐ๋ฐฉ์‹์œผ๋กœ ๋‹จ๊ณ„๊ฐ€ ์ง„ํ–‰๋˜๋Š” ๋“ฏ ๋ณด์ด์ง€๋งŒ ES ๋ชจ๋“ˆ ๋ช…์„ธ ๋ง๊ณ ๋„ loader๊ฐ€ ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ์‹์— ๋”ฐ๋ผ์„œ๋„ ์˜ํ–ฅ์„ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์—, ์‚ฌ์šฉ ์ค‘์ธ ํ”Œ๋žซํผ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋กœ๋”๊ฐ€ ๋™๊ธฐ์ ์œผ๋กœ ํŒŒ์ผ์„ ๋กœ๋“œํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

1. ๊ตฌ์„ฑ : ๋ชจ๋“  ํŒŒ์ผ์„ ํ™•์ธํ•˜๊ณ (resolution) ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ๋ชจ๋“ˆ ๋ ˆ์ฝ”๋“œ๋กœ ๊ตฌ๋ฌธ๋ถ„์„ํ•œ๋‹ค.

 

loader๋Š” ํŒŒ์ผ์„ ์ฐพ์•„์„œ ๋‹ค์šด๋กœ๋“œํ•˜๋Š”๋ฐ, script ํƒœ๊ทธ์˜ src๋ฅผ ํ†ตํ•ด entry point๋ฅผ ์ฐพ๊ณ  import, export๋ฅผ ๊ฑฐ์ณ๊ฐ€๋ฉด์„œ ํŒŒ์ผ๋“ค์„ ์ฐพ๋Š”๋‹ค. ๋ฏธ๋ฆฌ ์ „์ฒด ๋ชจ๋“ˆ ๊ทธ๋ž˜ํ”„๋ฅผ ์ž‘์„ฑํ•ด์•ผํ•˜๋ฉฐ ์ด ๋•Œ ๋ณ€์ˆ˜์—๋Š” ์•„์ง ๊ฐ’์ด ์—†๋‹ค. ๋”ฐ๋ผ์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” ๋ชจ๋“ˆ ๊ฒฝ๋กœ์— ๋ณ€์ˆ˜ ๊ฐ’์„ ๋„ฃ์–ด ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์ง€๋งŒ, import ํ‘œํ˜„์‹ ์„ ์‚ฌ์šฉํ•˜๋ฉด dynamic import๊ฐ€ ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ๋ณ€์ˆ˜ ๊ฐ’์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ชจ๋“ˆ ๋ ˆ์ฝ”๋“œ๋กœ ๋ถ„์„ํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ชจ๋“ˆ์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ณ , ํ•ด๋‹น ๋ ˆ์ฝ”๋“œ๋Š” ๋ชจ๋“ˆ๋งต์— ์ถ”๊ฐ€๋˜์–ด ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๋กœ๋”๊ฐ€ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค. ๋ชจ๋“ˆ ๋ถ„์„ ์ „์— ํ•ด๋‹น ํŒŒ์ผ์ด ๋ชจ๋“ˆ์ž„์„ ์•Œ๋ ค์ฃผ๊ธฐ ์œ„ํ•ด ์Šคํฌ๋ฆฝํŠธ ํƒœ๊ทธ ๋‚ด๋ถ€์— type="module"์„ ํ‘œ์‹œํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค. node ํ™˜๊ฒฝ์—์„œ๋Š” .mjs ํ™•์žฅ์ž๋กœ ๋ชจ๋“ˆ์ž„์„ ์•Œ๋ ค์ค€๋‹ค.

 

2. ์ธ์Šคํ„ด์Šค ํ™” : export๋œ ๊ฐ’์„ ์œ„ํ•ด ๋ฉ”๋ชจ๋ฆฌ์˜ ๊ณต๊ฐ„์„ ์ฐพ๊ณ  export, import๋ฅผ ํ•ด๋‹น ๊ณต๊ฐ„์— linkingํ•œ๋‹ค.

 

๋ชจ๋“ˆ ๋ ˆ์ฝ”๋“œ๋กœ๋ถ€ํ„ฐ ๋ชจ๋“ˆ ํ™˜๊ฒฝ ๋ ˆ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ณ€์ˆ˜๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. ๋ณ€์ˆ˜ ๊ฐ’์€ ํ‰๊ฐ€๊ฐ€ ๋๋‚œ ํ›„์— ์ฑ„์›Œ์ง„๋‹ค.

์œ„์™€ ๊ฐ™์ด export์™€ import๋ฅผ ๊ฐ™์€ ๋ณ€์ˆ˜์— linkingํ•œ๋‹ค. export ๋“ˆ์€ ๋ณ€์ˆ˜๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, import๋Š” ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

 

3. ํ‰๊ฐ€ : ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๋ณ€์ˆ˜์˜ ์‹ค์ œ ๊ฐ’์œผ๋กœ ์ฑ„์šด๋‹ค.

 

ํ• ๋‹น๋œ ๋ณ€์ˆ˜ ๊ฐ’์„ ์ฑ„์šด๋‹ค. ์ด ๋•Œ ๋‹ค๋ฅธ ์ž‘์—…์ด ์ผ์–ด๋‚ฌ๋‹ค๊ณ  ํ•ด์„œ ๋ชจ๋“ˆ์ด 2๋ฒˆ ํ‰๊ฐ€๋˜๋ฉด ์•ˆ๋˜๋ฏ€๋กœ ๋ชจ๋“ˆ ๋งต์„ ์ด์šฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ๋ชจ๋“ˆ ๋ ˆ์ฝ”๋“œ๋งŒ์ด ์กด์žฌํ•˜๋„๋ก ๋ณด์žฅํ•œ๋‹ค.

 

 

Common JS

  • ํŒŒ์ผ์„ import ์ˆœ์„œ์— ๋”ฐ๋ผ ์ˆœ์ฐจ์ ์œผ๋กœ ์™„์ „ ์‹คํ–‰ํ•˜๋ฏ€๋กœ ๋ณ€์ˆ˜ ๊ฐ’์„ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ณ€์ˆ˜์— linking ์‹œ export ๊ฐ’์„ ์‚ฌ๋ณธ์œผ๋กœ ๋ณต์‚ฌํ•˜์—ฌ ์‚ฌ์šฉํ•œ๋‹ค. ๋”ฐ๋ผ์„œ export, importํ•˜๋Š” ๋ณ€์ˆ˜๊ฐ€ ๋‹ค๋ฅด๋‹ค.

 

์ˆœํ™˜ ์˜์กด์„ฑ

// main.js
let count = require('./counter.js').count;
export message = 'hi';

// counter.js
let message = require('./main.js').message; // message ์ •์˜๋˜์–ด ์žˆ์ง€ ์•Š์Œ
setTimeout(() => console.log(message), 0); // CommonJS : undefined, ES Modules : 'hi'

์ˆœํ™˜๊ด€๊ณ„๊ฐ€ ์žˆ์„ ๋•Œ CommonJS๋Š” ๋ณ€์ˆ˜ ๊ฐ’์„ ๋ณต์‚ฌํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ main.js์—์„œ์˜ message๊ฐ€ ํ• ๋‹น์ด ๋˜์–ด๋„ counter.js์—์„œ์˜ ๋ณ€์ˆ˜๋Š” ๋ณ€ํ•˜์ง€ ์•Š๋Š”๋‹ค. ํ•˜์ง€๋งŒ ES Modules์—์„œ๋Š” ๊ฐ™์€ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ setTimout์—์„œ ์ œ๋Œ€๋กœ ํ• ๋‹น๋œ ๋ณ€์ˆ˜๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค. ES Module์€ ์œ„์™€ ๊ฐ™์ด ์ˆœํ™˜ ์˜์กด์„ฑ์„ ์ง€์›ํ•œ๋‹ค.

 


์‹ค์ œ ์‚ฌ์šฉ

React์—์„œ๋Š” ESModules์„ ์ฃผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. ํŒจํ‚ค์ง€ ๋ชจ๋“ˆ๋“ค์€ ๊ฒฐ๊ตญ CommonJS๋ฅผ ๊ธฐ๋ณธ ๋ชจ๋“ˆ ์‹œ์Šคํ…œ์œผ๋กœ ์„ ํƒํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์ฝ”๋“œ ์ž‘์„ฑ ์‹œ CommonJS๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ์–ด์•ผ ํ•˜๋Š”๋ฐ ํ•ด๋‹น ์ž‘์—…์€ ๋ฒˆ๋“ค๋Ÿฌ์ธ Babel์ด ์ˆ˜ํ–‰ํ•œ๋‹ค.

https://runebook.dev/ko/docs/babel/babel-plugin-transform-modules-commonjs/index

 

Babel - @babel/plugin-transform-modules-commonjs - History ์ฐธ๊ณ  : ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์€ modules ์˜ต์…˜ ์•„๋ž˜ @babel/preset-env

 

runebook.dev

 


 

์ •๋ฆฌ

๋Œ€ํ‘œ์ ์ธ ๋‘ ๊ฐ€์ง€์˜ ๋ชจ๋“ˆ ์‹œ์Šคํ…œ ์ค‘ CommonJS๊ฐ€ ์ฒ˜์Œ์— ๋“ฑ์žฅํ•˜์˜€์œผ๋‚˜, ํ˜„์žฌ๋Š” ES modules ๋ชจ๋“ˆ ์‹œ์Šคํ…œ์ด ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋‹ค. CommonJS์™€ ๋น„๊ตํ•˜์—ฌ ES modules๋Š” ๋น„๋™๊ธฐ๋กœ ๋™์ž‘ํ•˜์—ฌ ์†๋„๊ฐ€ ๋น ๋ฅด๊ณ  ์‹ค์ œ ์‚ฌ์šฉ๋˜๋Š” ๋ถ€๋ถ„๋งŒ์„ import(tree shaking) ํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ๊ฒŒ ์ฐจ์ง€ํ•˜๋ฉฐ, ๊ฐ€๋…์„ฑ์ด ์ข‹๊ณ  ์ˆœํ™˜ ์˜์กด์„ฑ์„ ์ง€์›ํ•œ๋‹ค๋Š” ์ด์ ์ด ์žˆ๋‹ค.

 


 

์ฐธ๊ณ 

https://yceffort.kr/2020/08/commonjs-esmodules
https://ui.toast.com/weekly-pick/ko_20180402
https://ko.javascript.info/modules-dynamic-imports
https://www.daleseo.com/js-module-import/

 

 

 

 ๋ถ€์ •ํ™•ํ•œ ์ •๋ณด๊ฐ€ ๋‹ด๊ฒจ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! 

 ๋Œ“๊ธ€๋กœ ์•Œ๋ ค์ฃผ์„ธ์š” :) 

๋ฐ˜์‘ํ˜•