우테코 react-module 미션을 진행하면서 npm build
명령어 실행시 아래 사진과 같이 dist 폴더에 다양한 파일들이 생긴다. 이번에는 npm build 시 어떤 과정이 일어나는지 알아 보고 아래 파일들이 어떤 것을 의미하는 지 알아보자 🧐
빌드란, 개발자가 작성한 코드를 실행 가능한 코드로 변환하는 과정이다. 예를 들어, React 프로젝트를 만든 경우 개발자는 .jsx
, .tsx
, .css
등의 파일을 사용해 개발한다. 하지만 브라우저는 이러한 파일들을 직접 이해하거나 실행할 수 없다. 따라서 Webpack, Vite, Parcel 같은 빌드 도구를 사용하여, 브라우저가 이해하고 실행할 수 있는 정적 파일로 변환해주는 과정이 필요하다.
우리는 리액트를 개발하다 보면, npm run dev
등과 같은 명령어로 빌드 과정을 하지 않고도 리액트 앱을 실행하곤 한다. 빌드 과정을 거치지 않으면 브라우저가 이해하지 못한다고 했는데 왜 npm run dev
를 입력했을 때는 브라우저에 리액트 앱이 실행될까?
npm run dev
는 “개발 모드” 명령어다. 보통 내부적으로 Vite, Webpack Dev Server 같은 개발용 서버가 실행된다. 이 개발 서버는 개발자가 코드를 수정할 때마다 자동으로 즉시 빌드해서 브라우저에 적용해준다. 그래서 우리가 npm run build
처럼 명시적으로 번들 파일을 생성하지 않아도, 개발 중에는 실시간으로 빌드된 결과를 사용하는 것이다.
빌드에 대해 알아봤으니, 이제 빌드 과정에 대해 알아보자. 우리가 자주 사용하는 번들링 도구인 vite를 기준으로 알아보자.
1. 설정 로딩 → 2. 의존성 분석 → 3. 트랜스파일 → 4. 번들링
→ 5. 최적화 → 6. dist 폴더에 산출물 출력
vite는 위와 같은 과정으로 빌드를 수행한다.
빌드를 한 결과 .d.ts 파일이 생긴 것을 볼 수 있다. 이게 무엇일까?
.d.ts
파일은 TypeScript의 타입 선언 파일 (declaration file) 이다. JavaScript 코드에는 타입이 없기 때문에, TypeScript 사용자에게 타입 정보를 제공하기 위해 만들어진다.
해당 파일이 없으면 내 라이브러리를 다운 받고 사용하는 곳에서 props를 추론하지 못하고, 자동완성 기능을 제공하지 않는다. 그렇기 때문에 TypeScript로 만든 라이브러리의 경우 .d.ts
파일이 필요하다.
그러면 어떻게 .d.ts
를 만들까?
tsconfig.json
의 declaration: true
가 설정되어 있으면, TypeScript는 .js
파일과 함께 .d.ts
파일도 생성한다
{
"compilerOptions": {
"declaration": true,
}
}
위와 같이 설정하면, 기본적으로 모든 TypeScript 파일에 대해 .d.ts
파일을 생성한다. 하지만 export가 되어 있지 않는 코드는 타입 정의에서 빠지게 된다.
또한 tsconfig.json
의 include, exclude 설정에 따라, .d.ts
파일을 만들지 안 만들지를 결정한다.
{
"include": ["src/lib"],
"exclude": ["src/test"]
}
위와 같이 작성하면 src/lib
아래의 파일만 .d.ts
파일을 만들게 된다.
즉,
만약 둘 다 함께 설정하면 exclude가 include보다 우선 적용된다.
.d.ts
에 대해서는 알아봤다. 그러면 index.js
와 index.umd.cjs
는 무엇일까?
index.js
와 index.umd.js
는 자바스크립트 코드가 번들링된 결과물이다. 실제로 배포를 할 때는 해당 파일을 배포하여 사용자가 사용할 수 있게 한다.
결국 index.js가 실제 실행 파일이고, .d.ts 파일은 타입 선언 파일로, 라이브러리를 사용하는 쪽에서 자동 완성, 타입 추론, 타입 안전성 등을 제공한다.
빌드된 결과물이 어떤 모듈 시스템을 따르는지에 따라 구분된 파일이다.
index.js
index.umd.cjs
그렇기 때문에 두 파일을 모두 배포 해야지, 어느 환경에서든 범용적으로 사용할 수 있는 라이브러리가 된다.
하지만 그렇게 하기 위해서 아래 처럼 package.json 파일에 따로 설정해줘야 한다.
"main": "dist/index.umd.cjs", // CommonJS 환경에서 진입점이 되는 파일
"module": "dist/index.js", // ESM(ES Module) 환경의 진입점
마지막으로 번들링에 얕게 대해서 알아보자….
영어 bundle 은 묶음이라는 뜻을 가진다. 즉 파일을 번들링한다는 여러개의 파일을 하나로 묶는다는 뜻이다. 번들링은 빌드 과정중 하나로 번들링된 파일을 배포하거나 브라우저에서 실행하곤 한다.
전역 범위(global scope)
를 기본으로 했기 때문에, 스크립트 간 변수 충돌 문제가 자주 발생했다. 번들링 도구는 각 모듈을 독립적인 스코프로 감싸기 때문에, 전역 변수 충돌 없이 안전하게 파일을 분리하고 관리할 수 있다. 또한, 의존성 그래프를 분석하여 사용되는 코드만 추출(tree-shaking)하는 등의 최적화도 가능해진다.
우디 덕분에 빌드 마스터 가능할 것 같네요! 좋은데요? 👍