Skip to Content
WebTypeScriptTypeScript18. 빌드와 타입 체크 분리, 최종 점검

이번 편의 결과물: npm run build로 프로덕션 번들이 생성되고 npm run typecheck가 별도로 통과하며, dist 폴더를 브라우저에서 열어 expense-tracker의 최종 동작을 확인합니다. · 다루는 개념: vite build, tsc --noEmit 분리, 소스맵, 최종 점검

이 편에서 만드는 파일

expense-tracker/ ├── package.json ~ (build/typecheck/verify 스크립트 분리) └── vite.config.ts + (build.sourcemap 옵션)

개념 정리

vite build는 타입을 검사하지 않는다

vite build는 내부적으로 esbuild(번들링 단계)와 Rollup(최적화 단계)을 씁니다. 둘 다 파일을 빠르게 자바스크립트로 변환하는 데 집중하고, 타입이 맞는지는 확인하지 않습니다. 즉 타입 오류가 있는 코드도 vite build는 성공적으로 번들을 만들어낼 수 있습니다.

에디터에서 오류가 빨갛게 보이는 이유는 에디터가 백그라운드에서 별도로 tsc를 돌려 알려주기 때문입니다. 터미널에서 vite build만 실행하면 이 검사를 거치지 않습니다.

타입 체크를 별도 스크립트로 분리

02편에서 만든 build 스크립트는 tsc -b && vite build였습니다. 타입 검사(tsc -b)가 먼저 실행되고 통과해야만 번들링(vite build)이 이어지는 방식이라 안전하지만, 커밋 전에 타입만 빠르게 확인하고 싶을 때도 매번 번들링까지 기다려야 하고, CI에서 타입 검사·테스트·빌드를 독립된 단계로 나눠 병렬 실행하기도 어렵습니다. 이번 편에서 세 가지를 각자 실행할 수 있는 스크립트로 나눕니다.

스크립트하는 일파일을 만드는가
buildvite build — 번들링, 최적화, dist/ 생성
typechecktsc --noEmit — 타입만 검사아니오
verifytypecheck·test·build를 순서대로 실행

build에서 tsc -b를 떼어내면 vite build 혼자서는 더 이상 타입을 검사하지 않으므로, verify처럼 세 단계를 모아 실행하는 스크립트가 따로 필요합니다. verify에서 typecheck를 가장 먼저 두는 이유는 타입 오류가 가장 빠르게 드러나는 검사라서, 뒤이은 테스트·빌드에 시간을 쓰기 전에 먼저 실패를 알려주기 위해서입니다.

소스맵

번들 파일은 여러 소스 파일을 합치고 압축한 결과라 원본 코드와 모양이 다릅니다. 소스맵은 압축된 코드의 위치와 원본 파일의 줄 번호를 연결한 지도 파일입니다. 브라우저 개발자 도구가 소스맵을 읽으면 압축된 코드 대신 원본 .ts 코드 기준으로 오류 위치를 보여줍니다.

실습

1. 빌드 설정에 소스맵 켜기

// vite.config.ts import { defineConfig } from 'vite' export default defineConfig({ build: { sourcemap: true, }, })

2. package.json 스크립트 분리

기존 "build": "tsc -b && vite build"를 아래처럼 바꿉니다.

// package.json (발췌) { "scripts": { "dev": "vite", "build": "vite build", "typecheck": "tsc --noEmit", "preview": "vite preview", "test": "vitest run", "coverage": "vitest run --coverage", "verify": "npm run typecheck && npm run test && npm run build" } }

3. 분리 이후 생기는 위험 확인

이제 build에는 타입 검사가 없습니다. src/services/stats.tsmonthlySummary 안, incomeTotal을 계산하는 줄을 잠시 이렇게 바꿔봅니다.

const incomeTotal: number = '집계 실패'
npm run build
vite v8.0.0 building for production... ✓ 12 modules transformed. dist/index.html 0.42 kB dist/assets/index-a1b2c3d4.js 9.87 kB ✓ built in 412ms

타입이 완전히 틀렸는데도 빌드는 성공했습니다. build에서 tsc -b를 떼어낸 대가입니다. 이어서 타입 체크를 실행합니다.

npm run typecheck src/services/stats.ts:20:11 - error TS2322: Type 'string' is not assignable to type 'number'.

typecheck만 실패를 잡아냅니다. 방금 바꾼 줄을 원래 계산식으로 되돌립니다.

4. verify로 한 번에 확인

