Production build에서 `tsc`와 `ts-node` 사용하기
목차
비교하게 된 내용 #
Node.js server를 TypeScript로 작성하면 실행하는 방법은 크게 두 가지입니다.
tsc로 TypeScript를 compile한 뒤, 생성된 JavaScript를 Node.js로 실행하기ts-node로 startup 중 TypeScript를 변환하고 실행하기
차이는 단순히 command 하나를 선택하는 데 있지 않습니다. TypeScript를 언제 변환하는지, production process에 무엇을 포함해야 하는지가 달라집니다.
tsc 사용하기 #
tsc는 tsconfig.json 설정에 따라 project를 compile합니다.
tsc -p ./
node dist/server.js
build가 끝나면 server가 시작되기 전에 JavaScript가 생성됩니다. Production image나 deployment에는 compile된 결과물과 이를 실행하는 데 필요한 runtime dependency만 포함할 수 있습니다.
TypeScript compile에 실패하면 server를 시작하기 전에 deployment를 중단할 수 있다는 점도 분명합니다. Build 단계와 server startup 단계의 경계가 나뉩니다.
ts-node 사용하기 #
ts-node는 Node.js의 module loading 과정에 연결되어 파일을 불러올 때 TypeScript를 변환합니다.
ts-node --transpile-only src/server.ts
별도의 compile command 없이 source file을 실행할 수 있어 development에서 편리합니다. 대신 runtime에 TypeScript 실행 도구와 source 설정을 함께 가지고 있어야 합니다.
--transpile-only를 사용하면 type checking을 건너뜁니다. startup 과정을 짧게 만들 수 있지만, type checking은 별도의 build나 CI 단계에서 수행해야 합니다.
Production에서의 선택 #
Production에서는 tsc로 compile한 뒤 생성된 JavaScript를 실행하는 방식을 선호합니다.
{
"scripts": {
"build": "tsc -p ./",
"start": "node dist/server.js",
"dev": "ts-node src/server.ts"
}
}
이렇게 하면 development의 편리함과 production runtime을 분리할 수 있습니다. 배포할 artifact가 무엇인지도 명확해집니다.
그렇다고 ts-node를 production에서 사용할 수 없다는 뜻은 아닙니다. deployment 환경이 runtime TypeScript 실행을 지원하고, build와 type-check를 다른 단계에서 보장한다면 선택할 수 있습니다. 중요한 것은 문제가 compile, startup 변환, application startup 중 어느 단계에서 발생했는지 구분하는 것입니다.
정리 #
tsc와 ts-node는 비슷해 보이지만 실행 시점이 다릅니다. tsc는 process가 시작되기 전에 JavaScript를 준비하고, ts-node는 Node.js가 파일을 불러올 때 TypeScript를 변환합니다.
이번에 고민한 production build에서는 tsc로 미리 만든 결과물을 사용하는 편이 deployment 경계를 이해하기 쉬웠습니다. 반대로 별도 artifact보다 짧은 development cycle이 중요하다면 ts-node가 더 편할 수 있습니다.