[Typescript] 의외로 까다로운 @types 의존성 관리

김유진·2023년 5월 17일
2

Effective-TypeScript

목록 보기
22/28
post-thumbnail

이번 Item에서는 devDependenciesdependencies에서 타입스크립트와 관련된 버전을 관리하는 데 있어 마주하였던 어려움에 대해서 궁금했던 점들에 대해서 알 수 있었다.
사실 typescript를 이용하면서 내가 사용하고 있는 모듈이나 라이브러리들과 버전이 맞지 않아 어려번 고생한 적이 있었기 때문에 이번 아이템은 조금 집중해서 읽어 보고 이해하려고 노력했던 것 같다.

@types는 devDependencies에 있는 이유

프로젝트 파일의 package.json을 보면 아래와 같이 devDependencies에 @types 설치가 기록되어 있다.

왜 dependencies가 아니라 devDependencies에 있나요..?

dependencies는 현재 프로젝트를 진행하는 데 있어 필수적인 라이브러리들이 들어간다. 만약 다른 개발자가 해당 프로젝트를 클론받아 install을 진행하게 되면 dependencies에 있는 모든 패키지들이 설치될 것이다. 그러나 타입스크립트는 현재 프로젝트를 개발하고 테스트하는데에만 사용되고, 런타임에는 필요가 없기 때문에 dev를 통해 의존성을 관리해야 하는 것이다.

타입스크립트를 사용한다면 패키지의 의존성을 꼼꼼히 체크하도록 하자.

1. 타입스크립트의 자체 의존성 체크하기

타입스크립트는 시스템 레벨로 설치하는 것은 좋지 않다. (그래서 devdependencies에 넣는 것) 그 이유는 아래와 같다.

  • 팀원들 모두가 항상 동일한 버전을 설치한다는 보장이 없음
  • 프로젝트를 셋업할 때, 별도의 단계가 추가됨

하지만 이에 대해서는 내가 직접 신경쓸 필요가 없다. 사람들이 주로 사용하는 vscode나 intellij와 같은 IDE 및 빌드 도구는 타입스크립트 버전을 devDependencies를 통해 인식하기 때문이다.

2. 타입 의존성(@types)를 고려하기

사용하는 라이브러리에 타입 선언이 포함되어 있지 않더라도, DefinitelyTyped라는 곳에서 자바스크립트 라이브러리의 타입을 유지보수하고 있기 때문에 타입 정보를 얻어보자.

만약 프로젝트를 react 라이브러리를 이용하여 진행하고 싶지만, 타입스크립트를 추가로 이용해야 한다면 @types/react를 이용하여 type에 대한 의존성을 관리하여 타입 정보를 얻어올 수 있도록 해야 한다.

오류의 늪에 빠지게 하는 타입 의존성 관리

강의를 듣거나 타입스크립트를 이용하여 프로젝트를 하다 보면 아래 의문을 심심치 않게 마주칠 수 있다.

위의 사진은 제로초님이 강의하는 인프런 강의 중 질의응답 페이지에서 많은 따봉을 많이 받은 글이다. socket을 사용하게 해 주는 라이브러리의 버전이 현재 진행하고 있는 프로젝트의 ts버전과 맞지 않아서 오류가 발생하는 모양이다.
이렇게 타입스크립트 버전은 개발하는 입장에서 번거롭게 만들 수 있다. 그렇기 때문에 더더욱이 버전과 의존성 관리에 대하여 잘 이해하고 있어야 하며 문제를 빠르게 해결할 수 있는 능력을 가지고 있어야 한다.
아래 세 가지를 고려하면서 개발을 하도록 해 보자..

  • 라이브러리의 버전
  • 타입 선언(@types)의 버전
  • 타입스크립트의 버전

실제로 나는 마지막인 타입스크립트의 버전 때문에 정말 많은 ... 어려움을 겪은 적이 있다. 이제 앞으로는 타입스크립트 의존성 관리에 휘둘리지(?)않을 것이다..

