개발새발
다양한 모듈 형식으로 js 파일 생성하기 본문
TypeScript를 사용하면 .ts 파일로 작성한 코드를 다양한 모듈 형식의 JavaScript 파일로 컴파일할 수 있다. 기본적으로 tsconfig.json을 설정하지 않으면 CommonJS 형식으로 변환되며, 이 설정을 수정하면 ECMAScript, UMD 등의 다른 형식으로도 출력할 수 있다.
본 글에서는 동일한 test.ts 파일을 CommonJS, ECMAScript, UMD 형식으로 각각 변환하면서 어떤 차이가 발생하는지 자세히 살펴보려고 한다.
기본 설정: CommonJS
1. test.ts 코드 예시
import axios from "axios";
(async () => {
try {
const res = await axios.get('https://jsonplaceholder.typicode.com/posts/1');
console.log(res.data.userid);
const res2 = await axios.post('https://jsonplaceholder.typicode.com/posts', {
title: 'foo',
body: 'bar',
userid: 1,
});
console.log(res2.data.id);
} catch (error) {
if (axios.isAxiosError(error)) {
console.log(error.response?.data.message);
}
}
})();
2. tsconfig.json 설정 (기본)
{
"compilerOptions": {
"target": "ES2016",
"module": "CommonJS",
"outDir": "./dist",
"esModuleInterop": true
}
}
3. 변환 결과 (CommonJS)
"use strict";
var __awaiter = ... // async/await를 지원하지 않는 target을 위한 대체 함수
var __importDefault = ... // esModuleInterop을 위한 함수
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = __importDefault(require("axios"));
(() => __awaiter(void 0, void 0, void 0, function* () {
...
}))();
- __awaiter: target이 ES2016이라 async/await가 직접 지원되지 않아 제너레이터 함수로 변환된다.
- __importDefault: esModuleInterop 옵션이 true일 경우 CommonJS 모듈에서 default를 안전하게 가져오기 위한 보조 함수이다.
- Object.defineProperty(..., "__esModule", ...): 해당 모듈이 ES 모듈 스타일로 작성되었음을 표시한다.
target을 높인 경우 (ES2022)
1. 변경된 tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "CommonJS",
"esModuleInterop": true
}
}
2. 변환 결과
"use strict";
var __importDefault = ...
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = __importDefault(require("axios"));
(async () => {
try {
const res = await axios_1.default.get(...);
...
} catch (error) {
...
}
})();
- __awaiter가 사라진다. 최신 자바스크립트 엔진에서는 async/await를 natively 지원하므로 별도 함수가 필요 없다.
ECMAScript 모듈로 변환 (ESM)
1. tsconfig.json 설정
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2015",
"moduleResolution": "node"
}
}
2. 변환 결과
import axios from "axios";
(async () => {
try {
const res = await axios.get(...);
...
} catch (error) {
...
}
})();
- CommonJS의 흔적이 사라지고 실제로 .ts와 거의 동일한 코드가 출력된다.
- 명시적인 exports, require, __importDefault, __esModule 등의 코드가 없다.
- Node.js에서는 .mjs 확장자를 사용하거나 type: "module" 설정이 필요하다.
UMD (Universal Module Definition)
1. tsconfig.json 설정
{
"compilerOptions": {
"target": "ES2022",
"module": "UMD",
"esModuleInterop": true
}
}
2. 변환 결과
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
} else if (typeof define === "function" && define.amd) {
define(["require", "exports", "axios"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = __importDefault(require("axios"));
(async () => {
...
})();
});
- CommonJS (Node.js)와 AMD (RequireJS 등) 환경 모두 호환되도록 만들어진 통합 모듈 형식이다.
- 브라우저, Node.js, CDN 환경에서도 유연하게 사용 가능하도록 설계된 구조이다.
- 최근에는 사용 빈도가 낮으며, 대부분은 ESM 또는 CommonJS를 사용한다.
결론
모듈 형식 | 특징 |
CommonJS | Node.js에서 기본 사용, require, module.exports 사용 |
ES2015 | 최신 표준 모듈 시스템, import / export 사용 |
UMD | CommonJS + AMD 통합, 광범위 호환성 |
AMD, SystemJS | 과거 사용되던 브라우저 기반 모듈 시스템 (현재는 비권장) |
타입스크립트는 다양한 런타임 환경에서의 호환성을 고려하여 모듈 형식을 유연하게 선택할 수 있도록 지원한다. 어떤 환경에서 어떤 모듈 시스템을 사용할지는 프로젝트의 목적과 배포 환경에 따라 달라진다.
부록: 추천 설정 조합
목적 | 추천 설정 |
Node.js 백엔드 개발 | module: "CommonJS" + target: "ES2022" |
브라우저 기반 프론트엔드 | module: "ES2015" + target: "ES2022" |
라이브러리 배포 (넓은 호환성) | module: "UMD" |
'Typescript' 카테고리의 다른 글
React 타입 분석하기 (1) | 2025.05.24 |
---|---|
axios의 타입을 어떻게 찾았는지 이해하기 (0) | 2025.05.17 |
Axios 직접 타이핑하기 (0) | 2025.05.15 |
Axios 타입 분석하기 (0) | 2025.05.15 |
스크립트 파일과 모듈 파일 이해하기 (0) | 2025.05.15 |