MSBuild에서의 컴파일러 옵션
MSBuild에서의 컴파일러 옵션 (Compiler Options in MSBuild)
MSBuild 기반 프로젝트(예: ASP.NET Core 프로젝트)에서 TypeScript를 쓸 때는 설정을 tsconfig.json으로 할지, 프로젝트 설정으로 할지 두 가지 방법이 있어요. 어떤 방식이 언제 어울리는지, 그리고 프로젝트 파일에서 어떤 옵션을 쓸 수 있는지 함께 살펴볼게요.
개요 (Overview)
ASP.NET Core 프로젝트처럼 TypeScript를 활용하는 MSBuild 기반 프로젝트가 있을 때, TypeScript를 두 가지 방식으로 구성할 수 있어요. tsconfig.json을 통하거나, 프로젝트 설정을 통하는 방식이죠.
tsconfig.json 사용하기
가능하면 프로젝트에 tsconfig.json을 사용하는 것을 권장합니다. 기존 프로젝트에 추가하려면, 최신 버전의 Visual Studio에서 "TypeScript JSON Configuration File"이라고 불리는 새 항목을 프로젝트에 추가하세요.
새 tsconfig.json은 그다음부터 파일과 설정 같은 TypeScript 고유의 빌드 정보에 대한 진실의 원천(source of truth)으로 사용될 거예요. TSConfig가 어떻게 동작하는지 여기서 배울 수 있고, 포괄적인 참조는 여기 있습니다.
프로젝트 설정 사용하기
TypeScript 설정을 프로젝트의 설정 안에서 정의할 수도 있어요. 이는 .csproj의 XML을 편집해 빌드가 어떻게 동작할지 설명하는 PropertyGroup들을 정의하는 방식으로 이루어집니다.
<PropertyGroup>
<TypeScriptNoEmitOnError>true</TypeScriptNoEmitOnError>
<TypeScriptNoImplicitReturns>true</TypeScriptNoImplicitReturns>
</PropertyGroup>
흔한 TypeScript 설정에 대한 일련의 매핑이 있어요. 이 설정들은 TypeScript CLI 옵션에 직접 대응하며, 더 이해하기 쉬운 프로젝트 파일을 작성하는 데 도움을 줍니다. 각 매핑의 값과 기본값에 대한 더 많은 정보는 TSConfig reference를 사용할 수 있어요.
CLI 매핑 (CLI Mappings)
| MSBuild Config Name | TSC Flag | |
|---|---|---|
<TypeScriptAllowJS> |
--allowJs |
|
|
JavaScript 파일이 프로그램의 일부가 되도록 허용합니다. 이 파일들에서 에러를 얻으려면 | ||
<TypeScriptRemoveComments> |
--removeComments |
|
|
주석 출력을 비활성화합니다. | ||
<TypeScriptNoImplicitAny> |
--noImplicitAny |
|
|
암시된 | ||
<TypeScriptGeneratesDeclarations> |
--declaration |
|
|
프로젝트의 TypeScript 및 JavaScript 파일로부터 .d.ts 파일을 생성합니다. | ||
<TypeScriptModuleKind> |
--module |
|
|
어떤 모듈 코드가 생성되는지 지정합니다. | ||
<TypeScriptJSXEmit> |
--jsx |
|
|
어떤 JSX 코드가 생성되는지 지정합니다. | ||
<TypeScriptOutDir> |
--outDir |
|
|
모든 출력 파일을 위한 출력 폴더를 지정합니다. | ||
<TypeScriptSourceMap> |
--sourcemap |
|
|
출력된 JavaScript 파일을 위한 소스 맵 파일을 생성합니다. | ||
<TypeScriptTarget> |
--target |
|
|
출력되는 JavaScript의 JavaScript 언어 버전을 설정하고 호환되는 라이브러리 선언을 포함합니다. | ||
<TypeScriptNoResolve> |
--noResolve |
|
|
| ||
<TypeScriptMapRoot> |
--mapRoot |
|
|
디버거가 생성된 위치 대신 맵 파일을 찾을 위치를 지정합니다. | ||
<TypeScriptSourceRoot> |
--sourceRoot |
|
|
디버거가 참조 소스 코드를 찾을 루트 경로를 지정합니다. | ||
<TypeScriptCharset> |
--charset |
|
|
더 이상 지원되지 않습니다. 초기 버전에서는 파일을 읽을 텍스트 인코딩을 수동으로 설정했습니다. | ||
<TypeScriptEmitBOM> |
--emitBOM |
|
|
출력 파일의 시작 부분에 UTF-8 바이트 오더 마크(BOM)를 출력합니다. | ||
<TypeScriptNoLib> |
--noLib |
|
|
기본 lib.d.ts를 포함한 라이브러리 파일을 전부 포함하는 것을 비활성화합니다. | ||
<TypeScriptPreserveConstEnums> |
--preserveConstEnums |
|
|
생성된 코드에서 | ||
<TypeScriptSuppressImplicitAnyIndexErrors> |
--suppressImplicitAnyIndexErrors |
|
|
인덱스 시그니처가 없는 객체를 인덱싱할 때 | ||
<TypeScriptNoEmitHelpers> |
--noEmitHelpers |
|
|
컴파일 출력에서 | ||
<TypeScriptInlineSourceMap> |
--inlineSourceMap |
|
|
출력된 JavaScript 안에 소스맵 파일을 포함합니다. | ||
<TypeScriptInlineSources> |
--inlineSources |
|
|
출력된 JavaScript 안의 소스맵에 소스 코드를 포함합니다. | ||
<TypeScriptNewLine> |
--newLine |
|
|
파일 출력을 위한 줄바꿈 문자를 설정합니다. | ||
<TypeScriptIsolatedModules> |
--isolatedModules |
|
|
각 파일이 다른 import에 의존하지 않고 안전하게 트랜스파일될 수 있도록 보장합니다. | ||
<TypeScriptEmitDecoratorMetadata> |
--emitDecoratorMetadata |
|
|
소스 파일의 데코레이트된 선언에 대한 design-type 메타데이터를 출력합니다. | ||
<TypeScriptRootDir> |
--rootDir |
|
|
소스 파일 안의 루트 폴더를 지정합니다. | ||
<TypeScriptExperimentalDecorators> |
--experimentalDecorators |
|
|
TC39 stage 2 초안 데코레이터에 대한 실험적 지원을 활성화합니다. | ||
<TypeScriptModuleResolution> |
--moduleResolution |
|
|
TypeScript가 주어진 모듈 스펙시파이어에서 파일을 어떻게 찾는지 지정합니다. | ||
<TypeScriptSuppressExcessPropertyErrors> |
--suppressExcessPropertyErrors |
|
|
객체 리터럴 생성 중 초과 프로퍼티 에러 보고를 비활성화합니다. | ||
<TypeScriptReactNamespace> |
--reactNamespace |
|
|
| ||
<TypeScriptSkipDefaultLibCheck> |
--skipDefaultLibCheck |
|
|
TypeScript에 포함된 .d.ts 파일의 타입 검사를 건너뜁니다. | ||
<TypeScriptAllowUnusedLabels> |
--allowUnusedLabels |
|
|
사용되지 않는 레이블에 대한 에러 보고를 비활성화합니다. | ||
<TypeScriptNoImplicitReturns> |
--noImplicitReturns |
|
|
함수에서 명시적으로 반환하지 않는 코드 경로에 대한 에러 보고를 활성화합니다. | ||
<TypeScriptNoFallthroughCasesInSwitch> |
--noFallthroughCasesInSwitch |
|
|
switch문에서 빠져나가는(fallthrough) 경우에 대한 에러 보고를 활성화합니다. | ||
<TypeScriptAllowUnreachableCode> |
--allowUnreachableCode |
|
|
도달 불가능한 코드에 대한 에러 보고를 비활성화합니다. | ||
<TypeScriptForceConsistentCasingInFileNames> |
--forceConsistentCasingInFileNames |
|
|
import의 대소문자가 올바른지 보장합니다. | ||
<TypeScriptAllowSyntheticDefaultImports> |
--allowSyntheticDefaultImports |
|
|
모듈에 기본 export가 없을 때 'import x from y'를 허용합니다. | ||
<TypeScriptNoImplicitUseStrict> |
--noImplicitUseStrict |
|
|
출력된 JavaScript 파일에 'use strict' 지시문을 추가하는 것을 비활성화합니다. | ||
<TypeScriptLib> |
--lib |
|
|
대상 런타임 환경을 설명하는 번들 라이브러리 선언 파일 집합을 지정합니다. | ||
<TypeScriptBaseUrl> |
--baseUrl |
|
|
베어 스펙시파이어(bare specifier) 모듈 이름을 해석할 기준 디렉터리를 지정합니다. | ||
<TypeScriptDeclarationDir> |
--declarationDir |
|
|
생성된 선언 파일의 출력 디렉터리를 지정합니다. | ||
<TypeScriptNoImplicitThis> |
--noImplicitThis |
|
|
| ||
<TypeScriptSkipLibCheck> |
--skipLibCheck |
|
|
모든 .d.ts 파일의 타입 검사를 건너뜁니다. | ||
<TypeScriptStrictNullChecks> |
--strictNullChecks |
|
|
타입 검사 시 | ||
<TypeScriptNoUnusedLocals> |
--noUnusedLocals |
|
|
지역 변수가 읽히지 않을 때 에러 보고를 활성화합니다. | ||
<TypeScriptNoUnusedParameters> |
--noUnusedParameters |
|
|
함수 파라미터가 읽히지 않을 때 에러를 냅니다. | ||
<TypeScriptAlwaysStrict> |
--alwaysStrict |
|
|
'use strict'가 항상 출력되도록 합니다. | ||
<TypeScriptImportHelpers> |
--importHelpers |
|
|
파일별로 포함하는 대신, 프로젝트당 한 번 tslib에서 헬퍼 함수를 가져오는 것을 허용합니다. | ||
<TypeScriptJSXFactory> |
--jsxFactory |
|
|
React JSX 출력을 대상으로 할 때 사용할 JSX 팩토리 함수를 지정합니다. 예: 'React.createElement' 또는 'h' | ||
<TypeScriptStripInternal> |
--stripInternal |
|
|
JSDoc 주석에 | ||
<TypeScriptCheckJs> |
--checkJs |
|
|
타입 검사되는 JavaScript 파일에서 에러 보고를 활성화합니다. | ||
<TypeScriptDownlevelIteration> |
--downlevelIteration |
|
|
반복(iteration)에 대해 더 규격을 준수하지만 장황하고 성능이 낮은 JavaScript를 출력합니다. | ||
<TypeScriptStrict> |
--strict |
|
|
모든 엄격 타입 검사 옵션을 활성화합니다. | ||
<TypeScriptNoStrictGenericChecks> |
--noStrictGenericChecks |
|
|
함수 타입에서 제네릭 시그니처의 엄격한 검사를 비활성화합니다. | ||
<TypeScriptPreserveSymlinks> |
--preserveSymlinks |
|
|
심볼릭 링크를 실제 경로(realpath)로 해석하는 것을 비활성화합니다. node의 같은 이름 플래그와 대응됩니다. | ||
<TypeScriptStrictFunctionTypes> |
--strictFunctionTypes |
|
|
함수를 할당할 때 파라미터와 반환 값이 서브타입 호환인지 확인합니다. | ||
<TypeScriptStrictPropertyInitialization> |
--strictPropertyInitialization |
|
|
선언되었지만 생성자에서 설정되지 않은 클래스 프로퍼티를 검사합니다. | ||
<TypeScriptESModuleInterop> |
--esModuleInterop |
|
|
CommonJS 모듈 가져오기 지원을 쉽게 하기 위해 추가 JavaScript를 출력합니다. 이는 타입 호환을 위해 | ||
<TypeScriptEmitDeclarationOnly> |
--emitDeclarationOnly |
|
|
JavaScript 파일이 아닌 d.ts 파일만 출력합니다. | ||
<TypeScriptKeyofStringsOnly> |
--keyofStringsOnly |
|
|
keyof가 문자열, 숫자, 심볼이 아닌 오직 문자열만 반환하게 합니다. 레거시 옵션입니다. | ||
<TypeScriptUseDefineForClassFields> |
--useDefineForClassFields |
|
|
ECMAScript 표준을 준수하는 클래스 필드를 출력합니다. | ||
<TypeScriptDeclarationMap> |
--declarationMap |
|
|
d.ts 파일용 소스맵(sourcemaps)을 생성합니다. | ||
<TypeScriptResolveJsonModule> |
--resolveJsonModule |
|
|
.json 파일 가져오기를 활성화합니다. | ||
<TypeScriptStrictBindCallApply> |
--strictBindCallApply |
|
|
| ||
<TypeScriptNoEmitOnError> |
--noEmitOnError |
|
|
타입 검사 에러가 보고되면 파일 출력을 비활성화합니다. | ||
추가 플래그 (Additional Flags)
MSBuild 시스템이 인자를 TypeScript CLI에 직접 전달하므로, 위의 매핑에 없는 특정 플래그를 제공하기 위해 TypeScriptAdditionalFlags 옵션을 사용할 수 있어요.
예를 들어, 다음은 noPropertyAccessFromIndexSignature를 켭니다.
<TypeScriptAdditionalFlags> $(TypeScriptAdditionalFlags) --noPropertyAccessFromIndexSignature</TypeScriptAdditionalFlags>
디버그/릴리스 빌드 (Debug and Release Builds)
PropertyGroup 조건(condition)을 사용해 서로 다른 설정 집합을 정의할 수 있어요. 예를 들어, 운영(production)에서는 주석과 소스맵을 제거하는 것이 흔한 작업이에요. 이 예시에서는 서로 다른 TypeScript 설정을 가진 디버그/릴리스 프로퍼티 그룹을 정의합니다.
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<TypeScriptRemoveComments>false</TypeScriptRemoveComments>
<TypeScriptSourceMap>true</TypeScriptSourceMap>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<TypeScriptRemoveComments>true</TypeScriptRemoveComments>
<TypeScriptSourceMap>false</TypeScriptSourceMap>
</PropertyGroup>
<Import
Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets"
Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets')" />
ToolsVersion
프로젝트 파일의 <TypeScriptToolsVersion>1.7</TypeScriptToolsVersion> 프로퍼티 값은 빌드에 사용할 컴파일러 버전을 식별합니다(이 예시에서는 1.7). 이를 통해 서로 다른 머신에서 같은 버전의 컴파일러로 프로젝트를 빌드할 수 있어요.
TypeScriptToolsVersion을 지정하지 않으면, 머신에 설치된 최신 컴파일러 버전으로 빌드할 거예요.
더 새로운 버전의 TS를 사용하는 사용자는 첫 로드 시 프로젝트를 업그레이드하라는 프롬프트를 볼 거예요.
TypeScriptCompileBlocked
다른 빌드 도구(예: gulp, grunt 등)로 프로젝트를 빌드하고, 개발과 디버깅 경험에는 VS를 사용한다면, 프로젝트에 <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>를 설정하세요. 이러면 모든 편집 지원은 그대로 받되, F5를 눌렀을 때 빌드는 하지 않아요.
TypeScriptEnableIncrementalMSBuild (TypeScript 4.2 Beta 이상)
기본적으로 MSBuild는 프로젝트의 소스 파일이 마지막 컴파일 이후 갱신된 경우에만 TypeScript 컴파일러를 실행하려고 시도합니다. 하지만 이 동작이 문제를 일으키는 경우, 예를 들어 TypeScript의 incremental 옵션이 활성화되어 있을 때는, <TypeScriptEnableIncrementalMSBuild>false</TypeScriptEnableIncrementalMSBuild>를 설정해 MSBuild가 실행될 때마다 TypeScript 컴파일러가 호출되도록 하세요.
더 알아보기 (Learn more)
- Compiler Options에서 각 플래그의 자세한 설명을 확인하세요.
- TSConfig Reference에서 각 옵션의 값과 기본값을 살펴보세요.
tsconfig.json사용법을 다시 복습해 보세요.