대부분 타입스크립트를 사용하게 된다면 아래와 같은 과정을 겪게 된다.

npm install react
npm install --save-dev @types/react

이렇게 설치하게 된다면, 라이브러리와 타입 정보의 버전이 별도로 관리되는 것이다. 이렇게 버전을 관리하게 되면 마주하게 될 수도 있는 오류를 미리 알아보자.

1. 라이브러리를 업데이트 했지만, 실수로 타입 선언은 업데이트하지 않는 경우

이럴 경우 라이브러리의 새로운 기능을 이용하고자 할 때 오류를 마주하게 된다. 이러한 경우, 타입 선언을 업데이트 해주면 되나 아직 타입 선언이 준비가 안되어 있을 수 있다. 이러면 보강 기법을 사용하여 사용하려는 새로운 함수와 메서드의 타입 정보를 프로젝트 자체에 추가해주면 된다.

2. 라이브러리보다 타입 선언의 버전이 최신인 경우

내가 아까 예시로 들었던 질문의 경우와 같은 문제이다. 이 때는 타입 선언의 버전을 내리거나, 라이브러리의 버전을 올리면 된다.

3. 프로젝트에서 사용하는 타입스크립트 버전보다 라이브러리에서 필요로 하는 타입스크립트 버전이 최신인 경우

이 경우를 내가 가장 많이 겪었던 문제인데...
나는 주로 프로젝트의 타입스크립트 버전을 올리거나/내리는 방식으로 해결했다. 라이브러리의 타입을 변경하는 것도 있겠지만, 이럴 경우 모듈 하나하나 사용하는 것에 대해 타입 선언을 다시 해주거나 사용 잘 하고 있던 함수도 못쓰게 되는 경우도 있었기 때문. 그리고 솔직히 몇버전까지 내려야지 가장 효율적으로 개발할 수 있을 지 감이 잘 안잡힌다. 그래서 자체적으로 타입스크립트 버전을 내리거나 올리는 것이 마음 편했던 것 같다.

4. @types의 의존성이 중복될 경우

이럴 경우 걍 node_modules를 쓰지 말자!!! 아님 삭제하고 다시 깔던지.(이걸 안쓰면 애초에 중복되어서 깔릴 경우가 별로 없음) 하지만 내가 마음대로 프로젝트의 패키지를 관리할 수 있는 것이 아니므로..

npm ls @types/foo

를 보아서 폴더 구조를 보고 타입 중복이 발생한 폴더를 찾아본다.

라이브러리에서 사용된 타입 찾아보기

그리고 앞으로 타입스크립트로 작성된/자바스크립트로 작성된 라이브러리의 타입들에 대하여 알아봐야 할 일들이 있을 텐데, 타입스크립트로 작성된 라이브러리 같은 경우에는 애초에 라이브러리 안에 타입 선언이 존재할 테지만, 자바스크립트로 작성된 라이브러리는 타입 선언이 위에 언급한 DefinitelyTyped에 공개되고 있으니 궁금하다면 한번씩 찾아보면 좋을 듯 하다.

또한 가끔 라이브러리에서 타입 정보를 익스포트하지 않아서 타입 선언에 대하여 찾아보기 어려울 때가 있다.

interface SecretName {
  first: string;
  last: string;
}

interface SecretSanta {
  name: SecretName;
  gift: string;
}
export function getGift(name: SecretName, gift: string): SecretSanta {
  //...
}

이럴 경우 getGift에 대한 타입은 SecretSanta라고 알 수 있겠지만, 라이브러리를 사용하는 입장에서는 SecretName이나 SecretSanta의 타입을 import해서 사용하고 싶을 수도 있을 것이다.
그럼 아래와 같이 작성해서 직접 추출을 해보자.

type MySanta = ReturnType<typeof getGift>; //SecretSanta
type MyName = Parameters<typeof getGift>[0]; //SecretName

되도록이면 많이많이 export 해주세요!! 천재 개발자님들 🥹

0개의 댓글