TypeScript 컴파일러 옵션으로 코드 품질 잠금 해제하기
Wenhao Wang
Dev Intern · Leapcell

소개: TypeScript 프로젝트의 숨겨진 건축가
JavaScript 개발 세계에서 TypeScript는 강력하고 확장 가능한 애플리케이션 구축을 위한 필수 도구가 되었습니다. 정적 타이핑 기능은 오류를 사전에 감지하고, 코드 가독성을 향상시키며, 개발자 자신감을 높여줍니다. 하지만 TypeScript의 힘은 단순히 JavaScript에 타입을 추가하는 것을 훨씬 뛰어넘습니다. 프로젝트 루트에 자리한 tsconfig.json
파일은 숨겨진 건축가 역할을 하며, TypeScript 코드가 어떻게 컴파일되는지를 조용히 조율합니다. 종종 개발자들은 기본 설정이나 기본적인 구성에 의존하며 잠재력을 표면적으로만 긁는 경우가 많습니다. 그러나 컴파일 옵션에 대한 더 깊은 이해와 전략적인 활용은 코드 품질을 극적으로 향상시키고, 개발 워크플로우를 간소화하며, 수많은 일반적인 함정을 예방할 수 있습니다. 이 문서는 tsconfig.json
의 베일을 걷어내고, 더 높은 품질의 유지보수 가능한 TypeScript 코드를 작성하는 데 필수적인 주요 컴파일 옵션을 공개하는 것을 목표로 합니다.
tsconfig.json 해독하기: TypeScript 프로젝트의 설계도
특정 옵션에 대해 자세히 알아보기 전에 tsconfig.json
에 대한 기본적인 이해를 확립해 보겠습니다. 본질적으로 tsconfig.json
은 TypeScript 프로젝트를 컴파일하는 데 필요한 루트 파일과 컴파일러 옵션을 지정하는 JSON 파일입니다. 어떤 파일을 포함할지부터 타입 검사가 얼마나 엄격해야 하는지, 어떤 대상 JavaScript 버전을 출력할지까지 TypeScript 컴파일러(tsc)가 어떻게 동작해야 하는지를 알려줍니다.
tsconfig.json
에서 가장 중요한 최상위 속성은 다음과 같습니다.
compilerOptions
: 이 객체는 TypeScript가 코드를 컴파일하는 방식을 결정하는 대부분의 구성 옵션을 포함합니다.include
: 프로그램에 포함할 파일을 지정하는 glob 패턴 배열입니다.exclude
:include
에서 지정되었더라도 프로그램에서 제외할 파일을 지정하는 glob 패턴 배열입니다.files
: 프로그램에 포함할 명시적인 파일 경로 배열입니다. 큰 프로젝트에서는include
/exclude
보다 덜 일반적입니다.extends
: 설정을 상속하기 위해 다른tsconfig.json
파일로의 경로를 지정하는 문자열입니다. 모노레포 또는 기본 설정 공유에 매우 좋습니다.
이제 코드 품질과 개발자 경험에 직접적인 영향을 미치는 몇 가지 중요한 compilerOptions
를 살펴보겠습니다.
타입 안전성 및 코드 신뢰성 향상
1. strict
이 단일 boolean 옵션은 TypeScript의 엄격함의 초석입니다. strict: true
를 설정하면 단일 플래그로 더 엄격한 타입 검사 옵션 모음이 활성화됩니다. 모든 새 프로젝트, 심지어 기존 프로젝트를 마이그레이션하는 데에도 강력히 권장됩니다.
// tsconfig.json { "compilerOptions": { "strict": true } }
strict
가 true
이면 다음이 암시적으로 활성화됩니다.
-
noImplicitAny
: 암시적으로any
타입을 가진 표현식과 선언에 플래그를 지정합니다. 이는 TypeScript가 추론할 수 없는 변수, 매개변수 또는 반환 값을 명시적으로 타입 지정하도록 강제하여 암묵적인 타입 오류를 방지합니다.// noImplicitAny 활성화 function greet(name) { // 오류: 매개변수 'name'에는 암시적으로 'any' 타입이 있습니다. console.log(`Hello, ${name}!`); } function greetExplicit(name: string) { // OK console.log(`Hello, ${name}!`); }
-
strictNullChecks
: 명시적으로 허용되지 않는 한null
및undefined
가 타입에 할당될 수 없도록 합니다 (예:string | null
). 이는 "undefined의 속성을 읽을 수 없습니다" 또는 "null" 런타임 오류를 방지하는 데 매우 강력합니다.// strictNullChecks 활성화 let username: string = "Alice"; username = null; // 오류: 'null' 타입은 'string' 타입에 할당할 수 없습니다. let optionalUsername: string | null = "Bob"; optionalUsername = null; // OK
-
strictFunctionTypes
: 함수 매개변수에 대한 타입 검사를 개선합니다. 함수 매개변수가 역변환 가능(contravariant)하도록 보장하여 고차 함수에서 더 건전한 타입 관계를 이끌어냅니다. -
strictPropertyInitialization
: 클래스 속성이 생성자나 속성 초기화에서 초기화되어야 합니다. 이는 속성이 접근 시undefined
가 되는 것을 방지하는 데 도움이 됩니다.// strictPropertyInitialization 활성화 class User { name: string; // 오류: 속성 'name'에는 초기화가 없으며 생성자에서 확실히 할당되지 않았습니다. age: number = 20; // OK constructor(name: string) { this.name = name; // OK } }
-
noImplicitThis
: 암묵적으로any
로 타이핑된this
표현식에 플래그를 지정합니다. 콜백 및 메서드에서this
를 올바르게 타이핑하는 데 중요합니다. -
alwaysStrict
: 출력 파일 맨 위에"use strict";
를 생성하여 JavaScript의 엄격 모드를 강제합니다. 이는 일반적인 코딩 실수를 포착하고 "안전하지 않은" 작업을 방지합니다.
권장 사항: 항상 새 프로젝트를 "strict": true
로 시작하세요. 레거시 코드베이스에서 작업 중인 경우, 전체 엄격함에 도달할 때까지 이러한 엄격한 옵션을 하나씩 점진적으로 활성화하세요.
2. noUnusedLocals
및 noUnusedParameters
이 옵션은 죽은 코드를 조기에 감지하여 깨끗하고 간결한 코드를 유지하는 데 탁월합니다.
noUnusedLocals
: 선언되었으나 읽히지 않은 지역 변수에 대한 오류를 보고합니다.noUnusedParameters
: 선언되었으나 함수 본문에서 사용되지 않은 매개변수에 대한 오류를 보고합니다.
// tsconfig.json { "compilerOptions": { "noUnusedLocals": true, "noUnusedParameters": true } }
// noUnusedLocals 및 noUnusedParameters 활성화 function calculate(x: number, y: number, unusedParam: number): number { // 오류: 'unusedParam'은 선언되었지만 그 값은 전혀 읽히지 않았습니다. const result = x + y; // OK const temp = 10; // 오류: 'temp'는 선언되었지만 그 값은 전혀 읽히지 않았습니다. return result; }
권장 사항: 이 두 옵션을 모두 활성화하여 개발자가 불필요한 코드를 제거하도록 장려하여 코드베이스를 더 작고 이해하기 쉽게 만드세요.
3. noFallthroughCasesInSwitch
이 옵션은 case
블록에 명시적인 break
, return
또는 throw
없이 다음 case
로 "넘어가는" switch
문에서 미묘한 버그를 방지하는 데 도움이 됩니다.
// tsconfig.json { "compilerOptions": { "noFallthroughCasesInSwitch": true } }
// noFallthroughCasesInSwitch 활성화 function handleStatus(status: "success" | "error" | "pending") { switch (status) { case "success": console.log("Operation successful!"); // 실수로 넘어감! case "error": // 오류: switch 문의 fallthrough case. console.log("Operation failed!"); break; case "pending": console.log("Operation pending..."); break; } }
권장 사항: 항상 이 옵션을 활성화하세요. 디버깅하기 어려운 논리 오류의 매우 일반적인 원인을 포착합니다.
모듈 해석 및 프로젝트 구조 개선
4. baseUrl
및 paths
이 옵션들은 긴 상대 임포트 경로 (../../../components/Button
)를 피하는 데 도움이 되는 대규모 프로젝트에서 모듈 임포트를 관리하는 데 필수적입니다.
baseUrl
: 비상대 모듈 이름을 해석하기 위한 기본 디렉토리를 지정합니다.paths
:baseUrl
을 기준으로 모듈 요청을 매핑할 수 있게 해줍니다.
// tsconfig.json { "compilerOptions": { "baseUrl": "src", // 아래 경로들은 'src'를 기준으로 상대적입니다. "paths": { "@components/*": ["components/*"], // 이제 '@components/Button'에서 임포트할 수 있습니다. "@utils/*": ["utils/*"], "@styles/*": ["styles/*"] } } }
이 구성으로 다음 대신에:
import { Button } from '../../components/Button'; import { formatDate } from '../../../utils/date';
다음과 같이 작성할 수 있습니다:
import { Button } from '@components/Button'; import { formatDate } from '@utils/date';
권장 사항: 중간 규모에서 대규모 프로젝트에서 baseUrl
과 paths
를 사용하여 임포트를 단순화하고, 가독성을 향상시키며, 리팩토링을 쉽게 만드세요. 또한 모듈 번들러(Webpack 또는 Rollup과 같은) 또는 Node.js 런타임이 이러한 경로 별칭을 이해하도록 구성해야 합니다.
컴파일러 출력 및 대상별 특정 사항
5. target
및 lib
이 옵션은 TypeScript 코드를 컴파일하는 JavaScript 버전과 타입 검사 중에 사용할 수 있는 내장 API를 제어합니다.
target
: 컴파일된 JavaScript에 대한 ECMAScript 대상 버전을 지정합니다. 이는 어떤 JavaScript 기능이 폴리필되거나 다르게 방출되는지에 영향을 미칩니다. 일반적인 값에는ES5
,ES2015
(ES6),ES2018
,ES2020
,ESNext
가 있습니다.lib
: 타입 정의에 포함할 환경 및 API 표준 목록을 지정합니다. 예를 들어,ES5
를 대상으로 하지만Promise
를 사용하는 경우ES2015.Promise
(또는 더 일반적인ES2015
또는ESNext
)를 포함해야 합니다.
// tsconfig.json { "compilerOptions": { "target": "ES2020", // ES2020 JavaScript 출력 "lib": ["ES2020", "DOM", "DOM.Iterable"] // ES2020 기능, DOM API, DOM 반복 가능 타입 포함 } }
ES5
를 대상으로 하지만 lib
에서 DOM
을 누락하면 TypeScript는 document
, window
등을 알지 못하고 오류를 보고합니다.
권장 사항: 대상 환경(브라우저, Node.js)이 완전히 지원하는 최신 JavaScript 버전을 target
으로 설정하고, 호환성과 최신 기능을 균형 있게 유지하세요. 런타임 환경과 원하는 API 가용성에 맞춰 lib
를 명시적으로 선언하세요.
기타 주목할 만한 옵션
jsx
: React 또는 기타 JSX 기반 프레임워크에 필수적이며, JSX가 처리되는 방식(예:react
,react-jsx
,react-jsxdev
)을 지정합니다.esModuleInterop
: CommonJS와 ES 모듈 간의 상호 운용성에 중요합니다. 기본 내보내기가 없는 모듈에서 기본 임포트를 허용하려면true
로 설정하세요.declaration
:true
이면 TypeScript는 JavaScript 파일과 함께.d.ts
선언 파일을 생성합니다. 이는 다른 TypeScript 프로젝트에서 사용할 수 있는 라이브러리를 만드는 데 필수적입니다.sourceMap
:true
이면 TypeScript는 컴파일된 JavaScript를 원래 TypeScript 소스로 디버깅하는 데 중요한.map
파일을 생성합니다.
결론: 신중한 구성을 통한 탁월함 구축
tsconfig.json
파일은 단순히 보일러플레이트 구성 그 이상입니다. 이는 효과적으로 사용될 때 TypeScript 프로젝트의 품질, 유지보수성 및 신뢰성을 크게 향상시킬 수 있는 강력한 도구입니다. strict
, noImplicitAny
, strictNullChecks
, noUnusedLocals
, noFallthroughCasesInSwitch
, baseUrl
, paths
와 같은 옵션을 신중하게 선택하고 이해함으로써 TypeScript 컴파일러가 경계하는 수호자 역할을 하여 오류를 조기에 감지하고 모범 사례를 적용하도록 할 수 있습니다. 잘 구성된 tsconfig.json
은 더 깨끗한 코드, 더 적은 런타임 버그, 더 즐거운 개발 경험으로 이어져 궁극적으로 강력하고 신뢰할 수 있는 코드베이스를 육성합니다. tsconfig.json
을 프로젝트의 탁월함 설계도로 받아들이고, 우수한 코드 품질을 위해 처음부터 견고한 기반을 구축하세요.