[tsconfig의 λͺ¨λ“  것] Compiler options / Emit

    [tsconfig의 λͺ¨λ“  것] Compiler options / Emit


    이번 ν¬μŠ€νŒ…μ—μ„œλŠ” μ§€λ‚œ [tsconfig의 λͺ¨λ“  것] Compiler options / Modules ν¬μŠ€νŒ…μ— 이어 tsconfig의 컴파일 μ˜΅μ…˜ 쀑 좜λ ₯ νŒŒμΌμ„ 컨트둀 ν•˜λŠ” μ˜΅μ…˜λ“€μ„ μ†Œκ°œν•  μ˜ˆμ •μ΄λ‹€.

    이 μ˜΅μ…˜λ“€μ€ νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„œλ§Œ μ§€μ›λ˜λŠ” 문법듀을 μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ μ–΄λ–»κ²Œ ν‘œν˜„ν•  것인지, ν˜Ήμ€ ES6 μ΄μƒμ˜ 문법을 ES5둜 νŠΈλžœμŠ€νŒŒμΌλ§ν•  λ•Œ μ–΄λ–»κ²Œ ν‘œν˜„ν•  것인지와 같이 νƒ€μž…μŠ€ν¬λ¦½νŠΈλ‘œ μž‘μ„±λœ μ½”λ“œλ₯Ό μ»΄νŒŒμΌν•œ 이후에 μƒμ„±λ˜λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œμ˜ λͺ¨μŠ΅μ„ κ²°μ •ν•˜λŠ” μ˜΅μ…˜λ“€μ΄λ‹€.

    λ¬Όλ‘  Babelκ³Ό 같은 νŠΈλžœμŠ€νŒŒμΌλŸ¬κ°€ μ œκ³΅ν•΄μ£ΌλŠ” κΈ°λŠ₯κ³Ό μ€‘λ³΅λ˜λŠ” 뢀뢄이 있기 λ•Œλ¬Έμ—, TSC와 Babel을 ν•¨κ»˜ μ‚¬μš©ν•˜λŠ” κ²½μš°μ—λŠ” tsconfigμ—μ„œ λͺ¨λ“  μ˜΅μ…˜μ„ μ„¬μ„Έν•˜κ²Œ 섀정해주지 μ•Šμ•„λ„ λ˜λŠ” κ²½μš°λ„ μžˆλ‹€.

    declaration

    κ°’ μ„€λͺ…
    true 컴파일 ν•  λ•Œ νƒ€μž… μ„ μ–Έ νŒŒμΌλ„ ν•¨κ»˜ μƒμ„±ν•œλ‹€
    false (default) 컴파일 ν•  λ•Œ μžλ°”μŠ€ν¬λ¦½νŠΈ νŒŒμΌλ§Œμ„ μƒμ„±ν•œλ‹€

    declaration μ˜΅μ…˜μ€ νƒ€μž…μŠ€ν¬λ¦½νŠΈμ˜ *.d.ts νŒŒμΌμ„ 내보낼지 말지λ₯Ό κ²°μ •ν•˜λŠ” μ˜΅μ…˜μ΄λ‹€. λ§Œμ•½ 기본적으둜 이 μ˜΅μ…˜μ€ 꺼져있기 λ•Œλ¬Έμ—, λ³„λ„μ˜ μ„€μ • 없이 νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό μ»΄νŒŒμΌν•˜κ²Œ 되면 *.js 파일만 λ©κ·ΈλŸ¬λ‹ˆ μƒμ„±λ˜λŠ” λͺ¨μŠ΅μ„ λ³Ό 수 μžˆλ‹€.

    // math.ts
    export const add = (x: number) => (y: number) => x + y;
    // math.js
    export var add = function (x) { return function (y) { return x + y; }; };

    ν•˜μ§€λ§Œ declaration μ˜΅μ…˜μ„ 켜게 되면, μƒμ„±λœ μžλ°”μŠ€ν¬λ¦½νŠΈ 파일 외에도 νƒ€μž… 선언을 λ‹΄κ³  μžˆλŠ” *.d.ts νŒŒμΌμ„ ν•¨κ»˜ μƒμ„±ν•˜κ²Œλœλ‹€.

    // math.d.ts
    export declare const add: (x: number) => (y: number) => number;

    λ§Œμ•½ μ—¬λŸ¬λΆ„μ΄ λ§Œλ“  λͺ¨λ“ˆμ΄ νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό μ§€μ›ν•˜λ„λ‘ ν•˜κ³  μ‹Άλ‹€λ©΄, μ‚¬μš©μžκ°€ 직접 λͺ¨λ“ˆμ˜ μ†ŒμŠ€μ½”λ“œλ₯Ό κ°€μ Έμ˜¬ 수 μžˆλ„λ‘ ν—ˆμš©ν•˜κ±°λ‚˜ μžλ°”μŠ€ν¬λ¦½νŠΈ νŒŒμΌμ„ μ œκ³΅ν•˜λ˜ νƒ€μž… μ„ μ–Έ 파일인 *.d.ts νŒŒμΌμ„ ν•¨κ»˜ μ œκ³΅ν•΄μ€˜μ•Ό ν•˜κΈ° λ•Œλ¬Έμ—, νƒ€μž…μŠ€ν¬λ¦½νŠΈ λŒ€μƒμ˜ 라이브러리λ₯Ό κ°œλ°œν•œλ‹€λ©΄ 이 μ˜΅μ…˜μ„ μ‚¬μš©ν•˜μ—¬ 컴파일 μ‹œ νƒ€μž… μ„ μ–Έ νŒŒμΌκΉŒμ§€ ν•¨κ»˜ μƒμ„±ν•˜λŠ” 것을 μΆ”μ²œν•œλ‹€.

    declarationDir

    νƒ€μž… μ„€λͺ…
    string νƒ€μž… μ„ μ–Έ νŒŒμΌμ„ 내보낼 λ””λ ‰ν† λ¦¬μ˜ 경둜

    declarationDir μ˜΅μ…˜μ€ 이름 κ·ΈλŒ€λ‘œ νƒ€μž… μ„ μ–Έ νŒŒμΌμ„ 내보낼 경둜λ₯Ό μ„€μ •ν•  수 μžˆλŠ” μ˜΅μ…˜μ΄λ‹€. μ΄λ•Œ .κ°€ μ˜λ―Έν•˜λŠ” ν˜„μž¬ κ²½λ‘œλŠ” tsconfig 파일이 μœ„μΉ˜ν•œ 곳을 μ˜λ―Έν•˜κΈ° λ•Œλ¬Έμ—, λ§Œμ•½ 컴파일된 νŒŒμΌλ“€μ΄ μœ„μΉ˜ν•œ 디렉토리 μ•ˆ μͺ½μ— νƒ€μž… μ„ μ–Έ νŒŒμΌμ„ 내보내고 μ‹Άλ‹€λ©΄ ./types와 같은 κ²½λ‘œκ°€ μ•„λ‹Œ, ./{outDir}/types와 같이 디렉토리λ₯Ό 직접 μ§€μ •ν•΄μ€˜μ•Ό ν•œλ‹€.

    λ§Œμ•½ declarationDir μ˜΅μ…˜μ„ λ³„λ„λ‘œ 섀정해주지 μ•ŠλŠ”λ‹€λ©΄ νƒ€μž… μ„ μ–Έ νŒŒμΌμ€ μžμ‹ μ˜ 원본 μžλ°”μŠ€ν¬λ¦½νŠΈ 파일과 λ™μΌν•œ μœ„μΉ˜μ— μƒμ„±λœλ‹€.

    declarationDir μ˜΅μ…˜μ„ μ„€μ •ν•˜μ§€ μ•Šμ€ 경우
    
    myProject
    β”œβ”€β”€ math.ts
    β”œβ”€β”€ dist
    β”‚   β”œβ”€β”€ math.d.ts <
    β”‚   └── math.js
    └── tsconfig.json
    declarationDir μ˜΅μ…˜μ„ "./dist/types"둜 μ„€μ •ν•œ 경우
    
    myProject
    β”œβ”€β”€ math.ts
    β”œβ”€β”€ dist
    β”‚   β”œβ”€β”€ math.js
    β”‚   └── types
    β”‚       └── math.d.ts <
    └── tsconfig.json

    μ΄λ ‡κ²Œ ν•˜λ‚˜μ˜ 디렉토리에 νƒ€μž… μ„ μ–Έ νŒŒμΌμ„ λͺ¨μ•„λ‘κ²Œ 되면 μΆ”ν›„ package.json의 types ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•˜μ—¬ νŽΈν•˜κ²Œ ν•΄λ‹Ή νŒ¨ν‚€μ§€μ˜ νƒ€μž… μ„ μ–Έ νŒŒμΌλ“€μ˜ μœ„μΉ˜λ₯Ό 지정할 수 μžˆμœΌλ―€λ‘œ ν•„μžλŠ” declarationDir μ˜΅μ…˜μ„ μ‚¬μš©ν•˜μ—¬ νƒ€μž… 선언을 ν•œ 곳에 λͺ¨μ•„λ‘λŠ” νŽΈμ΄λ‹€.

    declarationMap

    κ°’ μ„€λͺ…
    true νƒ€μž… μ„ μ–Έκ³Ό μ†ŒμŠ€ μ½”λ“œλ₯Ό μ—°κ²°ν•˜λŠ” 맀핑 νŒŒμΌμ„ μƒμ„±ν•œλ‹€
    false (default) 맀핑 νŒŒμΌμ„ μƒμ„±ν•˜μ§€ μ•ŠλŠ”λ‹€

    declarationMap μ˜΅μ…˜μ€ κ°œλ°œμžκ°€ IDEμ—μ„œ μ œκ³΅ν•˜λŠ” β€œGo to Definition” 같은 λ„€λΉ„κ²Œμ΄μ…˜ κΈ°λŠ₯을 톡해 원본 μ†ŒμŠ€ 파일둜 이동할 수 μžˆλ„λ‘ λ„μ™€μ£ΌλŠ” 맡핑 νŒŒμΌμ„ ν•¨κ»˜ 생성할 것인지에 λŒ€ν•œ μ—¬λΆ€λ₯Ό κ²°μ •ν•œλ‹€.

    μ•žμ„œ μ•Œμ•„λ³΄μ•˜λ“―μ΄ declaration μ˜΅μ…˜μ„ μ‚¬μš©ν•˜μ—¬ νƒ€μž… μ„ μ–Έ νŒŒμΌμ„ μƒμ„±ν•˜κ²Œ 되면 λ‹€μŒκ³Ό 같은 결과물이 μ»΄νŒŒμΌλœλ‹€.

    // math.ts (원본 μ†ŒμŠ€ 파일)
    export const add = (x: number) => (y: number) => x + y;
    // math.js (μžλ°”μŠ€ν¬λ¦½νŠΈ)
    export var add = function (x) { return function (y) { return x + y; }; };
    // math.d.ts (νƒ€μž… μ„ μ–Έ)
    export declare const add: (x: number) => (y: number) => number;

    μ΄λ•Œ μ‹€μ œλ‘œ μ‹€ν–‰λ˜λŠ” μ½”λ“œλ₯Ό λ‹΄κ³  μžˆλŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œμ™€ νƒ€μž… 선언을 λ‹΄κ³  μžˆλŠ” νƒ€μž… μ„ μ–Έ 파일의 μ—°κ΄€ 관계λ₯Ό μ •μ˜ν•œ 맀핑 파일이 μ—†λ‹€λ©΄, IDEμ—μ„œ λ„€λΉ„κ²Œμ΄νŒ… κΈ°λŠ₯을 μ‚¬μš©ν–ˆμ„ λ•Œ μ†ŒμŠ€ μ½”λ“œκ°€ μ•„λ‹Œ, math.d.ts 파일의 νƒ€μž… μ„ μ–ΈμœΌλ‘œ μ΄λ™ν•˜κ²Œ λœλ‹€.

    ν•˜μ§€λ§Œ μ–΄μ°¨ν”Ό 개발자 μžμ‹ μ˜ μ†ŒμŠ€ μ½”λ“œμ—λ„ νƒ€μž… 선언에 λŒ€ν•œ μ •λ³΄λŠ” λ‹€ λ…ΈμΆœλ˜κ³  있기 λ•Œλ¬Έμ—, λ„€λΉ„κ²Œμ΄νŒ…μ„ μ‚¬μš©ν•˜λŠ” κ²½μš°λŠ” νƒ€μž… μ„ μ–Έ μ •μ˜λ₯Ό μ•Œκ³  μ‹Άλ‹€κΈ° λ³΄λ‹€λŠ” μ‹€μ œλ‘œ ν•¨μˆ˜μ˜ λ‚΄λΆ€ κ΅¬ν˜„μ„ 보고 싢은 κ²½μš°κ°€ λŒ€λΆ€λΆ„μΌ 것이닀.

    이런 μƒν™©μ—μ„œ declarationMap μ˜΅μ…˜μ„ μ‚¬μš©ν•˜λ©΄ κ°œλ°œμžκ°€ λ„€λΉ„κ²Œμ΄νŒ… κΈ°λŠ₯을 μ‚¬μš©ν–ˆμ„ λ•Œ νƒ€μž… 선언이 μ•„λ‹Œ μ†ŒμŠ€ μ½”λ“œλ‘œ 이동할 수 μžˆλ„λ‘ λ³„λ„μ˜ 맀핑 νŒŒμΌμ„ ν•¨κ»˜ 생성해쀄 수 μžˆλ‹€.

    // math.d.ts (νƒ€μž… μ„ μ–Έ)
    
    export declare const add: (x: number) => (y: number) => number;
    //# sourceMappingURL=math.d.ts.map
    // math.d.ts.map
    {
      "version":3,
      "file":"math.d.ts",
      "sourceRoot":"",
      "sources":["../../../utils/math.ts"],
      "names":[],
      "mappings":"AAAA,eAAO,MAAM,GAAG,MAAO,MAAM,SAAS,MAAM,WAAU,CAAC"
    }

    맀핑 νŒŒμΌμ€ JSON 포맷으둜 κ΅¬μ„±λ˜μ–΄ 있으며, νƒ€μž… 선언이 μ •μ˜λœ 파일과 같은 κ²½λ‘œμ— μƒμ„±λœλ‹€. 이 맀핑 νŒŒμΌμ€ 원본 μ†ŒμŠ€ μ½”λ“œμ˜ 경둜λ₯Ό 가지고 있기 λ•Œλ¬Έμ—, IDE의 λ„€λΉ„κ²Œμ΄νŒ… κΈ°λŠ₯을 μ‚¬μš©ν–ˆμ„ λ•Œ β€œμ†ŒμŠ€μ½”λ“œλŠ” μ—¬κΈ°κ°€ μ•„λ‹ˆλΌ 이 κ²½λ‘œμ— μžˆμŒβ€μ΄λΌκ³  μ•Œλ €μ€„ 수 μžˆλŠ” 것이닀.

    즉, 이 κΈ°λŠ₯을 100% ν™œμš©ν•˜κ³  μ‹Άλ‹€λ©΄ npm λ ˆμ§€μŠ€νŠΈλ¦¬μ— λͺ¨λ“ˆμ„ 배포할 λ•Œ λ°˜λ“œμ‹œ μ†ŒμŠ€ μ½”λ“œκ°€ ν•¨κ»˜ ν¬ν•¨λ˜μ–΄μ•Ό ν•œλ‹€. 일반적으둜 npm λ ˆμ§€μŠ€νŠΈλ¦¬μ— 배포할 λ•Œ μ†ŒμŠ€μ½”λ“œκ°€ μ•„λ‹Œ λΉŒλ“œ κ²°κ³Όλ¬Όλ§Œμ„ λ°°ν¬ν•˜λŠ” κ²½μš°κ°€ λ§Žμ€λ°, μ΄λ ‡κ²Œ 되면 μ–΄μ°¨ν”Ό 라이브러리 내에 μ†ŒμŠ€μ½”λ“œκ°€ ν¬ν•¨λ˜μ–΄ μžˆμ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 맀핑 νŒŒμΌμ„ ν•¨κ»˜ λ„£μ–΄μ€˜λ„ μ˜λ―Έκ°€ μ—†μ–΄μ§€λŠ” 것이닀.

    λ‹¨μˆœνžˆ npm λ ˆμ§€μŠ€νŠΈλ¦¬μ— μ†ŒμŠ€μ½”λ“œκΉŒμ§€ ν¬ν•¨ν•΄μ„œ λ°°ν¬ν•œλ‹€κ³  ν•΄μ„œ λ‚΄κ°€ λ§Œλ“  λͺ¨λ“ˆμ„ μ‚¬μš©ν•œ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ λ²ˆλ“€ μ‚¬μ΄μ¦ˆκ°€ λŠ˜μ–΄λ‚˜λŠ” 것도 μ•„λ‹ˆλ‹ˆ, λ‚΄κ°€ λ§Œλ“  라이브러리λ₯Ό μ‚¬μš©ν•˜λŠ” κ°œλ°œμžλ“€μ˜ 생산성과 νŽΈμ˜μ„±μ„ 많이 λ†’ν˜€μ£ΌκΈ° μœ„ν•΄ declarationMap을 켜고 μ†ŒμŠ€μ½”λ“œκΉŒμ§€ ν¬ν•¨ν•΄μ„œ npm λ ˆμ§€μŠ€νŠΈλ¦¬μ— λ°°ν¬ν•˜λŠ” 것을 μΆ”μ²œν•œλ‹€.

    downlevelIteration

    κ°’ μ„€λͺ…
    true ES6에 μΆ”κ°€λœ μ΄ν„°λ ˆμ΄μ…˜ κΈ°λŠ₯에 λŒ€ν•œ λͺ…ν™•ν•œ κ΅¬ν˜„μ„ ν•¨κ»˜ μƒμ„±ν•œλ‹€
    false (default) 기본적인 νŠΈλžœμŠ€νŒŒμΌλ§λ§Œμ„ μˆ˜ν–‰ν•œλ‹€

    downlevelIteration μ˜΅μ…˜μ€ νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ ES6μ—μ„œ μΆ”κ°€λœ for/of, Spread, Symbol.iterator λ“±μ˜ κΈ°λŠ₯을 보닀 λͺ…ν™•ν•˜κ²Œ νŠΈλžœμŠ€νŒŒμΌλ§μ„ ν•˜λ„λ‘ λ§Œλ“€ 수 μžˆλŠ” μ˜΅μ…˜μ΄λ‹€.

    컴파일 νƒ€κ²ŸμΈ μžλ°”μŠ€ν¬λ¦½νŠΈ 버전이 ES6 이상이라면 이 μ˜΅μ…˜μ€ 크게 μ˜λ―Έκ°€ μ—†μ§€λ§Œ, 크둜슀 λΈŒλΌμš°μ§• 등을 μœ„ν•΄ ES5 μ΄ν•˜μ˜ 버전을 컴파일 νƒ€κ²ŸμœΌλ‘œ μ‚ΌλŠ” κ²½μš°μ—λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈκ°€ μ‹€ν–‰λ˜λŠ” λŸ°νƒ€μž„ λ•Œ μ΄ν„°λ ˆμ΄ν„°λ“€μ΄ 개발자의 μ˜λ„μ™€ λ‹€λ₯΄κ²Œ λ™μž‘ν•˜λŠ” 것을 방지할 수 μžˆλ‹€.

    예λ₯Ό λ“€μ–΄ for/ofλ₯Ό μ‚¬μš©ν•œ νƒ€μž…μŠ€ν¬λ¦½νŠΈ μ½”λ“œλ₯Ό ES5둜 νŠΈλžœμŠ€νŒŒμΌλ§ν•œλ‹€λ©΄, μ•„λž˜μ™€ 같은 결과물을 λ§Œλ‚˜λ³Ό 수 μžˆλ‹€.

    const str = 'Hello!';
    for (const s of str) {
      console.log(s);
    }
    'use strict';
    var str = 'Hello!';
    for (var _i = 0, str_1 = str; _i < str_1.length; _i++) {
      var s = str_1[_i];
      console.log(s);
    }

    for/ofλŠ” ES5μ—λŠ” μ—†λŠ” κΈ°λŠ₯μ΄λ―€λ‘œ νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” for/ofλ₯Ό 일반적인 for문으둜 트랜슀파일링 ν•œ 것이닀.

    μ—¬κΈ°κΉŒμ§€ 보면 λ³„λ‘œ λ¬Έμ œκ°€ μ—†λŠ” 것 κ°™μ§€λ§Œ, 사싀 μ΄λ ‡κ²Œ 트랜슀파일링된 μ½”λ“œλŠ” 원본 μ½”λ“œμ™€ μ •ν™•νžˆ μΌμΉ˜ν•˜λŠ” λ™μž‘μ„ λ³΄μ—¬μ£Όμ§€λŠ” μ•ŠλŠ”λ‹€. λ°”λ‘œ 이런 μ½”λ“œ λ•Œλ¬Έμ΄λ‹€.

    const str = 'πŸ™';
    for (const s of str) {
      console.log(s);
    }

    μœ„ μ½”λ“œμ—μ„œ μ‚¬μš©λœ πŸ™ 이λͺ¨μ§€λŠ” ν•„μžκ°€ κ°œμΈμ μœΌλ‘œλ„ μ•„μ£Ό μ• μš©ν•˜κ³  μžˆλŠ” 이λͺ¨μ§€μ΄λ‹€. λ‹¨μˆœνžˆ λˆˆμ— λ³΄μ΄λŠ” 문자의 μˆ˜κ°€ ν•œ 개이기 λ•Œλ¬Έμ— 이 이λͺ¨μ§€μ˜ 길이도 λ‹Ήμ—°νžˆ 1이라고 생각할 수 μžˆμ§€λ§Œ, 사싀 이λͺ¨μ§€λ“€μ˜ κΈΈμ΄λŠ” 1이 μ•„λ‹ˆλ‹€.

    'πŸ™'.length // 2
    'πŸ‘©β€β€οΈβ€πŸ’‹β€πŸ‘©'.length // 11

    즉, 이 이λͺ¨μ§€μ˜ 길이λ₯Ό μ‚¬μš©ν•˜μ—¬ 일반적인 for 문을 μž‘μ„±ν•˜κ²Œ 되면 μ œλŒ€λ‘œ 된 문자λ₯Ό 뽑아내기가 μ–΄λ €μšΈ 수 μžˆλ‹€λŠ” 것이닀. 무슨 말인지 잘 이해가 μ•ˆ λœλ‹€λ©΄, μ•„λž˜ μ½”λ“œλ₯Ό 크둬 κ°œλ°œμžλ„κ΅¬μ— λ³΅λΆ™ν•΄μ„œ ν•œλ²ˆ μ‹€ν–‰μ‹œμΌœλ³΄μž.

    const str = "πŸ™";
    
    for (let i = 0; i < str.length; i++) {
      console.log(`for문 > ${str[i]}`);
    }
    
    for (const s of str) {
      console.log(`for/of문 > ${s}`);
    }
    for문 > �
    for문 > �
    
    for/ofλ¬Έ > πŸ™

    이것이 λ°”λ‘œ for/of 문을 κ·Έλƒ₯ for문으둜 νŠΈλžœμŠ€νŒŒμΌλ§ν•˜λ©΄ μ•ˆ λ˜λŠ” μ΄μœ μ΄λ‹€.

    이처럼 이λͺ¨μ§€μ˜ 길이가 1이 μ•„λ‹Œ 이유λ₯Ό κ°„λ‹¨νžˆλ§Œ μ„€λͺ…ν•˜μžλ©΄, 일단 이λͺ¨μ§€κ°€ λ©€ν‹°λ°”μ΄νŠΈ 문자이기 λ•Œλ¬Έμ΄κΈ°λ„ ν•˜κ³  계속 ν•΄μ„œ μƒˆλ‘œμš΄ 이λͺ¨μ§€κ°€ μΆ”κ°€λ˜κΈ°λ„ ν•˜κ³  κΈ°μ‘΄ 이λͺ¨μ§€λ“€μ„ κ²°ν•©ν•œ 이λͺ¨μ§€λ“€μ΄ λ‚˜μ˜€λ©΄μ„œ 이λͺ¨μ§€λ₯Ό ν‘œν˜„ν•˜λŠ” 방법이 κ΄΄λž„ν•΄μ Έμ„œ 그렇기도 ν•˜λ‹€. 이λͺ¨μ§€ 길이에 λŒ€ν•œ μžμ„Έν•œ λ‚΄μš©μ€ 이 ν¬μŠ€νŒ…μ— 잘 μ„€λͺ…λ˜μ–΄μžˆμœΌλ‹ˆ ν•œλ²ˆ 읽어보도둝 ν•˜μž.

    μ–΄μ°Œλλ˜ μ—¬κΈ°μ„œ μ€‘μš”ν•œ ν¬μΈνŠΈλŠ” for/of와 for의 λ™μž‘μ΄ μœ μ‚¬ν•˜λ‹€κ³  ν•΄μ„œ 묻어놓고 νŠΈλžœμŠ€νŒŒμΌλ§μ„ ν–ˆλ‹€κ°€λŠ” 이런 참사가 λ°œμƒν•  μˆ˜λ„ μžˆλ‹€λŠ” 것이닀.

    κ·Έλž˜μ„œ νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” downlevelIterationμ΄λΌλŠ” μ˜΅μ…˜μ„ λ³„λ„λ‘œ μ œκ³΅ν•΄μ„œ for/of, Spread, Symbol.iterator와 같은 μ΄ν„°λ ˆμ΄μ…˜ κΈ°λŠ₯이 개발자의 μ˜λ„μ™€ λ‹€λ₯΄κ²Œ λ™μž‘ν•˜μ§€ μ•Šλ„λ‘ Symbol.iterator 같은 κΈ°λŠ₯이 μžˆλŠ”μ§€ κ²€μ‚¬ν•˜κ±°λ‚˜, μ•„μ˜ˆ 이런 κΈ°λŠ₯을 κ΅¬ν˜„ν•΄λ†“μ€ ν΄λ¦¬ν•„κΉŒμ§€ ν•¨κ»˜ μΆ”κ°€ν•  수 μžˆλ„λ‘ λ§Œλ“€μ–΄ λ‘μ—ˆλ‹€.

    emitBOM

    κ°’ μ„€λͺ…
    true νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ 좜λ ₯ νŒŒμΌμ„ 생성할 λ•Œ BOM을 ν‘œμ‹œν•œλ‹€
    false (default) νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ 좜λ ₯ νŒŒμΌμ„ 생성할 λ•Œ BOM을 ν‘œμ‹œν•˜μ§€ μ•ŠλŠ”λ‹€

    emitBOM μ˜΅μ…˜μ€ νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ 좜λ ₯ νŒŒμΌμ„ 생성할 λ•Œ BOM(Bite Order Mark)λ₯Ό ν‘œμ‹œν• μ§€ 말지λ₯Ό κ²°μ •ν•  수 μžˆλŠ” μ˜΅μ…˜μ΄λ‹€.

    Bite Order MarkλŠ” νŠΉλ³„ν•œ μœ λ‹ˆμ½”λ“œλ₯Ό 파일의 κ°€μž₯ μ•ž 뢀뢄에 μΆ”κ°€ν•΄μ„œ 이 파일이 μ–΄λ–€ 인코딩 방식을 μ‚¬μš©ν–ˆλŠ”μ§€λ₯Ό λ‚˜νƒ€λ‚΄λŠ” 방법이닀.

    BOM은 μ• μ΄ˆμ— μ‚¬λžŒμ΄ 읽을 λͺ©μ μ΄ μ•„λ‹ˆλΌ μ»΄ν“¨ν„°μ—κ²Œ ν˜„μž¬ 파일의 인코딩 정보λ₯Ό μ•Œλ¦¬κΈ° μœ„ν•΄μ„œλ§Œ μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ—, ν…μŠ€νŠΈ μ—λ””ν„°λ‚˜ vim 같은 κ³³μ—μ„œ νŒŒμΌμ„ 열어보아도 BOM을 λ³΄μ—¬μ£Όμ§€λŠ” μ•ŠλŠ”λ‹€.

    κ·ΈλŸ¬λ‚˜ 일반적으둜 μžλ°”μŠ€ν¬λ¦½νŠΈκ°€ μ‹€ν–‰λ˜λŠ” λŸ°νƒ€μž„ ν™˜κ²½μ—μ„œ ꡳ이 BOMκΉŒμ§€ ν•„μš”ν•œ κ²½μš°κ°€ ν”μΉ˜ μ•ŠκΈ°λ„ ν•˜κ³ , μœ λ‹ˆμ½”λ“œ 3.2λΆ€ν„°λŠ” BOM을 μ‚¬μš©ν•˜μ§€ μ•Šμ„ 것을 ꢌμž₯ν•˜κ³  μžˆκΈ°λ„ ν•΄μ„œ, ꡳ이 μΌ€ ν•„μš”κ°€ μ—†λŠ” μ˜΅μ…˜μ΄κΈ°λ„ ν•˜λ‹€. (νƒ€μž…μŠ€ν¬λ¦½νŠΈ 곡식 λ¬Έμ„œμ—μ„œλ„ ꡳ이 μ•ˆ μΌœλ„ λœλ‹€κ³  ν•˜κ³  μžˆλ‹€)

    emitDeclarationOnly

    κ°’ μ„€λͺ…
    true μžλ°”μŠ€ν¬λ¦½νŠΈ 없이 νƒ€μž… μ„ μ–Έ νŒŒμΌλ§Œμ„ 좜λ ₯ν•œλ‹€
    false (default) μžλ°”μŠ€ν¬λ¦½νŠΈ νŒŒμΌμ„ ν¬ν•¨ν•˜μ—¬ 좜λ ₯ν•œλ‹€

    emitDeclarationOnly μ˜΅μ…˜μ€ Declaration onlyλΌλŠ” 이름 κ·ΈλŒ€λ‘œ, μ»΄νŒŒμΌμ„ 진행할 λ•Œ μžλ°”μŠ€ν¬λ¦½νŠΈ 파일 없이 νƒ€μž… μ„ μ–Έ νŒŒμΌλ§Œμ„ 좜λ ₯할지에 λŒ€ν•œ μ—¬λΆ€λ₯Ό κ²°μ •ν•˜λŠ” μ˜΅μ…˜μ΄λ‹€.

    보톡 νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ λ³€ν™˜ν•  λ•Œ νƒ€μž…μŠ€ν¬λ¦½νŠΈ μ»΄νŒŒμΌλŸ¬κ°€ μ•„λ‹Œ λ³„λ„μ˜ 도ꡬλ₯Ό μ‚¬μš©ν•˜λŠ” κ²½μš°λ‚˜, 기쑴에 μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ λ§Œλ“€μ–΄μ§„ λͺ¨λ“ˆμ— νƒ€μž… μ„ μ–Έλ§Œμ„ μ œκ³΅ν•΄μ•Όν•˜λŠ” κ²½μš°μ— μ‚¬μš©ν•˜κ²Œ λœλ‹€.

    importHelpers

    κ°’ μ„€λͺ…
    true 좜λ ₯ 파일 λ‚΄μ—μ„œ tslibκ°€ μ œκ³΅ν•˜λŠ” 헬퍼 ν•¨μˆ˜λ“€μ„ μ‚¬μš©ν•œλ‹€
    false (default) tslibκ°€ μ œκ³΅ν•˜λŠ” 헬퍼 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  직접 헬퍼λ₯Ό κ΅¬ν˜„ν•˜λ„λ‘ ν•œλ‹€

    importHelpers μ˜΅μ…˜μ€ νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό μžλ°”μŠ€ν¬λ¦½νŠΈ ES5 μ΄ν•˜μ˜ λ²„μ „μœΌλ‘œ νŠΈλžœμŠ€νŒŒμΌλ§ν•  λ•Œ λ°œμƒν•˜λŠ” 헬퍼 ν•¨μˆ˜λ“€μ„ 좜λ ₯ 파일 내에 직접 μž‘μ„±ν•  것이냐, μ•„λ‹ˆλ©΄ tslib λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μ œκ³΅ν•˜λŠ” 헬퍼 ν•¨μˆ˜λ‘œ λŒ€μ²΄ν•  수 μžˆλ„λ‘ ν•  것이냐λ₯Ό κ²°μ •ν•  수 μžˆλŠ” μ˜΅μ…˜μ΄λ‹€.

    ν•œλ²ˆ μ†ŒμŠ€ μ½”λ“œμ™€ 좜λ ₯ νŒŒμΌμ„ ν•¨κ»˜ λ³΄λ©΄μ„œ 이해해보도둝 ν•˜μž.

    export function fn(arr: number[]) {
      return [1, ...arr];
    }

    fn ν•¨μˆ˜λŠ” 인자둜 받은 λ°°μ—΄μ˜ 맨 μ•žμ— 1μ΄λΌλŠ” μ›μ†Œλ₯Ό μΆ”κ°€ν•΄μ„œ λ°˜ν™˜ν•˜λŠ” κ°„λ‹¨ν•œ ν•¨μˆ˜μ΄λ‹€. μ—¬λŸ¬λΆ„λ„ μ•„μ‹œλ‹€μ‹œν”Ό [...arr]λΌλŠ” λ¬Έλ²•μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλŠ” Spread κΈ°λŠ₯은 ES5에 ν¬ν•¨λ˜μ–΄μžˆμ§€ μ•ŠμœΌλ―€λ‘œ, νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” __spreadArray λΌλŠ” 헬퍼 ν•¨μˆ˜λ₯Ό 좜λ ₯ 파일 내에 μΆ”κ°€ν•˜μ—¬ Spread κΈ°λŠ₯을 νŠΈλžœμŠ€νŒŒμΌλ§ν•œλ‹€.

    var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
      if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
          if (!ar) ar = Array.prototype.slice.call(from, 0, i);
          ar[i] = from[i];
        }
      }
      return to.concat(ar || Array.prototype.slice.call(from));
    };
    export function fn(arr) {
      return __spreadArray([1], arr, true);
    }

    μ—¬κΈ°μ„œ μ€‘μš”ν•œ 것은 ES6의 Spread κΈ°λŠ₯을 κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄ __spreadArrayλΌλŠ” ν•¨μˆ˜μ˜ κ΅¬ν˜„μ΄ 좜λ ₯ 파일 내에 ν•¨κ»˜ ν¬ν•¨λ˜μ—ˆλ‹€λŠ” 것이닀. 사싀 이런 κ΅¬ν˜„μ΄ 좜λ ₯ νŒŒμΌλ‚΄μ— ν¬ν•¨λ˜λŠ” 것이 큰 λ¬Έμ œλŠ” 아닐 수 μžˆμ§€λ§Œ, λ§Œμ•½ μ € __spreadArrayλ₯Ό λ‹€λ₯Έ κ³³μ—μ„œ 또 μ‚¬μš©ν•΄μ•Όν•˜λŠ” κ²½μš°μ—λŠ” κ·Έ λͺ¨λ“ˆμ— 또 λ‹€μ‹œ __spreadArray ν•¨μˆ˜μ˜ κ΅¬ν˜„μ΄ μΆ”κ°€λ˜κΈ° λ•Œλ¬Έμ— μ€‘λ³΅λœ μ½”λ“œκ°€ λ°œμƒν•˜κ²Œ λœλ‹€.

    μ΄λ•Œ importHelpers μ˜΅μ…˜μ„ μ‚¬μš©ν•˜κ²Œ 되면 μ΄λŸ¬ν•œ 헬퍼 ν•¨μˆ˜λ“€μ„ tslib λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ κ°€μ Έμ˜€λ„λ‘ λ³€κ²½ν•˜μ—¬ μ½”λ“œμ˜ 쀑볡을 μ œκ±°ν•  수 μžˆλ‹€.

    import { __spreadArray } from 'tslib';
    export function fn(arr) {
      return __spreadArray([1], arr, true);
    }

    μ΄λ ‡κ²Œ 되면 __spreadArray ν•¨μˆ˜λ₯Ό tslibμ—μ„œ λΆˆλŸ¬μ™€μ„œ μ‚¬μš©ν•˜κ²Œ λ˜λ―€λ‘œ, 맀번 __spreadArray ν•¨μˆ˜λ₯Ό μ„ μ–Έν•  ν•„μš”κ°€ 사라지기 λ•Œλ¬Έμ— μ½”λ“œμ˜ 쀑볡을 μ œκ±°ν•  수 μžˆλ‹€. ν•˜μ§€λ§Œ 이 μ˜΅μ…˜μ„ μ‚¬μš©ν•˜μ—¬ 트랜슀파일링된 μ½”λ“œλŠ” λ‹Ήμ—°νžˆ tslib νŒ¨ν‚€μ§€λ₯Ό μ„€μΉ˜λ˜μ–΄μžˆμ–΄μ•Ό μ œλŒ€λ‘œ μž‘λ™ν•˜λ―€λ‘œ, 헬퍼 ν•¨μˆ˜μ˜ μ€‘λ³΅λœ κ΅¬ν˜„μ„ ν—ˆμš©ν•˜λŠ” 것과 tslibλ₯Ό λ‚΄ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ— μ„€μΉ˜ν•˜λŠ” κ²ƒμ˜ 득과 싀을 잘 따져보고 μ˜΅μ…˜μ„ μ‚¬μš©ν•˜λ„λ‘ ν•˜μž.

    importsNotUsedAsValues

    κ°’ μ„€λͺ…
    remove 좜λ ₯ νŒŒμΌμ—μ„œ λŸ°νƒ€μž„ λ•Œ ν•„μš”μ—†λŠ” import 문을 μ œκ±°ν•œλ‹€
    preserve 좜λ ₯ νŒŒμΌμ—μ„œ νƒ€μž… μ •λ³΄λŠ” μ œκ±°ν•˜λ˜, import 문은 μœ μ§€ν•œλ‹€
    error νƒ€μž… μ •λ³΄λ§Œ κ°€μ Έμ˜€λŠ” import 문을 μ‚¬μš©ν–ˆμ„ λ•Œ μ—λŸ¬λ₯Ό λ°œμƒμ‹œν‚¨λ‹€

    importsNotUsedAsValues μ˜΅μ…˜μ€ νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ 좜λ ₯ νŒŒμΌμ„ 생성할 λ•Œ ν•„μš”μ—†λŠ” import ꡬ문을 μ²˜λ¦¬ν•˜λŠ” 방법을 μ œμ–΄ν•  수 μžˆλŠ” μ˜΅μ…˜μ΄λ‹€. 이 μ˜΅μ…˜μ΄ κ°€μ§€λŠ” 의미λ₯Ό μ•ŒκΈ° μœ„ν•΄μ„œλŠ” νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ import 문을 μ²˜λ¦¬ν•˜λŠ” 방법에 λŒ€ν•΄μ„œ 쑰금 μ•Œμ•„μ•Ό ν•œλ‹€.

    기본적으둜 νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ μ»΄νŒŒμΌμ„ 톡해 μžλ°”μŠ€ν¬λ¦½νŠΈ νŒŒμΌμ„ 생성할 λ•Œ, νƒ€μž…κ³Ό κ΄€λ ¨λœ μ •λ³΄λŠ” μ§€μ›Œλ²„λ¦°λ‹€. μ½”λ“œλ₯Ό λ³΄λ©΄μ„œ ν•œλ²ˆ 이해해보도둝 ν•˜μž.

    import { InterfaceFoo } from '../utils/foo';
    import { ClassBar } from '../utils/bar';
    
    const classBar: InterfaceFoo = new ClassBar();
    import { ClassBar } from '../utils/bar';
    var classBar = new ClassBar();

    μœ„ μ½”λ“œλ₯Ό 보면 InterfaceFoo μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ°€μ Έμ˜€λŠ” import 문이 μžλ°”μŠ€ν¬λ¦½νŠΈ 좜λ ₯ 파일 λ‚΄μ—μ„œλŠ” 사라진 것을 λ³Ό 수 μžˆλ‹€. μ™œλƒν•˜λ©΄ μžλ°”μŠ€ν¬λ¦½νŠΈμ—λŠ” νƒ€μž…μŠ€ν¬λ¦½νŠΈμ˜ νƒ€μž…μ΄λ‚˜ μΈν„°νŽ˜μ΄μŠ€ 같은 κΈ°λŠ₯이 μ—†μœΌλ‹ˆ, νƒ€μž… 정보λ₯Ό λ‚¨κ²¨λ†”λ΄€μž μ˜λ―Έκ°€ μ—†κΈ° λ•Œλ¬Έμ΄λ‹€.

    λ¬Όλ‘  μ•žμ„œ μ΄μ•ΌκΈ°ν•œλŒ€λ‘œ νƒ€μž… μ •λ³΄λŠ” μ–΄μ°¨ν”Ό μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ μ‚¬μš©ν•  수 μ—†μœΌλ‹ˆ, 이런 μ •λ³΄λŠ” μ œκ±°ν•˜λŠ” 것이 λ§žμ§€λ§Œ, λ§Œμ•½ ../utils/foo λͺ¨λ“ˆμ΄ μ˜λ„μ μΈ μ‚¬μ΄λ“œμ΄νŽ™νŠΈλ₯Ό ν¬ν•¨ν•˜κ³  μžˆμ„ κ²½μš°μ—λŠ” λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆλ‹€.

    // utils/foo.ts
    export interface InterfaceFoo {}
    console.log('hello world!');

    utils/foo.ts λͺ¨λ“ˆμ€ μΈν„°νŽ˜μ΄μŠ€λ§Œμ„ λ…ΈμΆœν•˜κ³  μžˆλŠ” λͺ¨λ“ˆμ΄μ§€λ§Œ, λ‚΄λΆ€μ—λŠ” console.logλΌλŠ” μ‚¬μ΄λ“œ μ΄νŽ™νŠΈλ₯Ό ν¬ν•¨ν•˜κ³  μžˆλ‹€. 이 μ˜ˆμ‹œμ—μ„œλŠ” λ‹¨μˆœν•œ μ½˜μ†” 좜λ ₯μ΄μ§€λ§Œ, μ‹€μ œλ‘œ Angular 같은 κ²½μš°λŠ” 이런 λͺ¨λ“ˆ λ‚΄λΆ€μ—μ„œ λͺ…μ‹œμ μœΌλ‘œ λͺ¨λ“ˆμ„ μ£Όμž…ν•˜κ³  λ“±λ‘ν•˜λŠ” μ‚¬μ΄λ“œ μ΄νŽ™νŠΈκ°€ ν¬ν•¨λ˜κΈ°λ„ ν•œλ‹€.

    λ¬Έμ œλŠ” 이런 κ²½μš°μ—λ„ νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό 좜λ ₯ν•  λ•Œ utils/foo λͺ¨λ“ˆμ„ import ν–ˆλ˜ ꡬ문 자체λ₯Ό μ§€μ›Œλ²„λ¦°λ‹€λŠ” 것이닀. 그러면 λ‹Ήμ—°νžˆ console.logλΌλŠ” μ‚¬μ΄λ“œ μ΄νŽ™νŠΈλŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ λŸ°νƒ€μž„μ—μ„œ μ‹€ν–‰λ˜μ§€ μ•ŠλŠ”λ‹€. κ·Έλž˜μ„œ 이런 경우 κ°œλ°œμžλ“€μ€ μ˜λ„μ μœΌλ‘œ μ‚¬μ΄λ“œ μ΄νŽ™νŠΈλ₯Ό μ‹€ν–‰μ‹œν‚€κΈ° μœ„ν•΄ νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό 속일 수 μžˆλŠ” import 문을 ν•˜λ‚˜ 더 μΆ”κ°€ν•΄μ•Όν•œλ‹€.

    import { InterfaceFoo } from '../utils/foo';
    import '../utils/foo';
    import { ClassBar } from '../utils/bar';
    
    const classBar: InterfaceFoo = new ClassBar();
    import './utils/foo';
    import { ClassBar } from "../utils/bar";
    var classBar = new ClassBar();

    κ·Έλž˜μ„œ νƒ€μž…μŠ€ν¬λ¦½νŠΈ 3.8λ²„μ „μ—λŠ” β€œμ΄ import문이 νƒ€μž… μ •λ³΄λ§Œμ„ κ°€μ Έμ˜€λŠ” κ΅¬λ¬Έμ΄λ‹€β€λΌλŠ” 것을 λͺ…μ‹œμ μœΌλ‘œ ν‘œν˜„ν•  수 μžˆλŠ” import type κΈ°λŠ₯을 μΆ”κ°€ν–ˆκ³ , ν˜Ήμ—¬λ‚˜ 일반적인 import 문을 μ‚¬μš©ν•˜μ—¬ νƒ€μž… μ •λ³΄λ§Œμ„ κ°€μ Έμ˜€λ”λΌλ„ import문을 λ‚¨κ²¨λ‘˜ 수 μžˆλ„λ‘ μ œμ–΄ν•  수 μžˆλŠ” importsNotUsedAsValues μ˜΅μ…˜μ„ μ œκ³΅ν•˜λŠ” 것이닀.

    inlineSourceMap

    κ°’ μ„€λͺ…
    false μ†ŒμŠ€λ§΅ νŒŒμΌμ„ λ”°λ‘œ μƒμ„±ν•œλ‹€
    true μ†ŒμŠ€λ§΅ 파일의 λ‚΄μš©μ„ Base64둜 μΈμ½”λ”©ν•˜μ—¬ μ†ŒμŠ€ νŒŒμΌμ— μΆ”κ°€ν•œλ‹€

    inlineSourceMap μ˜΅μ…˜μ€ νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ 컴파일 μ‹œ μ–΄λ–€ λ°©μ‹μœΌλ‘œ μ†ŒμŠ€λ§΅μ„ 생성할 것인지λ₯Ό κ²°μ •ν•˜λŠ” μ˜΅μ…˜μ΄λ‹€. 기본적으둜 νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” *.js.map 파일의 ν˜•νƒœλ‘œ μ†ŒμŠ€λ§΅μ„ μ œκ³΅ν•˜λŠ”λ°, λ§Œμ•½ inlineSourceMap이 true일 κ²½μš°μ—λŠ” μ†ŒμŠ€ 파일 내뢀에 μ£Όμ„μœΌλ‘œ μ†ŒμŠ€λ§΅μ„ μΆ”κ°€ν•œλ‹€.

    κ°„λ‹¨ν•œ ν•¨μˆ˜λ₯Ό 가지고 μžˆλŠ” λͺ¨λ“ˆμ„ 직접 μ»΄νŒŒμΌν•΄λ³΄λ©° μ–΄λ–€ 차이가 μžˆλŠ”μ§€ 직접 μ•Œμ•„λ³΄λ„λ‘ ν•˜μž.

    // math.ts
    export const add = (x: number) => (y: number) => x + y;

    λ§Œμ•½ inlineSourceMap μ˜΅μ…˜μ΄ κΊΌμ Έ μžˆλŠ” 경우, νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” λ³„λ„μ˜ μ†ŒμŠ€λ§΅ νŒŒμΌμ„ μƒμ„±ν•˜κ³ , 컴파일된 JS νŒŒμΌμ—λŠ” ν•΄λ‹Ή μ†ŒμŠ€λ§΅μ˜ κ²½λ‘œλ§Œμ„ μ μ–΄λ‘λŠ” ν˜•νƒœλ‘œ μ†ŒμŠ€λ§΅μ„ μƒμ„±ν•œλ‹€.

    // math.js
    export var add = function (x) { return function (y) { return x + y; }; };
    //# sourceMappingURL=math.js.map
    // math.js.map
    {"version":3,"file":"math.js","sourceRoot":"","sources":["../../utils/math.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,IAAM,GAAG,GAAG,UAAC,CAAS,IAAK,OAAA,UAAC,CAAS,IAAK,OAAA,CAAC,GAAG,CAAC,EAAL,CAAK,EAApB,CAAoB,CAAC"}

    μ΄λ•Œ 컴파일된 JS νŒŒμΌμ—λŠ” μ†ŒμŠ€λ§΅ 파일의 κ²½λ‘œκ°€ #sourceMappingURL=math.js.map의 ν˜•νƒœλ‘œ μΆ”κ°€λ˜κ³ , μ†ŒμŠ€λ§΅ νŒŒμΌμ—λŠ” "sources": ["../../utils/math.ts"]처럼 원본 νƒ€μž…μŠ€ν¬λ¦½νŠΈ μ†ŒμŠ€ 파일의 κ²½λ‘œκ°€ μ ν˜€μžˆλŠ” 것을 확인할 수 μžˆλ‹€.

    λ§Œμ•½ inlineSourceMap μ˜΅μ…˜μ„ 켜게되면 이제 νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” μ†ŒμŠ€λ§΅ νŒŒμΌμ„ μƒμ„±ν•˜μ§€ μ•Šκ³ , 컴파일된 JS 파일 내에 직접 μ†ŒμŠ€λ§΅ 파일의 λ‚΄μš©μ„ Base64둜 μΈμ½”λ”©ν•΄μ„œ μΆ”κ°€ν•œλ‹€.

    export var add = function (x) { return function (y) { return x + y; }; };
    //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0aC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3V0aWxzL21hdGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxDQUFDLElBQU0sR0FBRyxHQUFHLFVBQUMsQ0FBUyxJQUFLLE9BQUEsVUFBQyxDQUFTLElBQUssT0FBQSxDQUFDLEdBQUcsQ0FBQyxFQUFMLENBQUssRUFBcEIsQ0FBb0IsQ0FBQyJ9

    inlineSources

    κ°’ μ„€λͺ…
    false 인라인 μ†ŒμŠ€λ§΅μ— μ†ŒμŠ€ μ½”λ“œμ˜ λ‚΄μš©μ€ ν¬ν•¨μ‹œν‚€μ§€ μ•ŠλŠ”λ‹€.
    true 인라인 μ†ŒμŠ€λ§΅μ— μ†ŒμŠ€ μ½”λ“œμ˜ λ‚΄μš©λ„ ν•¨κ»˜ ν¬ν•¨μ‹œν‚¨λ‹€

    inlineSources μ˜΅μ…˜μ€ inlineSourceMap μ˜΅μ…˜μ„ μ‚¬μš©ν•˜μ—¬ λ§Œλ“€μ–΄λ‚Έ 인라인 μ†ŒμŠ€λ§΅μ— 원본 μ†ŒμŠ€ μ½”λ“œμ˜ λ‚΄μš©λ„ ν•¨κ»˜ ν¬ν•¨μ‹œν‚¬ 것인지 μ—¬λΆ€λ₯Ό κ²°μ •ν•œλ‹€.

    이 μ˜΅μ…˜μ˜ 값이 true인 경우, 인라인 μ†ŒμŠ€λ§΅μ— sourceContentλΌλŠ” ν•„λ“œκ°€ μΆ”κ°€λ˜κ³  ν•΄λ‹Ή ν•„λ“œμ—λŠ” μ†ŒμŠ€ μ½”λ“œμ˜ λ‚΄μš©μ΄ 함꼐 ν¬ν•¨λœλ‹€.

    export var add = function (x) { return function (y) { return x + y; }; };
    //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0aC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3V0aWxzL21hdGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxDQUFDLElBQU0sR0FBRyxHQUFHLFVBQUMsQ0FBUyxJQUFLLE9BQUEsVUFBQyxDQUFTLElBQUssT0FBQSxDQUFDLEdBQUcsQ0FBQyxFQUFMLENBQUssRUFBcEIsQ0FBb0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjb25zdCBhZGQgPSAoeDogbnVtYmVyKSA9PiAoeTogbnVtYmVyKSA9PiB4ICsgeTtcbiJdfQ==
    // Decoding된 μ†ŒμŠ€λ§΅
    
    {
      "version":3,
      "file":"math.js",
      "sourceRoot":"",
      "sources":["../../utils/math.ts"],
      "names":[],
      "mappings":"AAAA,MAAM,CAAC,IAAM,GAAG,GAAG,UAAC,CAAS,IAAK,OAAA,UAAC,CAAS,IAAK,OAAA,CAAC,GAAG,CAAC,EAAL,CAAK,EAApB,CAAoB,CAAC",
      "sourcesContent":["export const add = (x: number) => (y: number) => x + y;\n"]
    }

    μ• μ΄ˆμ— μ†ŒμŠ€λ§΅μ˜ μŠ€νŽ™ 상 sourceContent ν•„λ“œλŠ” 원본 μ†ŒμŠ€ νŒŒμΌμ— μ ‘κ·Όν•˜μ§€ λͺ»ν•œ 경우λ₯Ό λŒ€μ‘ν•˜κΈ° μœ„ν•œ μΌμ’…μ˜ μ˜ˆμ™Έμ²˜λ¦¬μ— κ°€κΉŒμš°λ―€λ‘œ, ꡳ이 μΌœμ§€ μ•Šμ•„λ„ 큰 λ¬Έμ œκ°€ μ—†λŠ” μ˜΅μ…˜μ΄κΈ°λ„ ν•˜λ‹€.

    noEmit

    κ°’ μ„€λͺ…
    false 컴파일 후에 좜λ ₯ νŒŒμΌμ„ 내보낸닀
    true 컴파일 후에 좜λ ₯ νŒŒμΌμ„ 내보내지 μ•ŠλŠ”λ‹€

    noEmit μ˜΅μ…˜μ€ 이름 κ·ΈλŒ€λ‘œ νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ μ»΄νŒŒμΌμ„ ν•œ 이후에 좜λ ₯ νŒŒμΌλ“€μ„ 내보낼 것인지에 λŒ€ν•œ λ™μž‘μ„ κ²°μ •ν•œλ‹€. μ„€λͺ…λ§Œ 듀어보면 이런 κ²½μš°κ°€ ν•„μš”ν• κΉŒ μ‹ΆκΈ°λŠ” ν•œλ°, 생각보닀 μœ μš©ν•˜κ²Œ 자주 μ“°μ΄λŠ” μ˜΅μ…˜μ΄λ‹€.

    λŒ€ν‘œμ μΈ μ˜ˆλ‘œλŠ” CIλ‚˜ Git Hook 같은 타이밍에 정적 νƒ€μž… 체크만 진행해야 ν•˜λŠ” 경우 tsc --noEmit와 같은 λͺ…λ Ήμ–΄λ₯Ό NPM 슀크립트둜 λ“±λ‘ν•΄λ†“κ±°λ‚˜, Webpack, Parcel, Rollup λ“±μ˜ 도ꡬλ₯Ό μ‚¬μš©ν•˜μ—¬ μ»΄νŒŒμΌμ„ 진행할 λ•Œλ„ 정적 νƒ€μž… μ²΄ν¬λ§Œμ„ TSCμ—κ²Œ μ‹œν‚€κΈ° μœ„ν•΄ ν•΄λ‹Ή μ˜΅μ…˜μ„ μ‚¬μš©ν•˜λŠ” κ²½μš°κ°€ λ§Žλ‹€.

    noEmitHelpers

    κ°’ μ„€λͺ…
    false 컴파일된 νŒŒμΌμ— __awaiter와 같은 헬퍼 ν•¨μˆ˜λ₯Ό ν¬ν•¨μ‹œν‚¨λ‹€
    true 컴파일된 νŒŒμΌμ—λŠ” __awaiter와 같은 헬퍼 ν•¨μˆ˜λ₯Ό ν¬ν•¨μ‹œν‚€μ§€ μ•ŠλŠ”λ‹€

    noEmitHelpers μ˜΅μ…˜μ€ 컴파일이 μ™„λ£Œλœ 좜λ ₯ νŒŒμΌμ— __awaiterλ‚˜ __generator와 같은 헬퍼 ν•¨μˆ˜λ“€μ„ ν¬ν•¨μ‹œν‚¬μ§€ μ—¬λΆ€λ₯Ό κ²°μ •ν•œλ‹€.

    noEmitHelpers μ˜΅μ…˜μ˜ λ™μž‘μ΄ importHelpers와 μœ μ‚¬ν•˜κΈ° λ•Œλ¬Έμ— 쑰금 ν—·κ°ˆλ¦΄ 수 μžˆλ‹€. importHelpers μ˜΅μ…˜μ€ 헬퍼 ν•¨μˆ˜λ“€μ˜ κ΅¬ν˜„μ„ β€œμ†ŒμŠ€μ— 포함할지”, β€œλ‹€λ₯Έ κ³³μ—μ„œ import할지”λ₯Ό κ²°μ •ν•œλ‹€λ©΄, noEmitHelpers μ˜΅μ…˜μ€ 헬퍼 ν•¨μˆ˜λ“€μ˜ κ΅¬ν˜„μ„ β€œμ†ŒμŠ€μ— 포함할지”, β€œμ•„μ˜ˆ ν•˜μ§€ μ•Šμ„ 것인지”λ₯Ό κ²°μ •ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

    이 차이점을 직접 컴파일된 μ½”λ“œλ₯Ό λ³΄λ©΄μ„œ μ•Œμ•„λ³΄λ„λ‘ ν•˜μž.

    // importHelpers, noEmitHelpersκ°€ λͺ¨λ‘ κΊΌμ ΈμžˆλŠ” κ²½μš°μ—λŠ” 좜λ ₯ νŒŒμΌμ— ν—¬νΌμ˜ κ΅¬ν˜„λ„ ν¬ν•¨λœλ‹€
    
    var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
      // ...
    };
    var __generator = (this && this.__generator) || function (thisArg, body) {
      // ...
    };
    
    export function foo() {
      return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
        return [2 /*return*/];
      }); });
    }
    // importHelperκ°€ μΌœμ ΈμžˆλŠ” κ²½μš°μ—λŠ” μ™ΈλΆ€μ—μ„œ 헬퍼λ₯Ό κ°€μ Έμ˜¨λ‹€
    
    import { __awaiter, __generator } from "tslib";
    export function foo() {
      return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
        return [2 /*return*/];
      }); });
    }
    // noEmitHelpersκ°€ μΌœμ ΈμžˆλŠ” κ²½μš°μ—λŠ” μ•„μ˜ˆ 헬퍼λ₯Ό κ°€μ Έμ˜€κ±°λ‚˜ μ„ μ–Έν•˜λŠ” μ½”λ“œ μ‘°μ°¨ μ—†λ‹€
    
    'use strict';
    export function foo() {
      return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
        return [2 /*return*/];
      }); });
    }

    λ§Œμ•½ importHelpers와 noEmitHelpers μ˜΅μ…˜μ΄ λͺ¨λ‘ μΌœμ Έμžˆλ‹€λ©΄ 헬퍼 ν•¨μˆ˜λ₯Ό β€œμ™ΈλΆ€μ—μ„œ κ°€μ Έμ˜¬ 것이냐”, β€œμΆœλ ₯ νŒŒμΌμ— ν¬ν•¨μ‹œν‚€μ§€ μ•Šμ„ κ²ƒμ΄λƒβ€λΌλŠ” 섀정이 μΆ©λŒν•˜κ²Œ λ˜λŠ”λ°, 이 κ²½μš°μ—λŠ” importHelpers의 λ™μž‘μ„ μš°μ„ μ μœΌλ‘œ λ”°λ₯΄κ²Œ λ˜λ‹ˆ 이 점을 μ£Όμ˜ν•˜λ„λ‘ ν•˜μž.

    noEmitOnError

    κ°’ μ„€λͺ…
    false 컴파일 쀑 μ—λŸ¬κ°€ λ°œμƒν•˜λ”λΌλ„ 좜λ ₯ νŒŒμΌμ„ 내보낸닀
    true 컴파일 쀑 μ—λŸ¬κ°€ λ°œμƒν•œ 경우 좜λ ₯ νŒŒμΌμ„ 내보내지 μ•ŠλŠ”λ‹€

    noEmitOnError μ˜΅μ…˜μ€ 이름 κ·ΈλŒ€λ‘œ 컴파일 쀑 μ—¬λŸ¬κ°€μ§€ μš”μΈμœΌλ‘œ 인해 μ—λŸ¬κ°€ λ°œμƒν•˜κ²Œ λ˜λŠ” 경우 좜λ ₯ νŒŒμΌμ„ 내보낼 것인지에 λŒ€ν•œ μ—¬λΆ€λ₯Ό κ²°μ •ν•œλ‹€. λ§Œμ•½ 이 μ˜΅μ…˜μ΄ μΌœμ ΈμžˆλŠ” 경우, 컴파일 쀑 μ—λŸ¬κ°€ λ°œμƒν•˜λ©΄ 좜λ ₯ 파일이 내보내지지 μ•ŠλŠ”λ‹€.

    μ΄λ ‡κ²Œλ§Œ 보면 β€œλ‹Ήμ—°νžˆ μ—λŸ¬κ°€ λ‚˜λ©΄ 좜λ ₯ νŒŒμΌμ„ μ•ˆ λ§Œλ“œλŠ” 게 λ§žμ§€ μ•Šλ‚˜?”라고 생각할 수 μžˆμ§€λ§Œ, TSC의 Watch μ˜΅μ…˜μ„ μ‚¬μš©ν•˜κ³  μžˆλŠ” κ°œλ°œν™˜κ²½ 같은 κ²½μš°λŠ” 컴파일 쀑 μ—λŸ¬κ°€ λ°œμƒν•΄λ„ 좜λ ₯ νŒŒμΌμ„ μƒμ„±ν•˜κ³  그둜 인해 λ°œμƒν•˜λŠ” μ‚¬μ΄λ“œ μ΄νŽ™νŠΈ λ˜ν•œ ν•¨κ»˜ κ΄€μ°°ν•˜λŠ” 것이 더 νŽΈν•  μˆ˜λ„ 있기 λ•Œλ¬Έμ—, κ°œλ°œν™˜κ²½μ—μ„œλŠ” ν•΄λ‹Ή μ˜΅μ…˜μ„ 끄고 μš΄μ˜ν™˜κ²½ 배포λ₯Ό μœ„ν•œ λΉŒλ“œ νƒ€μž„ λ•ŒλŠ” μΌœλ†“λŠ” 것을 μΆ”μ²œν•œλ‹€.

    preserveConstEnums

    κ°’ μ„€λͺ…
    false const enum ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•œ Enum 선언을 컴파일 νƒ€μž„ λ•Œ μ œκ±°ν•œλ‹€
    true const enum ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•œ Enum 선언을 컴파일 νƒ€μž„ λ•Œ μ œκ±°ν•˜μ§€ μ•ŠλŠ”λ‹€

    preserveConstEnums μ˜΅μ…˜μ€ 컴파일 νƒ€μž„ λ•Œ const enum ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•œ Enum 선언을 μ œκ±°ν•  것인지에 λŒ€ν•œ μ˜΅μ…˜μ΄λ‹€. νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” λŸ°νƒ€μž„ λ•Œμ˜ λ©”λͺ¨λ¦¬ λΉ„μš©μ„ μ ˆμ•½ν•˜κΈ° μœ„ν•΄ const enum ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ Enum의 값을 μ°Έμ‘°ν•˜λŠ” 뢀뢄을 ν•΄λ‹Ή Enum의 κ°’μœΌλ‘œ μΉ˜ν™˜ν•œλ‹€.

    enum ν‚€μ›Œλ“œλ§Œμ„ μ‚¬μš©ν•˜μ—¬ μ„ μ–Έν•œ Enumκ³Ό λ‹€λ₯΄κ²Œ const enum ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•œ Enum은 λ°˜λ“œμ‹œ μƒμˆ˜ κ°’λ§Œ κ°€μ§€λŠ” 것이 보μž₯되기 λ•Œλ¬Έμ— μ°Έμ‘° 투λͺ…μ„± λ˜ν•œ 보μž₯되고, κ²°κ΅­ 컴파일 νƒ€μž„ λ•Œ 값을 κ·Έλƒ₯ μΉ˜ν™˜ν•΄λ²„λ €λ„ 아무 λ¬Έμ œκ°€ μ—†λŠ” 것이닀.

    const enum Foo {
      A = 1,
      B = 2,
      C = 3,
    }
    const foo = Foo.A;
    var Foo;
    (function (Foo) {
        Foo[Foo["A"] = 0] = "A";
        Foo[Foo["B"] = 1] = "B";
        Foo[Foo["C"] = 2] = "C";
    })(Foo || (Foo = {}));
    var foo = 1 /* A */; // <= Foo.Aκ°€ μ•„λ‹Œ, κ°’μœΌλ‘œ μΉ˜ν™˜λ˜μ—ˆλ‹€

    μ΄λ•Œ 컴파일된 μ½”λ“œλ₯Ό μžμ„Ένžˆ 보면, Enum을 ν‘œν˜„ν•˜κΈ° μœ„ν•΄ FooλΌλŠ” λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜κ³  IIFEλ₯Ό μ‚¬μš©ν•˜μ—¬ ν•΄λ‹Ή λ³€μˆ˜μ— 값을 ν• λ‹Ήν•˜κ³  μžˆμ§€λ§Œ, μ •μž‘ 이 λ³€μˆ˜μ— μ ‘κ·Όν•˜λŠ” 뢀뢄은 μ—†λŠ” 것을 μ•Œ 수 μžˆλ‹€. 즉, 이 JS μ½”λ“œκ°€ μ‹€ν–‰λ˜λŠ” λŸ°νƒ€μž„ ν™˜κ²½μ—μ„œλŠ” FooλΌλŠ” λ³€μˆ˜κ°€ 없어도 아무 λ¬Έμ œκ°€ μ—†λ‹€λŠ” 것이닀.

    μ΄λ•Œ preserveConstEnums μ˜΅μ…˜μ˜ 값을 false둜 μ„€μ •ν•˜λ©΄ μ΄λ ‡κ²Œ λŸ°νƒ€μž„μ—μ„œλŠ” 아무 μ˜λ―Έμ—†λŠ” Enum 선언을 μ œκ±°ν•  수 μžˆλ‹€.

    var foo = 1 /* A */;

    마치며

    μ΄λ ‡κ²Œ tsconfig 4번째 μ‹œλ¦¬μ¦ˆμΈ Emit νŽΈμ„ λ§ˆλ¬΄λ¦¬ν–ˆλ‹€. Emitκ³Ό κ΄€λ ¨λœ 역할을 ν•˜λŠ” μ˜΅μ…˜λ“€μ€ 주둜 TSC와 λ‹€λ₯Έ 도ꡬλ₯Ό κ²°ν•©ν•˜μ—¬ μ‚¬μš©ν•˜κ±°λ‚˜, λ²ˆλ“€ μ‚¬μ΄μ¦ˆλ₯Ό μ΅œμ ν™”ν•΄μ•Όν•˜λŠ” κ²½μš°μ— 주둜 κ±΄λ“œλ¦¬κ²Œ λ˜λŠ”λ°, ν•„μž λ˜ν•œ κ½€λ‚˜ μ˜€λžœλ§Œμ— 이 μ˜΅μ…˜λ“€μ„ κ³΅λΆ€ν•˜κ²Œ λ˜μ—ˆλ˜ 지라 μ˜ˆμ „μ— 써본 μ˜΅μ…˜λ“€μ΄ μžˆμŒμ—λ„ λΆˆκ΅¬ν•˜κ³  기얡이 κ°€λ¬Όκ°€λ¬Ό ν–ˆλ˜ 것 κ°™λ‹€.

    μ΄μƒμœΌλ‘œ [tsconfig의 λͺ¨λ“  것] Compiler options / Emit ν¬μŠ€νŒ…μ„ λ§ˆμΉœλ‹€.

    Evan Moon

    🐒 거뢁이처럼 μ‚΄μž

    κ°œλ°œμ„ μž˜ν•˜κΈ° μœ„ν•΄μ„œκ°€ μ•„λ‹Œ κ°œλ°œμ„ 즐기기 μœ„ν•΄ λ…Έλ ₯ν•˜λŠ” κ°œλ°œμžμž…λ‹ˆλ‹€. μ‚¬μ†Œν•œ 생각 정리뢀터 νŠœν† λ¦¬μ–Ό, μ‚½μ§ˆκΈ° 정도λ₯Ό 주둜 끄적이고 μžˆμŠ΅λ‹ˆλ‹€.