๐ฃ๏ธ import๊ณผ require์ ์ฐจ์ด๋ฅผ ์๊ณ ๊ณ์๋์?
๐ค ๋ ธ๋ ํ๋ก์ ํธ์์๋ require ๋ง์ด ๋ณธ ๊ฑฐ ๊ฐ๊ณ , react์์ import ๋ง์ด ์ผ๋ ๊ฑฐ ๊ฐ์๋ฐ?
import๊ณผ require์ ๋ํด ์๊ธฐ ์ํด์๋ ๋ชจ๋ ์์คํ ์ด๋ผ๋ ๊ฒ์ ๋ํด ์์์ผ ํ๋ค.
์ค๋์ ๋ชจ๋ ์์คํ ์ด ๋ฌด์์ด๊ณ , ์ด๋ค ๊ฒ๋ค์ด ์์ผ๋ฉฐ, ๊ฐ๊ฐ์ ํน์ง๊ณผ ์ฅ๋จ์ ์ ์ดํด๋ณด์.
JS ๋ชจ๋ ์์คํ ์ด๋?
์์ ์น์์ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๋ด๋นํ๊ณ ์ ๊ณตํ ์ ์๋ ๊ธฐ๋ฅ๋ค์ ํ์ด์ง๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฒ ์ ๋์๋ค.
ํ์ง๋ง ์ ์ฐจ ์๋ฐ์คํฌ๋ฆฝํธ์ ์ญํ ์ด ๊ฑฐ๋ํด์ง๊ณ , ๊ธฐ๋ฅ๋ค์ ๋ง๋ค๋ฉด์ ๋ค์์คํ์ด์ค๋ฉฐ dependency๋ฉฐ ๊ด๋ฆฌํ ๊ฒ๋ ๋น๋ก(์ ๋น๋ก๋ ์๋ ์๋?)ํด์ ๋ฐฉ๋ํด์ก๋ค.
๋ชจ๋ ์์คํ ์ ์ด๋ ๊ฒ ๊ด๋ฆฌํ๊ธฐ ์ด๋ ค์ด ์ค์ฝํ ์ด์๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๋ฐฉ์์ผ๋ก ๋ฑ์ฅํ๊ฒ ๋์๋ค.
JS ๋ชจ๋ ์์คํ ์ ์์์ผ ํ๋ ์ด์
ํ๋ก์ ํธ๋ฅผ ํ๋ค ๋ณด๋ฉด ํ๋ก์ ํธ๋ฅผ ๋๋๋ค๋ฉฐ ๊ณตํต์ผ๋ก ์ฌ์ฉํ๋ ๊ธฐ๋ฅ๋ค์ ๋ณต์ฌ+๋ถ์ฌ๋๊ธฐ ๋ฐ๋ณต์์ ์ ํ๋ ๊ฒฝ์ฐ๊ฐ ์ข ์ข ์๋ค.
๊ทผ๋ฐ ํ ๊ณณ์ ์ฝ๋๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์์์ ์ผ๋ก ํ๋ก์ ํธ๋ค ๋ชจ๋์์ sync๋ฅผ ๋ง์ถ๋ ์์ ์ ํด์ผ ํ๋ ์๊ณ ์ค๋ฌ์์ด ์๋ค.
์ด ์์ ์ ์ง์ณ์ ๋ค๋ฅธ ํ๋ก์ ํธ์์๋ ์์ฝ๊ฒ ๊ณตํต ๊ธฐ๋ฅ๋ค์ ๊ฐ์ ธ๋ค ์ธ ์ ์๊ณ , ๋ณ๊ฒฝ ์ฌํญ๋ ์ผ๊ด+์๋ ์ ์ฉํ๊ณ ์ถ๋ค๋ ์๊ฐ์ด ๋ ๋ค๋ฉด, ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๋ง๋ค์ด์ dependency๋ก ์ฌ์ฌ์ฉํด๋ณด๋ ๋ฐฉ๋ฒ์ด ์๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ฑ! ๋ง๋ค๊ณ ์ด์ ๋ง์ง๋ง ํผ๋ธ๋ฆฌ์ฑ ๋จ๊ณ์์ ๊ณ ๋ฏผ๋ค์ด ์๊ฒจ๋๋ค.
1. tree shaking์ด ๊ฐ๋ฅํ๋๋ก ํ๋ ๋ฐฉ๋ฒ?
2. JS ๋ชจ๋ ์์คํ ์ค์์ ๋ญ ์จ์ผ ํ์ง?
์ด๋ JS๋ชจ๋ ์์คํ ์ ๋ํด ์๊ณ ์๋ค๋ฉด, ์ด ๊ณ ๋ฏผ๋ค์ ๋ํ ๋ต์ ์ฐพ์ ์ ์๋ค.
JS ๋ชจ๋ ์์คํ ์ ์ข ๋ฅ
CommonJS | AMD: Async Module Definition | UMD: Universal Module Definition | ECMAScript Module (ESM) |
require ์ module.exports | require | require์ module.exports | import์ export |
- ES5 ๋ชจ๋ ์์คํ
- node๋ก ๊ตฌํ - ๋ชจ๋ ์ค์น ์ ์๋ฒ์ฌ์ด๋์ ์ฐ์ - import๋ฅผ ํ๋ฉด object๋ฅผ ๋ฐํ๋ฐ๋๋ค ๋ฐ๋ผ์ ๋ค์๊ณผ ๊ฐ์ ํน์ง์ด ์๋ค: - tree shaking์ด ๋ถ๊ฐ๋ฅ - ํ๋กํผํฐ ๊ฒ์(property lookup)์ด ๋ฐํ์์ ์งํ๋๋ฏ๋ก ์ ์ ๋ถ์(static analyzing)์ด ๋ถ๊ฐ๋ฅ - ํญ์ object์ ๋ณต์ฌ๋ณธ์ ๋ฐ์ผ๋ฏ๋ก ๋ชจ๋ ์์ฒด์ ์ฆ๊ฐ์ ์ธ ๋ณํ๋ ๋ฐ์๋์ง ์๋๋ค - ์ํ (cyclic) dependency ๊ด๋ฆฌ๊ฐ ์ด๋ ต๋ค - syntax๊ฐ ๊ฐ๋จํ๋ค |
- ES5 ๋ชจ๋ ์์คํ
- RequireJs๋ก ๊ตฌํ - ๋ชจ๋์ ๋์ ์ผ๋ก ๋ก๋ํ๊ณ ์ถ์ ๋ ํด๋ผ์ด์ธํธ (๋ธ๋ผ์ฐ์ )์์ ์ฐ์ - syntax๊ฐ ๋ณต์กํ๋ค |
- ES5 ๋ชจ๋ ์์คํ
- AMD์ CMJ ํ๊ฒฝ ๋ชจ๋์์ ์ฌ์ฉ ๊ฐ๋ฅ - CommonJS์ syntax์ AMD์ ๋น๋๊ธฐ ๋ก๋ฉ - UMD๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ ํ๊ฒฝ์์ ๋ชจ๋ ์ฌ์ฉ ๊ฐ๋ฅํ๋๋ก ํ๋ฉด์๋ ์ ์ญ ๋ณ์ ์ ์ธ๋ ์ง์ํ๋ค - ๋ฐ๋ผ์ UMD ๋ชจ๋์ ํด๋ผ์ด์ธํธ์ ์๋ฒ ๋ชจ๋์์ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค |
- ES6 ๋ชจ๋ ์์คํ
- ํด๋ผ์ด์ธํธ์ ์๋ฒ ๋ชจ๋์์ ์ฌ์ฉ ๊ฐ๋ฅ - ๋ฐํ์/ ์ ์ (static) ๋ชจ๋ ๋ก๋ฉ ์ง์ - import๋ฅผ ํ๋ฉด binding value (์ค์ ๊ฐ)์ ๋ฐํ๋ฐ๋๋ค - ๋ฐ๋ผ์ ๋ชจ๋ ์์ฒด์ ์ฆ๊ฐ์ ์ธ ๋ณํ๊ฐ ๋ฐ์๋๋ค - ์ ์ ๋ถ์ (static analyzing) ๊ฐ๋ฅ : import/export๋ฅผ ์ปดํ์ผ ๋์ค์ ์ ์ ์ผ๋ก ํ ์ ์๋ค - ์ ์ ๋ถ์์ด ๊ฐ๋ฅํ๋ฏ๋ก Tree shaking์ด ๊ฐ๋ฅํ๋ค (ES6์ง์) - CJS์ ๋นํด ์ํ dependency ๊ด๋ฆฌ๊ฐ ์ฉ์ดํ๋ค |
๐ด tree shaking์ด๋?
์๋ฐ์คํฌ๋ฆฝํธ์ ๊ด์ ์์๋ tree shaking์ด๋ ์ฃฝ์ ์ฝ๋ ์ ๊ฑฐ๋ฅผ ๊ฐ๋ฆฌํค๊ธฐ ์ํด ์ฌ์ฉ๋๋ ์ฉ์ด์ด๋ค.
ESM ํน์ง ์ดํด๋ณด๊ธฐ (ft. CJS์ ๋น๊ต)
ESM export ๋ฐฉ์ ๋ ๊ฐ์ง : Named exports์ default exports
ESM export ๋ฐฉ์์๋ Named exports (๋ชจ๋ ๋น ์ฌ๋ฌ๊ฐ)์ default exports (๋ชจ๋ ๋น ํ๋)๊ฐ ์๋ค.
๋์์ ๋์ ์ฌ์ฉํ๋ ๊ฒ์ ๊ฐ๋ฅํ๋, ๋๋๋ก์ด๋ฉด ๋ถ๋ฆฌํด ์ฃผ๋ ๊ฒ์ด ์ข๋ค.
Named exports ์ฌ์ฉ
//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
return x * x;
}
export function diag(x, y) {
return sqrt(square(x) + square(y));
}
//------ main.js ------
import { square, diag } from 'lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5
// ์ ์ฒด ๋ชจ๋์ ๊ฐ์ ธ์ค๊ณ ์ถ์ ๊ฒฝ์ฐ
//------ main.js ------
import * as lib from 'lib';
console.log(lib.square(11)); // 121
console.log(lib.diag(4, 3)); // 5
CJS์์๋ ๋ค์๊ณผ ๊ฐ์ด ๋์ผํ๊ฒ ์์ฑ ๊ฐ๋ฅํ๋ค.
//------ lib.js ------
var sqrt = Math.sqrt;
function square(x) {
return x * x;
}
function diag(x, y) {
return sqrt(square(x) + square(y));
}
module.exports = {
sqrt: sqrt,
square: square,
diag: diag,
};
//------ main.js ------
var square = require('lib').square;
var diag = require('lib').diag;
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5
default exports ์ฌ์ฉ
// ํจ์ default export
//------ myFunc.js ------
export default function () {} // no semicolon!
//------ main1.js ------
import myFunc from 'myFunc';
myFunc();
// ํด๋์ค default export
//------ MyClass.js ------
export default class {} // no semicolon!
//------ main2.js ------
import MyClass from 'MyClass';
const inst = new MyClass();
// ์ ์ธ label ๋ฐฉ์
export default function foo() {} // no semicolon!
export default class Bar {} // no semicolon!
// default-export ๊ฐ์ ์ง์ export ํ๊ธฐ
export default function () {} // no semicolon! (์ต๋ช
ํจ์๋ฅผ ํ์ฉ)
export default class {} // no semicolon!
export default 'abc';
export default foo();
export default /^xyz$/;
export default 5 * 7;
export default { no: false, yes: true };
default exports ๋ฐฉ์์ ๋ณด๋ฉด default exports์ ํผ์ฐ์ฐ์ (export ํ๋ ๋์)์ด ํํ์์ผ ๊ฑฐ๋ผ๊ณ ์๊ฐํ ์๋ ์๋ค.
ํ์ง๋ง ํํ์์ด ์๋ ์ ์ธ๋ฌธ์ด๋ค. ํํ์์ผ๋ก ํด์๋๊ธฐ ์ํด์๋ ๋ค์๊ณผ ๊ฐ์ด ๊ดํธ๋ก ๊ฐ์ธ์ค์ผ ํ๋ค.
export default (function () {});
ESM export/import ์ ์ธ์ ์ต์๋จ์
ESM์ ์ ์ ๋ชจ๋์ ์ง์ํ๋ค๊ณ ํ๋ค. ์ฆ, ์กฐ๊ฑด๋ถ์ ์ผ๋ก import/export๋ฅผ ๊ฒฐ์ ํ ์ ์๋ค.
๋ฐ๋ผ์ ํด๋น ์ค์ฝํ์ ์ต์๋จ์ ์์น์์ผ์ค์ผ ํ๋ค.
ESM import ์ ํธ์ด์คํ ๋๋ค
import ํ ๋ชจ๋์ ํ์ฌ ์ค์ฝํ์ ์ต์๋จ์ผ๋ก ๋์ด์ฌ๋ ค์ง๋ ํธ์ด์คํ ์ด ๋ฐ์ํ๋ค.
ESM import ๋ ๊ฐ์ export ํ ๊ฐ์ ์ฝ๊ธฐ ์ ์ฉ LIVE(๋ณ๊ฒฝ์ฌํญ์ด ์ฆ๊ฐ ๋ฐ์๋) ๊ฐ์ด๋ค
CJS์ ๋ฌ๋ฆฌ ESM์ ์ํ dependency๋ฅผ ๋ค๋ฃจ๊ธฐ ์ฉ์ดํ๋ค๊ณ ํ๋๋ฐ, ๋ฐ๋ก export ํ ESM์ ์ฝ๊ธฐ ์ ์ฉ(read-only)์ด๊ธฐ ๋๋ฌธ์ด๋ค.
์ฝ๊ธฐ ์ ์ฉ์ด๋ผ๋ ๊ฒ ๋ฌด์จ ์๋ฏธ์ผ๊น? import ํด์จ ๊ฐ์ ๋ณ๊ฒฝ ์ฌํญ์ด ๊ณง๋ฐ๋ก ๋ฐ์๋๋ ๋ค์ ์๋ฅผ ์ดํด๋ณด์.
//------ lib.js ------
export let counter = 3;
export function incCounter() {
counter++;
}
//------ main.js ------
import { counter, incCounter } from './lib';
// import ํด์จ ๊ฐ value `counter`๋ ๋ณ๊ฒฝ ์ฌํญ์ด ๊ณง๋ฐ๋ก ์ ์ฉ๋๋ค
console.log(counter); // 3
incCounter();
console.log(counter); // 4
CJS๋ import ํด์จ ๊ฐ์ด ๋ณต์ฌ๋ณธ์ธ ๋ฐ๋ฉด, ESM์ exportํ ๊ฐ์ด ๋ฐ์ธ๋ฉ๋ ๊ฐ์ด๋ผ๊ณ ํ๋ค.
๋ฐ์ธ๋ฉ๋ ๊ฐ์ ๋ณ๊ฒฝ ์ฌํญ์ ์ฆ๊ฐ ๋ฐ์ํ export ํ ๊ฐ์ ์ฝ๊ธฐ ์ ์ฉ ๊ฐ์ด๋ค.
์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ๊ฐ์ importํด์ค๋ฉด import์์ ์ด ์๋ฐฉํฅ์ด๊ฒ ๋๋ค.
๋ฐ๋ผ์ ์ฌ๋ฌ ๊ฐ์ ๋ชจ๋๋ก ์ฝ๋๋ฅผ splitํด๋ import ๊ฐ์ ๋ณ๊ฒฝํ์ง ์๋ ์ด์ ์๋๋๋ก ์๋ํ๊ณ ,
์ํ dependency๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ์ ๊ฐ์ด ๋น์ ์์ (?)์ธ import๋ ์ง์ํด ์ค๋ค.
๐ค ๊ทผ๋ฐ ์ ์ด์ ์ํ dependency๊ฐ ๋ฐ์ํ์ง ์๊ฒ ํ๋ฉด ๋๋ ๊ฑฐ ์๋๊ฐ? ์ถ์ ์ ์๋ค.
์ด์ ๊ดํด์๋ ๋ค์์์ ๋ค๋ค๋ณด์.
๐ป ์ํ dependency๋ ๋์ ๊ฒ๋ง์ ์๋๋ค. ํนํ ๊ฐ์ฒด๋ฅผ ๋ค๋ฃฐ ๋ ์ด๋ฐ dependency๋ฅผ ์คํ๋ ค ์ ํธํ ์๋ ์๋ค.
์๋ฅผ ๋ค๋ฉด, DOM ๊ฐ์ฒด์ ๊ฐ์ด ๋ถ๋ชจ์ ์ง์ ๊ฐ์ ์ฐธ์กฐ๊ฐ ํ์ํ ์๋ ์๋ค.
์ผ๋ฐ์ ์ผ๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ฒฝ์ฐ ์ํ dependency๋ ๋์์ธ์ ์ ์ค์ ๊ฐํ๋ฉด ํผํ ์๋ ์๋ค.
ํ์ง๋ง ์์คํ ์ด ์ปค์ง๊ณ , ํนํ ๋ฆฌํํฐ๋ง ๋์ค์๋ ์ํ dependency๊ฐ ๋ฐ์ํ ์ ์๋ค.
๋ชจ๋ ์์คํ ์ด ์ํ dependency๋ฅผ ์ง์ํ๋ฉด ์์คํ ์ด ๊ณ ์ฅ ๋์ง ์๊ณ ๋ ์์ ์ ํ ์ ์์ด์ ์ ์ฉํ๋ค.
ESM ์ ์ํ dependency๋ฅผ ์ง์ํ๋ค
๋ชจ๋ A์ B๊ฐ ์๋ก๋ฅผ import ํ๊ณ ์๋ ๊ฒฝ์ฐ ์ํ dependency๋ฅผ ์ง๋ ๋ค๊ณ ํ ์ ์๋ค.
๊ฐ๋ฅํ๋ค๋ฉด ์ํ dependency๋ ๋ชจ๋ ๊ฐ์ ๊ฒฐํฉ๋(coupling)์ ๋์ฌ ๋ชจ๋ ๋ถ๋ฆฌ์ ๋ชฉ์ ์ ํค์น๋ฏ๋ก ์ง์ํด์ผ ํ๋ค.
ํ์ง๋ง ๋ถ๊ฐํผํ ๊ฒฝ์ฐ์ ์ํ dependency๊ฐ ๋ฐ์ํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ์์คํ ์ ์ด๋ฅผ ์ง์์ ํด์ผ ํ๋ค.
๋ค์์ CJS์ ESM์ด ๊ฐ๊ฐ ์ํ dependency๋ฅผ ๋ค๋ฃจ๋ ๋ฐฉ์์ด๋ค.
๋ค๋ง ์ด๋ ๋ชจ๋์ด๋ ๊ฐ์ ์ํ dependency๊ฐ ์๋ค๋ฉด ๋ชจ๋ body ๋ด๋ถ์์ import์ ์ ๊ทผ ๋ถ๊ฐ๋ฅํ๋ค๋ ์ ์ ๊ธฐ์ตํ์.
// CJS์์์ ์ํ dependency ํธ๋ค๋ง
//------ a.js ------
var b = require('b');
function foo() {
b.bar();
}
exports.foo = foo;
//------ b.js ------
// a๊ฐ ๋ฒ์ b์์ import๋๋ฉด export๊ฐ ์ถ๊ฐ๋๊ธฐ ์ ์ a์ object๋ฅผ ๋ฐ๋๋ค
// ๋ฐ๋ผ์ b๋ a.foo๋ฃฐ ์ต์๋จ์ด ์๋ a์ ์คํ์ด ๋๋๊ณ ํ๋กํผํฐ๊ฐ ์กด์ฌํ ๋ค์์์ผ ์ ๊ทผ ๊ฐ๋ฅํ๋ค.
var a = require('a');
function bar() {
if (Math.random()) {
a.foo(); // bar()์ด ๊ทธ ํ ํธ์ถ๋๋ฉด ์คํ
}
}
exports.bar = bar;
CJS ๋ฐฉ์์๋ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ์ ๋ค์ด ์๋ค.
1. node.js ์คํ์ผ์ ๋จ์ผ ๊ฐ export๋ฅผ ์ฌ์ฉํ ์ ์๋ค. object ๋์ ๋จ์ผ ๊ฐ์ export ํด์ผ ํ๋ค.
module.exports = function () { ··· };
์์ ์ดํด๋ณธ ์์์ ๋ง์ฝ์ ๋ชจ๋ a ๊ฐ ์์ ๊ฐ์ด export ๋๋ค๋ฉด, b์ ๋ณ์ a๋ ํ ๋น์ด ๋๊ธฐ ์ ๊น์ง ์ ๋ฐ์ดํธ๊ฐ ๋ฐ์๋์ง ์๊ฒ ๋๋ค.
2. named exports๋ฅผ ์ง์ ์ฌ์ฉํ ์ ์๋ค. ์ฆ, ๋ชจ๋ b๋ ๋ค์๊ณผ ๊ฐ์ด foo๋ฅผ import ํ ์ ์๊ธฐ ๋๋ฌธ์ a.foo๋ก ์ฐธ์กฐํ ์๋ฐ์ ์๋ค.
var foo = require('a').foo; // undefined
ํต์ฌ์ import๋ฅผ ํ๋ ๋ชจ๋๊ณผ export๋ฅผ ํ๋ ๋ชจ๋ ๋ชจ๋ ์ํ dependency์ ๋ํ ๋ช ์์ ์ฒ๋ฆฌ๋ฅผ ํด์ค์ผ ํ๋ค๋ ์ ์ด๋ค.
๋์์์ ESM์ด ์ํ dependency๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ ์ดํด๋ณด๋ฉด, ๋ค์๊ณผ ๊ฐ์ด ์๋์ ์ผ๋ก ์ง์์ ํด์ค๋ค๋ ๊ฑธ ์ ์ ์๋ค.
//------ a.js ------
import {bar} from 'b'; // b ๋ชจ๋์ bar์ ์ฝ๊ธฐ-์ ์ฉ ๋ฒ์ import
export function foo() {
bar(); // ์ฝ๊ธฐ ์ ์ฉ์ ๊ฐ, ์ค๋ฆฌ์ง๋ ๋ฐ์ดํฐ bar๋ฅผ ๊ฐ์ ์ ์ผ๋ก ์ฐธ์กฐ
}
//------ b.js ------
import {foo} from 'a'; // a๋ชจ๋์ foo๋ฅผ ์ฝ๊ธฐ-์ ์ฉ ๋ฒ์ ์ผ๋ก import
export function bar() {
if (Math.random()) {
foo(); // foo์ ์ค๋ฆฌ์ง๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ์ ์ผ๋ก ์ฐธ์กฐ
}
}
import๋ ์ฝ๊ธฐ-์ ์ฉ์ ๊ฐ์ ๊ฐ์ ธ์จ๋ค๋ ์ ์ ํตํด ์ํ dependency๊ฐ ์์ด๋ ํญ์ ์ค๋ฆฌ์ง๋ ๋ฐ์ดํฐ๋ฅผ ์ฐพ์๊ฐ๋๋ก ๋ณด์ฅํ๋ค.
ESM๋ก import ํ ๊ฐ์ export ๊ฐ์ ์ฝ๊ธฐ-์ ์ฉ LIVE ๋ฒ์ , CJS๋ export ๊ฐ์ ๋ณต์ฌ๋ณธ์ import ํ๋ค
๋ณต์ฌ๋ณธ์ import ํด์ ๋ฐ์ํ๋ CJS์ ๋ฌธ์ ์ ์ ์ดํด๋ณด์.
//------ lib.js ------
var counter = 3;
function incCounter() {
counter++;
}
module.exports = {
counter: counter, // (A)
incCounter: incCounter,
};
//------ main1.js ------
var counter = require('./lib').counter; // (B)
var incCounter = require('./lib').incCounter;
// importํ ๊ฐ์ ๋ณต์ฌ๋ณธ์ ๋ณต์ฌ๋ณธ์ด๋ค
console.log(counter); // 3
incCounter();
console.log(counter); // 3
// importํ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ค.
counter++;
console.log(counter); // 4
export ํ ๊ฐ์ฒด์ ๊ฐ์ ์ ๊ทผํ๊ฒ ๋๋ฉด ๋๋ค์ export์์ ๋ณต์ฌ๋์ด ๋ณต์ฌ๋ณธ์ด import ์ฌ์ฉ์ฒ์ ์ ๋ฌ๋๋ค.
๋ฐ๋ฉด์ ESM์์๋ export๊ฐ์ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก LIVE(๋ณ๊ฒฝ์ฌํญ์ด ์ฆ๊ฐ ๋ฐ์๋ ๊ฐ)์ด ์ ๋ฌ๋๋ค.
๋ค์ ์๋ฅผ ์ดํด๋ณด์.
//------ lib.js ------
export let counter = 3;
export function incCounter() {
counter++;
}
//------ main1.js ------
import { counter, incCounter } from './lib';
// importํ ๊ฐ counter๋ ๋ผ์ด๋ธ(๋ณ๊ฒฝ์ฌํญ์ด ์ฆ๊ฐ ๋ฐ์๋) ๊ฐ์ด๋ค.
console.log(counter); // 3
incCounter();
console.log(counter); // 4
// ์ฝ๊ธฐ ์ ์ฉ ๊ฐ์ธ import๋ counter์ ๋ณ๊ฒฝํ ์ ์๋ค.
counter++; // TypeError
๋ค๋ง, import๊ฐ์ ๊ฐ์ฒด ์์ฑ์ ๋ณ๊ฒฝ๊ฐ๋ฅํ๋ค.
//------ lib.js ------
export let obj = {};
//------ main.js ------
import { obj } from './lib';
obj.prop = 123; // OK
obj = {}; // TypeError
ESM๋ ์ ์ (static) ๋ชจ๋ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ ํ๋ค
ํ์ฌ ์๋ฐ์คํฌ๋ฆฝํธ ๋ชจ๋์ ๋์ ๊ตฌ์กฐ๋ฅผ ๋ค๋ค. ๋ฐ๋ผ์ ๋ฐํ์์ ์ด๋ค ๋ชจ๋์ด import/export ๋๋์ง ๋์ ์ผ๋ก ๋ณํ ์ ์๋ค.
์ ์ ๋ชจ๋ ๊ตฌ์กฐ๋ฅผ ์ง๋ ๋ค๋ ๊ฒ์ ์ปดํ์ผ ์๊ธฐ์ import/export๋ฅผ ๊ฒฐ์ ํ ์ ์๋ค๋ ๊ฒ์ด๋ค.
์ด๋ ์ฝ๋๋ฅผ ์คํํ์ง ์์๋ import/export ๊ฐ์ ๋ฐ๋ก ์ ์ ์๋ค๋ ๊ฒ์ด๋ค.
๋ฐ๋ฉด์ CJS๋ ์ ์ ๋ชจ๋ ๊ตฌ์กฐ๋ฅผ ์ง์ํ์ง ์๋๋ค. ๋ค์ ์์๋ฅผ ์ดํด๋ณด์.
์ฝ๋๋ฅผ ์คํํด์ผ์ง๋ง ์ด๋ค ๊ฐ์ด import ๋ ์ง ์ ์ ์๋ค.
var my_lib;
if (Math.random()) {
my_lib = require('foo');
} else {
my_lib = require('bar');
}
๋ค์ ์์ ๋ํ ์คํ์ ํด์ผ์ง๋ง ์ด๋ค ๊ฐ์ด export ๋๋์ง ์ ์ ์๋ค.
if (Math.random()) {
exports.baz = ···;
}
๋ฐ๋ฉด ESM์ด ์ ์ ๋ชจ๋์ ์ง์ํด์ ๋ฐ์ํ๋ ์ฅ์ ์ ๋ค์๊ณผ ๊ฐ๋ค.
1. tree shaking (๋ฒ๋ค๋ง ์ค ์ฃฝ์ ์ฝ๋ ์ ๊ฑฐ)
ํ๋ก ํธ์๋ ๊ฐ๋ฐ์์ ๋ชจ๋์ ์ฃผ๋ก ๋ค์๊ณผ ๊ฐ์ด ํธ๋ค๋ง๋๋ค :
- ๊ฐ๋ฐ ๋์ค ์์ฃผ ๋ง๊ณ ์ฃผ๋ก ์์ ๋ชจ๋๋ก ์ฝ๋๊ฐ ์์ฑ๋๋ค.
- ๋ฐฐํฌ๋ฅผ ์ํด์ ์ด ๋ชจ๋๋ค์ ์ ๊ณ , ์๋์ ์ผ๋ก ํฐ ํ์ผ๋ค๋ก ๋ฒ๋ค๋ง ๋๋ค.
๋ฒ๋ค๋ง์ ์ ํ ๊น?
1. ๋ชจ๋ ๋ชจ๋์ ๋ก๋ํ๊ธฐ ์ํ ํ์ผ๋ค์ ์ฐพ๊ธฐ ์ํ ์๊ณ ๋ฅผ ๋ ์ ์๋ค. โก ํ์ผ ์์ฒญ ๋น์ฉ์ด ์๋์ ์ผ๋ก ๋์ HTTP/1์์ ์ค์, HTTP/2์์๋ ํด๊ฒฐ
2. ๋ฒ๋ค๋ง ๋ ํ์ผ์ ์์ถํ๋ ๊ฒ์ด ์ฌ๋ฌ ๊ฐ์ ํ์ผ์ ์์ถํ๋ ๊ฒ๋ณด๋ค ํจ์จ์ ์ด๋ค.
3. ๋ฒ๋ค๋ง ๋์ค ์ฌ์ฉ๋์ง ์์ export๋ ์ ๊ฑฐํ ์ ์๊ณ ์ฉ๋์ ์๋นํ ์ค์ผ ์ ์๋ค. โก ์ ์ ๊ตฌ์กฐ์ ๋ชจ๋ ์์คํ ์์๋ง ์ง์
2. compact ๋ฒ๋ค๋ง, ์ปค์คํ ๋ฒ๋ค๋ง ํ์ ์์
Rollup ๋ชจ๋ ๋ฒ๋ค๋ฌ๋ ์ค๋ณต๋ ๋ณ์๋ช ์ ๋ณ๊ฒฝํ๊ณ , ESM์ ํจ์จ์ ์ผ๋ก ํ๋์ ์ค์ฝํ๋ก ํตํฉํ ์ ์๋ค๋ ๊ฑธ ๋ณด์ฌ์คฌ๋ค.
์ด๋ ์ ์ ๊ตฌ์กฐ๋ฅผ ์ง๋ ๊ธฐ ๋๋ฌธ์ ๋ฒ๋ค ํฌ๋งท์ด ์กฐ๊ฑด๋ถ์ ์ผ๋ก ๋ชจ๋์ด ๋ก๋๋๋ ์ํฉ์ ๊ณ ๋ คํ์ง ์์ ์ ์๊ณ ,
์ฝ๊ธฐ-์ ์ฉ export ๊ฐ์ import ํด์จ๋ค๋ ์ ์์ export๋ฅผ ๋ณต์ฌํ์ง ์์์ ์ง์ ์ฐธ์กฐํ ์ ์๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฅํ๋ค.
๋ค์ ์์์ Rollup์ด ๋ฒ๋ค๋ง ๊ณผ์ ์์ ์ฌ์ฉํ์ง ์์ export๋ฅผ tree shaking ํ๋ ์๋ฅผ ์ดํด๋ณด์.
๐ฅ ๋ฒ๋ค๋ง ์ด์
// lib.js
export function foo() {}
export function bar() {}
// main.js
import {foo} from './lib.js';
console.log(foo());
๐ค ๋ฒ๋ค๋ง ์ดํ : ์ฌ์ฉ๋์ง ์์ export bar๋ ์ ๊ฑฐ๋์๋ค.
function foo() {}
console.log(foo());
3. import lookup์ด ๋ ๋น ๋ฅด๋ค.
์ด์ ์ ๋ค๋ฃจ์๋ฏ์ด, CJS๋ก ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ require๋ก ๊ฐ์ ๊ฐ์ ธ์ค๋ฉด object์ ๋ฐํ๋ฐ๋๋ค.
var lib = require('lib');
lib.someFunc(); // property lookup
๋ฐ๋ผ์ ๊ฐ์ property์ ์ ๊ทผํ๊ธฐ ์ํด์๋ property lookup์ ํด์ผ ํ๋๋ฐ, ๋์ ์ผ๋ก ์ด๋ฃจ์ด์ง๊ธฐ ๋๋ฌธ์ ๋๋ฆฌ๋ค.
๋ฐ๋ฉด์ ESM๋ก ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ import ํด์ค๋ ๊ฒฝ์ฐ ์ ์ ์ผ๋ก ๋ชจ๋ ์ฝํ ์ธ ๋ฅผ ์ ์ ์๊ณ ์ต์ ํ๋ ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค.
import * as lib from 'lib';
lib.someFunc(); // statically resolved
๋ฟ๋ง ์๋๋ผ ESM๋ ๋ณ์ ์ฒดํฌ, macro ํน์ ํ์ ์ ์ฉ์ ์นํ์ ์ด๋ค๋ ์ฅ์ ๋ ์ง๋ ๋ค.
๐ฑ TAKEAWAYS
๋ชจ๋ ์์คํ ์๋ ํฌ๊ฒ ๋ ๊ฐ์ง CJS์ ESM ๊ฐ ์๋ค.
CJS๋ require์ module.exports๋ก, ESM ์ import๊ณผ export์ผ๋ก ๋ชจ๋์ ๊ฐ์ ธ์ค๊ณ ๋ด๋ณด๋ธ๋ค.
ESM์ด CJS์ ๋นํด ์ง๋ ์ด์ ๋ค์ด ์ฌ๋ฟ ์๋๋ฐ, ์ด ์ค์ tree shaking๊ณผ ์ํ dependency ์ง์์ด ์ค์ํ๋ค๊ณ ๊ผฝ์ ์ ์๋ค.
์ด๋ ESM์ด ์ ์ ๊ตฌ์กฐ๋ก ๋ฐํ์ ์ด์ ์ import๊ณผ export๋ฅผ ์ ์ ์์ด, ์ฃฝ์ ์ฝ๋๋ฅผ ์ ๊ฑฐํ๊ธฐ ์ฉ์ดํ๊ฒ ๋ฉ๋๋ค.
๋ํ ESM์ export์ ๋ณต์ฌ๋ณธ ๊ฐ์ฒด๋ฅผ import ํ๋ CJS์ ๋ฌ๋ฆฌ,
export ๊ฐ์ ์ฝ๊ธฐ ์ ์ฉ LIVE ๊ฐ์ import ํ๋ค๋ ์ ์์ ์๋์ ์ผ๋ก ์ํ dependency๋ฅผ ์ง์ํด ์ค๋ค๋ ์ ์์ ์ฅ์ ์ ์ง๋๊ณ ์์ต๋๋ค.
๐ฉ๐ป๐ปTMI
๊ธ์ด ๊ธธ์ด์ง ๊ฑฐ ๊ฐ์์ ๋ฒ๋ค๋ง ๊ด๋ จ์ ๋ค์์ ๋ค๋ค์ผ ํ ๊ฑฐ ๊ฐ๋ค.
๋ชจ๋ ์์คํ ์ ๋ํด ์ ๋ชจ๋ฅด๊ณ ๋์ด๊ฐ ๋ถ๋ถ์ ๋ณด๊ณ ๊ฐ ์ ์์๋ ์๊ฐ์ด์๋ค.
๐ References
https://www.freecodecamp.org/news/anatomy-of-js-module-systems-and-building-libraries-fadcd8dbd0e/
https://exploringjs.com/es6/ch_modules.html#static-module-structure
'๐ฉ๐ปโ๐ป dev' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
ํจํค์ง ๋งค๋์ ( ft. ํจํค์ง ๋งค๋์ ์ ๊ณผ๊ฑฐ, ํ ์ค์ ์ ํ, ๊ทธ๋ฆฌ๊ณ ๋ฏธ๋) (0) | 2024.07.08 |
---|---|
ํ ์คใ ฃSLASH 23 - ํผ๋ : ์์์ง๋ ํ์ด์ง ํ ๋ฐฉ์ ๊ด๋ฆฌํ๊ธฐ (TOSH | SLASH 23 - Funnel Pattern : Organizing an overflow of pages at once) (2) | 2024.07.05 |
โ๏ธ Error boundary (0) | 2024.06.19 |
โ๏ธ <Suspense> ํ์ฉ (0) | 2024.06.16 |
โ๏ธ <Suspense>๋? (0) | 2024.06.15 |