npm run verify
> tsc --noEmit > vitest run ✓ tests/createTransaction.test.ts (1) ✓ tests/storage.test.ts (2) ✓ tests/stats.test.ts (3) > vite build ✓ built in 398ms

5. dist 폴더와 실제 화면 확인

npm run preview
  • dist/ 폴더에 index.html, assets/index-*.js, assets/index-*.css, 그리고 .map으로 끝나는 소스맵 파일이 생성되어 있다.
  • npm run preview가 알려주는 주소를 열면 거래 추가·수정·삭제·필터·통계·예산 경고가 개발 서버와 동일하게 동작한다.
  • 브라우저 개발자 도구에서 오류를 하나 만들어 보면(예: 콘솔에서 임의 함수 호출), 스택 추적이 압축된 파일이 아니라 원본 .ts 파일 줄 번호를 가리킨다.

6. 프로젝트 최종 폴더 트리

18편까지 진행한 expense-tracker의 전체 구조입니다. 각 파일의 완전한 코드는 해당 편(괄호 안 숫자)에서 이미 작성했으므로 여기서는 다시 싣지 않습니다.

expense-tracker/ ├── index.html (02) ├── package.json (02, 13, 17, 18) ├── tsconfig.json (02, 16) ├── vite.config.ts (18) ├── vitest.config.ts (17) ├── dist/ (18, 빌드 산출물) ├── src/ │ ├── main.ts (02~16, 편마다 갱신) │ ├── style.css (02) │ ├── models/ │ │ ├── expense.ts (03, 04, 05, 06, 07, 09, 10) │ │ └── index.ts (12, 배럴·type-only export) │ ├── services/ │ │ ├── storage.ts (09) │ │ ├── stats.ts (10, 11, 14, 16) │ │ ├── createTransaction.ts (13) │ │ ├── budgetRules.ts (15, 전략 객체) │ │ └── index.ts (12, 14, 15 배럴) │ ├── ui/ │ │ ├── transactionForm.ts (12, 16) │ │ ├── transactionList.ts (12, 16) │ │ └── statsPanel.ts (12, 14, 15, 16) │ ├── lib/ │ │ ├── parsing.ts (06, 07) │ │ ├── signedAmount.ts (07) │ │ ├── arrayUtils.ts (08, sortBy·filterBy) │ │ └── dom.ts (16, getRequiredElement) │ ├── data/ │ │ └── seedTransactions.json (13) │ └── types/ │ └── date-format-lib.d.ts (13, 앰비언트 선언) └── tests/ ├── createTransaction.test.ts (17) ├── storage.test.ts (17) └── stats.test.ts (17)

직접 해보기

  1. dist/assets 안의 .js 파일을 열어 코드가 한 줄로 압축된 것을 확인하고, 같은 이름의 .map 파일이 있는지 확인해 봅니다.
  2. verify 스크립트에서 typecheckbuild의 순서를 바꿔 build를 먼저 실행하도록 고친 뒤, 타입 오류가 있는 상태에서 실행하면 무엇이 달라지는지 비교해 봅니다.

정답 보기

순서를 바꾸면 타입 오류가 있어도 build가 먼저 성공해 시간을 쓴 뒤에야 typecheck에서 실패가 드러납니다. 실패를 최대한 빨리 알고 싶다면 가장 가벼운 검사(typecheck)를 앞에 두는 편이 낫습니다.

자주 하는 실수

증상원인고치는 법
타입 오류가 있는데도 배포됨build 스크립트만 CI에 등록하고 typecheck를 빼먹음CI 파이프라인에 typecheck(또는 verify)를 반드시 포함한다
npm run dev에서는 안 보이던 오류가 배포 후 발견됨개발 중 에디터의 실시간 검사만 믿고 터미널 타입 체크를 따로 돌리지 않음커밋 전에 npm run typecheck를 습관적으로 실행한다
소스맵 파일까지 그대로 운영 서버에 배포build.sourcemap을 켠 뒤 별도 처리 없이 dist/를 통째로 올림필요하면 소스맵은 별도 저장소(오류 추적 서비스 등)에만 업로드한다

확인 문제

문제 14지선다
vite build가 타입 오류가 있는 코드도 성공적으로 번들링할 수 있는 이유는
문제 24지선다
tsc --noEmit의 역할은
문제 34지선다
verify 스크립트에서 typecheck를 test·build보다 먼저 실행하는 이유는
문제 44지선다
소스맵의 역할은

참고 자료

Last updated on