타입스크립트를 사용하여 자바스크립트 라이브러리를 개발할 때, 또는 기존 자바스크립트 라이브러리를 타입스크립트 프로젝트에서 활용할 때 가장 중요한 요소 중 하나가 바로 타입 정의 파일(.d.ts) 입니다. 하지만 세상에는 수많은 자바스크립트 라이브러리가 존재하고, 이 모든 라이브러리에 대해 개발자가 직접 .d.ts 파일을 작성하는 것은 비효율적이고 거의 불가능에 가깝습니다.
이러한 문제를 해결하기 위해 등장한 것이 바로 DefinitelyTyped 프로젝트와 npm의 @types 스코프 패키지입니다.
DefinitelyTyped는 수많은 자바스크립트 라이브러리에 대한 고품질의 타입 정의 파일을 제공하는 오픈 소스 프로젝트입니다. 전 세계의 개발자들이 자발적으로 참여하여 각 라이브러리의 .d.ts 파일을 작성하고 유지보수하며, 이를 통해 타입스크립트 사용자들이 자바스크립트 생태계를 타입 안전하게 활용할 수 있도록 돕습니다.
DefinitelyTyped에 기여된 모든 타입 정의 파일은 자동으로 npm의 @types 스코프로 패키징되어 배포됩니다. 즉, lodash 라이브러리에 대한 타입 정의는 npm install @types/lodash 명령어로 설치할 수 있게 됩니다.
이 @types 패키지들은 실제 자바스크립트 코드를 포함하지 않고, 오직 해당 라이브러리의 타입 정의(.d.ts 파일)만을 포함합니다. 타입스크립트 컴파일러는 기본적으로 node_modules/@types 디렉토리를 자동으로 검색하여 필요한 타입 정의 파일을 찾습니다.
사용 예시
lodash 라이브러리를 타입스크립트 프로젝트에서 사용하려고 할 때:
lodash 라이브러리 설치
npm install lodash
lodash에 대한 타입 정의 설치
npm install --save-dev @types/lodash
--save-dev 플래그는 개발 의존성(devDependencies)으로 설치하여, 실제 프로덕션 환경에는 포함되지 않음을 나타냅니다. 타입 정의 파일은 컴파일 시에만 필요하기 때문입니다.
이제 타입스크립트 코드에서 lodash를 가져와 사용하면, 타입스크립트 컴파일러는 node_modules/@types/lodash 경로의 .d.ts 파일을 참조하여 _ 객체의 모든 메서드와 속성에 대한 정확한 타입 정보를 제공합니다.
import _ from 'lodash'; // 'lodash' 모듈을 가져옴 (CommonJS 모듈이므로 esModuleInterop: true 권장)const numbers = [1, 2, 3, 4, 5];const sum = _.sum(numbers); // sum은 number 타입으로 추론됩니다. (정확한 매개변수 힌트 제공)console.log(sum); // 15const shuffled = _.shuffle(numbers); // shuffled는 number[] 타입으로 추론됩니다.console.log(shuffled);// _.sortBy(numbers, 'invalidKey'); // Error: 'string' 형식은 'lodash.ValueIteratee<number>' 형식에 할당될 수 없습니다. // 타입 정의 덕분에 잘못된 인자 사용 시 오류를 즉시 감지합니다.
만약 특정 자바스크립트 라이브러리에 대한 @types 패키지가 존재하지 않는다면, 다음 두 가지 방법 중 하나를 선택할 수 있습니다.
직접 .d.ts 파일 작성:
해당 라이브러리의 외부 API를 파악하여 직접 앰비언트 모듈 선언(.d.ts 파일)을 작성합니다 (8장 3절 참조). 이 방법은 라이브러리의 규모가 작거나, 사용하려는 부분이 제한적일 때 유용합니다.
my-lib-declaration.d.ts
declare module 'my-custom-js-lib' { export function doSomething(param: string): number;}
app.ts
import { doSomething } from 'my-custom-js-lib';doSomething('hello');
any 타입으로 사용 (최후의 수단):
정의된 타입이 없어 타입 안정성을 포기하고 any 타입으로 라이브러리를 사용하는 방법입니다.
app.ts
import SomeUntypedLib from 'some-untyped-lib'; // 타입 정보가 없으므로 SomeUntypedLib는 any 타입const lib = new SomeUntypedLib();lib.doSomethingElse(123); // 타입 검사 없이 허용
tsconfig.json 파일의 compilerOptions에서 types와 typeRoots 옵션을 사용하여 타입 정의 파일의 검색 방식을 더 세밀하게 제어할 수 있습니다.
typeRoots: node_modules/@types와 같이 타입 정의 파일을 검색할 루트 디렉토리 목록을 지정합니다. 기본적으로 node_modules/@types가 포함되어 있으므로, 대부분의 경우 명시할 필요는 없습니다. 하지만 @types가 아닌 특정 커스텀 타입 정의 경로를 추가하고 싶을 때 사용합니다.
types: 컴파일러가 전역 타입 선언으로 포함할 @types 패키지 목록을 지정합니다. 이 옵션이 없으면 typeRoots에 있는 모든 @types 패키지가 자동으로 포함되지만, types를 명시하면 여기에 나열된 패키지만 포함됩니다.
"compilerOptions": { "types": ["node", "jest"] // 오직 @types/node와 @types/jest만 포함하고 싶을 때}
이는 번들링 크기를 줄이거나, 불필요한 전역 타입 충돌을 피하고 싶을 때 유용합니다.
DefinitelyTyped와 @types는 타입스크립트 생태계의 핵심적인 부분이며, 자바스크립트와 타입스크립트 간의 호환성을 보장하는 가장 중요한 메커니즘입니다. 이를 통해 수많은 기존 자바스크립트 라이브러리를 타입 안전하게 활용할 수 있게 되어, 타입스크립트의 도입 장벽을 크게 낮추고 개발 생산성을 향상시키는 데 기여합니다. 새로운 라이브러리를 사용할 때는 항상 @types 패키지의 존재 여부를 먼저 확인하는 습관을 들이는 것이 좋습니다.