๋ชจ๋?
๊ด๋ จ๋ ์ฝ๋๋ค์ ํ๋์ ์ฝ๋ ๋จ์๋ก ์บก์ํํ ํ๋์ ํ์ผ์ ๋งํ๋ค.
CommonJS (CJS)
Require ํค์๋๋ฅผ ์ฌ์ฉํ ๋ชจ๋ ์์คํ ์ ๋งํ๋ค.
Node.js์ ๊ตฌ๋ฒ์ ์ ๋ธ๋ผ์ฐ์ ์์ ์ฃผ๋ก ์ฌ์ฉํ๋ค.
module.exports์ exports ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ๋ชจ๋์ ๋ด๋ณด๋ผ ์ ์๋ค
์์1. module.exports
// arithmetic.js
class Arithmetic {
constructor(a, b) {
this.a = a;
this.b = b;
}
add() {return this.a + this.b;}
subtract() {return this.a - this.b;}
};
module.exports = Arithmetic;
// main.js
const Arithmetic = require('./calculator.js');
const op = new Arithmetic(100,40)
op.add();
- module.exports์ ๊ฐ์ ๋ด์์ ๋ด๋ณด๋ด๋ ๋ฐฉ์
- ๊ฐ์ ํด๋์ค, ๋ณ์, ํจ์ ๋ฑ ํ๋์ ๋ ํผ๋ฐ์ค(๋ฉ๋ชจ๋ฆฌ ์ฃผ์)๋ฑ์ด ๋ค์ด๊ฐ ์ ์๋ค.
- require ํค์๋๋ module.exports์ ํ ๋นํ ๊ฐ์ ๋ฐํํ๋ค.
์์2. module.exports
// module.js
module.exports = {
name: 'junha',
age: 27
}
// main.js
const obj = require('./module.js')
obj.name // 'junha'
obj.age // 27
์์3. exports
// arithmetic.js
exports.add = (a, b) => a + b;
exports.subtract = (a, b) => a - b;
// main.js
const Arithmetic = require('./calculator.js');
Arithmetic.add(100,40)
Arithmetic.subtract(100,40)
- exports ๊ฐ์ฒด๋ module.exports ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ๋ณ์๋ค.
- exports ๊ฐ์ฒด์ ํ ๋น๋ ํ๋กํผํฐ๋ค์ ๋ชจ๋ module.exports ๊ฐ์ฒด์์ ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค.
ECMAScript Modules (ESM)
es6์์ ๊ณต์์ ์ผ๋ก ์ฑํ๋ ๋ชจ๋ ์์คํ ์ด๋ค.
Default exports, Named exports ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ๋ชจ๋์ ๋ด๋ณด๋ผ ์ ์๋ค.
์์1. Default exports
// arithmetic.js
class Arithmetic {
constructor(a, b) {
this.a = a;
this.b = b;
}
add() {return this.a + this.b;}
subtract() {return this.a - this.b;}
};
export default Arithmetic;
// main.js
import Arithmetic from './arithmetic.js'
const op = new Arithmetic(100,40)
op.add()
op.subtract()
- ํ ํ์ผ์์ ํ ๋ฒ๋ง ์ฌ์ฉํ ์ ์๊ณ , ๋ํ๋ก ๊ฐ์ ๋ด๋ณด๋ผ ๋ ์ฌ์ฉํ๋ค.
// utils.js
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
const array = [1, 2, 3];
const object = { a: 1, b: 2, c: 3 };
const obj = {
add,
subtract,
array,
object
};
export default obj;
import { add, subtract, array, object } from "./utils.js";
- import์ ์๋ฌด ์ด๋ฆ์ด๋ ์ฌ์ฉ ํ ์ ์์ผ๋ฉฐ, destructring๋ ๊ฐ๋ฅํ๋ค.
์์2. Named exports
2๊ฐ ์ด์ ๋ณ์๋ค์ ๊ฐ์ฒด์ ๋ด์ exportํ ๋ ์ฌ์ฉํ๋ค.
export const getUpload = (req, res) => res.render("upload", obj);
export const postUpload = async (req, res) => {};
import { getUpload, postUpload } from "../controllers/videoController.js";
โ import upload from "../controllers/videoController.js";
// SyntaxError: The requested module does not provide an export named 'default'
โ
import * as upload from "../controllers/videoController.js";
// as๋ฅผ ํตํด ๊ฐ์ฒด๋ก ๊ฐ์ ธ์ฌ ์ ์๋ค
default exports ๋ฐฉ์๊ณผ named exports ๋ฐฉ์์ ํจ๊ป ์ฌ์ฉํ ์ ์๋ค.
// utils.js
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
const array = [1, 2, 3];
export { subtract, array };
export default add;
// app.js ํ์ผ
import add, { subtract, array } from './utils.js';
๋ณ์๋ก ๋ฐ์ธ๋ฉ ์์ด, ๋จ์ํ ๋ชจ๋๋ง ์คํํ ๋ชฉ์ ์ด๋ฉด import๋ง ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค.
import "my-module.js";
์ฃผ์
โ export default const a = 1;
- var, const, let ํ ๋นํ๋ฉด์ ์ฌ์ฉํ ์ ์๋ค.
- ๋ธ๋ก {…} ์์์ ๋์ํ์ง ์๋๋ค.
- import, export ๋ ํ์ผ๋ด ์ต์์์ ๋ฐฐ์นํด์ผํ๋ค.
- file ํ๋กํ ์ฝ๋ก ์ด๋ํ ๊ฒฝ์ฐ
- ๋ชจ๋์ ๋ก์ปฌ ํ์ผ์์ ๋์ํ์ง ์๊ณ , HTTP ๋๋ HTTPS ํ๋กํ ์ฝ์ ํตํด์๋ง ๋์ํ๋ค.
- ๋ก์ปฌ์์ file:// ํ๋กํ ์ฝ์ ์ฌ์ฉํด ์นํ์ด์ง๋ฅผ ์ด๋ฉด import, export ์ง์์๊ฐ ๋์ํ์ง ์๋๋ค.
- ๋ธ๋ผ์ฐ์ ์์ origin์ด ์กด์ฌํ์ง ์๋ ๊ฒ์ผ๋ก ์ทจ๊ธํ๊ธฐ ๋๋ฌธ์ด๋ค.
- ๋ก์ปฌ ์น ์๋ฒ์ธ ‘๋ผ์ด๋ธ ์๋ฒ’๋ฅผ ์ฌ์ฉํ ๊ฒ!!
ESM ์ฌ์ฉํ๊ธฐ
๋ธ๋ผ์ฐ์ ์์ ์ฌ์ฉํ๋ ค๋ฉด, ๋ชจ๋์ ํด๋น๋๋ script ํ๊ทธ์ type="module"์ ์ถ๊ฐํ๋ค.
Node.js์์ ์ฌ์ฉํ๋ ค๋ฉด, package.json์ type="module"์ ์ถ๊ฐํ๋ค.
Uncaught SyntaxError: Cannot use import statement outside a module”
- commonjs ๋ฐฉ์์์ import๋ฅผ ์ฌ์ฉํ๋ ค ํ๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ ์ค๋ฅ๋ค.
- package.json์ “type” ํ๋ ๊ฐ์ “module”๋ก ์ค์ ํด์ค์ผํจ.
- ๋จ, ์ด์ ์ requre๋ก ๋ถ๋ฌ์ค๋ ๋ชจ๋์ด ์์๋ค๋ฉด import๋ก ๋ถ๋ฌ์ค๋๋ก ๋ค์ ์ ์ธํด ์ค์ผํ๋ค.
๋ธ๋ผ์ฐ์ ์์ ESM ํน์ง
- ์ง์ฐ(defer) ์คํ: ๋ค์ด๋ก๋์ ํ์ฑ์ ํ์ง๋ง, ์คํ์ ํ์ด์ง์ ํ์ฑ์ด ์๋ฃ๋ ํ์ ์ํํ๋ค.
- ์ธ๋ถ ์ค๋ฆฌ์ง(๋๋ฉ์ธ์ด๋ ํ๋กํ ์ฝ, ํฌํธ๊ฐ ๋ค๋ฅธ ์ค๋ฆฌ์ง)์์ ์คํฌ๋ฆฝํธ๋ฅผ ๋ถ๋ฌ์ค๋ ค๋ฉด CORS ํค๋๊ฐ ์์ด์ผ ํ๋ค.
- ์ค๋ณต๋ ์ธ๋ถ ์คํฌ๋ฆฝํธ๋ ๋ฌด์๋๋ค.
- ๋ ๋ฆฝ์ ์ธ ์ค์ฝํ๋ฅผ ๊ฐ๋๋ค.
- ํญ์ ์๊ฒฉ ๋ชจ๋๋ก ์คํ(use strict)๋๋ค.
- ๋ชจ๋ ๋ด ์ฝ๋๋ ๋จ ํ ๋ฒ๋ง ์คํ๋๋ค. ๋ชจ๋์ ๋ด๋ณด๋ด๋ฉด ์ด ๋ชจ๋์ ๊ฐ์ ธ์ค๊ธฐ ํ๋ ๋ชจ๋ ๋ชจ๋๊ฐ ๋ด๋ณด๋ด์ง ๋ชจ๋์ ๊ณต์ ํ๋ค.
- ๋ชจ๋ ๋ด์์ ์ ์๋ ๋ณ์, ํจ์, ํด๋์ค ๋ฑ์ ๋ชจ๋ ์ธ๋ถ์์ ์ง์ ์ ๊ทผํ ์ ์์ผ๋ฉฐ, ๊ฐ๊ฐ์ ๋ชจ๋์์ ํด๋น ๋ชจ๋์ import ํ์ฌ ๊ฐ์ ธ์์ผ ํฉ๋๋ค. ๋ชจ๋์ ํ ๋ฒ๋ง ์คํ๋๋ฉฐ, ์ดํ์ ๋ค๋ฅธ ๋ชจ๋์์ ํด๋น ๋ชจ๋์ ๊ฐ์ ธ์ฌ ๋๋ ๋ค์ ๋ค์ด๋ก๋ํ์ง ์๋๋ค.
- ์ธ๋ผ์ธ ๋ชจ๋ ์คํฌ๋ฆฝํธ๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ ํ ์ ์๋ค.
(async () => { const { someFunction } = await import('./someModule.js');})();
์ ๊น, Import๋ ๋๊ธฐ์ ํธ์ถ์ผ๊น?
JavaScript ์์ง์ ๊ตฌ๋ฌธ์ ํํ๋ฅผ ๋ณด๊ณ ์ ์ /๋์ import๋ฅผ ์๋์ผ๋ก ๊ตฌ๋ถํ์ฌ ์ฒ๋ฆฌํ๋ค.
1. ์ฒ๋ฆฌ ์์
- ๊ตฌ๋ฌธ ๋ถ์: ๋ชจ๋ import/export ์ฐพ๊ธฐ
- ๋ชจ๋ ๋ก๋ฉ: import๋ ๋ชจ๋ ๋ถ๋ฌ์ค๊ธฐ
- ๋ชจ๋ ํ๊ฐ: ์ค์ ์ฝ๋ ์คํ
2. ์ ์ Import (Static Import)
- ์ด๋ Import๋ ๋ชจ๋ ์ด๊ธฐํ ๋จ๊ณ์์ ์ฒ๋ฆฌ๋๋ค.
- ์ ์ (Static) ๊ตฌ๋ฌธ
- ์ฝ๋๊ฐ ์คํ๋๊ธฐ ์ ์ ์ฒ๋ฆฌ๋๋ ๋ฌธ๋ฒ ๊ตฌ์กฐ
- ์ปดํ์ผ/ํ์ฑ ๋จ๊ณ์์ ์ฒ๋ฆฌ๋จ
- ์์น๋ ํํ๊ฐ ๊ณ ์ ๋์ด์ผ ํจ
- ์ ์ (Static) ๊ตฌ๋ฌธ
- ์ฝ๋๊ฐ ์คํ๋๊ธฐ ์ ์ ํ๊ฐ ๋ฐ ๋ก๋๋๊ธฐ ๋๋ฌธ์ ๋๊ธฐ์ ํธ์ถ๋ก ์๊ฐํ ์ ์๋ค.
- ๋ฐ๋์ ์ต์์ ๋ ๋ฒจ์์ ์ฌ์ฉํด์ผ ํจ
import module from './module'
import { something } from './module'
import * as all from './module'
3. ๋์ Import (Dynamic Import)
- ์ด๋ Import๋ Promise๋ก ๊ฐ์ธ์ง ํด๋น ๋ชจ๋์ ๋ฐํํ๋ ๋น๋๊ธฐ ๋ฐํ์ ํจ์๋ค.
- ์ฝ๋ ์ด๋์๋ ์ฌ์ฉ ๊ฐ๋ฅ
async function someFunction() {
const module = await import('./module');
}
import('./db.js')
.then((module) => {
const db = module.default;
// ๋ชจ๋ ๋ด default export๋ก ์ ์๋ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ ์ ์์
// module.default๋ db.js ํ์ผ์์ export default๋ก ๋ด๋ณด๋ธ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํด
})
.catch((error) => {
console.error('Error loading the module:', error);
});
4. CommonJS
- require() ํจ์๋ ๋ชจ๋์ ๋๊ธฐ์ ์ผ๋ก ๋ถ๋ฌ์ค๋ฉฐ, ์ฒ์ ์คํ๋ ํ module.exports๋ฅผ ๋ฐํ. ์ดํ ๋์ผํ ๋ชจ๋์ ๋ํ ํธ์ถ์ ์บ์๋ ๊ฐ์ ๋ฐํํ๋ค.
CJS vs ESM
1. CJS๋ ๊ธฐ๋ณธ ๊ฐ์ด๋ค. ์๋๋ฉด ESM์ ๋ฐ๋๊ฒ ๋ ๋ง์์
๊ธฐ๋ณธ ๊ฐ์ผ๋ก use strict๊ฐ ์ค์ ๋์ด ์์ด์ผํ๊ณ , this๋ global object๋ฅผ ์ฐธ์กฐํ์ง ์๊ณ , ์ค์ฝํ๋ ๋ค๋ฅด๊ฒ ์๋ ๋๋ ๋ฑ๋ฑ ๋ณํ๊ฐ ๋ง๋ค. ๋ธ๋ผ์ฐ์ ์์ ์กฐ์ฐจ <script>๊ฐ ESM์ ๊ธฐ๋ณธ์ผ๋ก ์ง์ ํ์ง ์๋ ์ด์ ๋ค. ESM์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ type="module"์ ์ถ๊ฐํด ์ฃผ์ด์ผ ํ๋ค. ๊ธฐ๋ณธ ๊ฐ์ CJS์์ ESM์ผ๋ก ๋ฐ๊พธ๋ ๊ฒ์ ํธํ์ฑ์ ํด์น๋ ๋ฌธ์ ๊ฐ ๋๋ค. (node์ ๋์์ผ๋ก ์ฃผ๋ชฉ๋ฐ๊ณ ์๋ deno๋ ESM์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ฌ์ฉํ์ง๋ง, ๊ฒฐ๊ณผ์ ์ผ๋ก ๋ชจ๋ ์ํ๊ณ๋ฅผ ์ฒ์๋ถํฐ ๋ค์ ์ค๊ณํด์ผ ํ๋ค.)
2. ESM๊ณผ CJS๋ ์์ ํ ๋ค๋ฅด๋ค.
CommonJS์์๋ require()๋ ๋๊ธฐ๋ก ์ด๋ฃจ์ด์ง๋ค. ๋ฐ๋ผ์ promise๋ ์ฝ๋ฐฑ ํธ์ถ์ ๋ฆฌํดํ์ง ์๋๋ค. require()๋ ๋์คํฌ๋ก ๋ถํฐ ์ฝ์ด์ (๋คํธ์ํฌ ์ผ์๋ ์๋ค) ๊ทธ ์ฆ์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๋ค. ๋ฐ๋ผ์ ์ค์ค๋ก I/O๋ ๋ถ์ํจ๊ณผ (side effect)๋ฅผ ์คํํ๊ณ module.exports์ ์ค์ ๋์ด ์๋ ๊ฐ์ ๋ฆฌํดํ๋ค.
๋ฐ๋ฉด์ ESM์ ๋ชจ๋ ๋ก๋๋ฅผ ๋น๋๊ธฐ ํ๊ฒฝ์์ ์คํํ๋ค. ๋จผ์ ๊ฐ์ ธ์จ ์คํฌ๋ฆฝํธ๋ฅผ ๋ฐ๋ก ์คํํ์ง ์๊ณ , import์ export๊ตฌ๋ฌธ์ ์ฐพ์์ ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฑํ๋ค. ํ์ฑ ๋จ๊ณ์์, ์ค์ ๋ก ESM ๋ก๋๋ ์ข ์์ฑ์ด ์๋ ์ฝ๋๋ฅผ ์คํํ์ง ์๊ณ ๋๋, named imports์ ์๋ ์คํ๋ฅผ ๊ฐ์งํ์ฌ ์๋ฌ๋ฅผ ๋ฐ์์ํฌ ์ ์๋ค.
๊ทธ ๋ค์ ESM ๋ชจ๋ ๋ก๋๋ ๊ฐ์ ธ์จ ์คํฌ๋ฆฝํธ๋ฅผ ๋น๋๊ธฐ๋ก ๋ค์ด๋ก๋ ํ์ฌ ํ์ฑํ๋ค์, import๋ ์คํฌ๋ฆฝํธ๋ฅผ ๊ฐ์ ธ์ค๊ณ , ๋ ์ด์ import ํ ๊ฒ์ด ์์ด์ง ๋๊น์ง import๋ฅผ ์ฐพ์ ๋ค์ dependencies์ ๋ชจ๋ ๊ทธ๋ํ๋ฅผ ๋ง๋ค์ด ๋ธ๋ค. ๊ทธ๋ฆฌ๊ณ , ์คํฌ๋ฆฝํธ๋ ์คํ๋ ์ค๋น๋ฅผ ๋ง์น๊ฒ ๋๋ฉฐ, ๊ทธ ์คํฌ๋ฆฝํธ์ ์์กดํ๊ณ ์๋ ์คํฌ๋ฆฝํธ๋ค๋ ์คํํ ์ค๋น๋ฅผ ๋ง์น๊ฒ ๋๊ณ , ๋ง์นจ๋ด ์คํ๋๋ค. ESM ๋ชจ๋ ๋ด์ ๋ชจ๋ ์์ ์คํฌ๋ฆฝํธ๋ค์ ๋ณ๋ ฌ๋ก ๋ค์ด๋ก๋ ๋์ง๋ง, ์คํ์ ์์ฐจ์ ์ผ๋ก ์งํ๋๋ค.
3. export default๋ฅผ ํผํด์ผ ํ๋ ๋ ๊ฐ์ง ์ด์
export default ๋ฌธ๋ฒ์ ์๋ ๊ธฐ์กด์ CommonJS ๋ชจ๋ ์์คํ ๊ณผ ํธํ์ฑ์ ์ ์งํ๊ธฐ ์ํด ๋ง๋ค์ด์ก๋ค. ๊ทธ๋ฌ๋ named exports์๋ ๋ค๋ฅด๊ฒ, importํ๋ ๊ณณ์์ ์ด๋ฆ์ ์์ ์์ฌ๋ก ์ ํ ์ ์๋ค. ๋๋ฌธ์ 1. ๊ฐ์ ๋ชจ๋์ด๋๋ผ๋ ์ฌ์ฉ์ฒ์ ๋ฐ๋ผ ์ด๋ฆ์ด ๋ฌ๋ผ์ ธ, 1. ํฐ ๊ท๋ชจ์ ๋ฆฌํฉํ ๋ง์ ์ด๋ ต๊ฒ ๋ง๋ ๋ค. ๋ฐ๋ฉด named exports๋ export ๋๋ ๊ฐ๋ค์ ์ด๋ฆ์ ๋ถ์ฌํ๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ์ฌ์ฉ์ฒ์์ ๋์ผํ ์ด๋ฆ์ ์ฌ์ฉํด IDE๊ฐ ์ด๋ฅผ ์ฐพ์์ ์๋์ผ๋ก import๋ฅผ ๋์์ค ์ ์์ด ์ด๋ฌํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์๋๋ค.
2. tree-shaking์ ํตํด ๋ฒ๋ค ์ฌ์ด์ฆ๋ฅผ ์ค์ผ ์ ์๋ค. ์๋ฅผ ๋ค์ด, ํ๋์ ๊ฑฐ๋ํ ๊ฐ์ฒด๋ฅผ default๋ก ํ๋ฒ์ exportํ๋ ๊ฒฝ์ฐ์๋ tree-shaking์ ํ ์ ์๋ค. ํ์ง๋ง named exports๋ก ๊ฐ์ ํ๋์ฉ export ํด์ฃผ๋ฉด ์ฌ์ฉํ์ง ์๋ ๊ฐ๋ค์ tree-shaking์ ํตํด ๋ฒ๋ค ์ฌ์ด์ฆ๋ฅผ ์ค์ผ ์ ์๋ค. ES Modules๋ก ์์ฑ๋ ๋ชจ๋์ ๊ฒฝ์ฐ์๋ tree-shaking์ ํ ์ ์์ง๋ง, CommonJS ๋ชจ๋๋ก ์์ฑ๋ ๋ชจ๋์ ๊ฒฝ์ฐ์๋ tree-shaking์ ํ ์ ์๋ค.
// 1. Tree-shaking ์ ๋๋ ๊ฒฝ์ฐ๋ค
// math.js
export default function add(a, b) { return a + b } // default export๋ OK
export const subtract = (a, b) => a - b // named export๋ OK
// 2. Tree-shaking ์ ๋๋ ๊ฒฝ์ฐ
// utils.js
export default {
add: (a, b) => a + b,
subtract: (a, b) => a - b,
multiply: (a, b) => a * b,
// ํ๋๋ง ์จ๋ ๋ชจ๋ ํจ์๊ฐ ๋ฒ๋ค์ ํฌํจ๋จ!
}
// main.js
import { add } from './utils' // multiply, subtract๋ ํจ๊ป ๋ฒ๋ค๋ง๋จ
// ๊ทธ์ destructring ํ ๊ฒ์ผ ๋ฟ์ด๋ค
default export ์์ฒด๊ฐ ๋ฌธ์ ๋ผ๊ธฐ ๋ณด๋ค๋, ๊ฐ์ฒด๋ก ๋ฌถ์ด์ exportํ๋ฉด tree-shaking์ด ์๋๋ค๋ ์ ์ ๋ช ์ฌํ์.