기존 JavaScript 프로젝트에 TypeScript 점진적으로 도입하기

배경

작년부터 운영 중인 React 프로젝트에 TypeScript를 도입하기로 했다. 컴포넌트가 100개가 넘는 상황에서 한 번에 전환하는 건 무리였고, 점진적 마이그레이션 전략을 택했다.

초기 설정

먼저 tsconfig.json을 생성하고 기존 JS 파일과 공존할 수 있도록 설정했다.

{
  "compilerOptions": {
    "target": "es5",
    "module": "esnext",
    "lib": ["dom", "es2015"],
    "jsx": "react",
    "allowJs": true,
    "checkJs": false,
    "strict": false,
    "esModuleInterop": true
  },
  "include": ["src/**/*"]
}

allowJs: true로 JS와 TS 파일을 섞어 쓸 수 있게 했다. strict: false로 시작해서 타입 에러에 막히지 않도록 했다.

마이그레이션 순서

  1. 유틸 함수부터 시작 - 의존성이 적고 테스트하기 쉬움
  2. 타입 정의 파일 작성 - 자주 쓰는 도메인 모델부터
  3. 신규 컴포넌트는 무조건 TS로 작성
  4. 기존 컴포넌트는 수정할 때 TS로 전환
// types/user.ts
export interface User {
  id: number;
  email: string;
  name: string;
  createdAt: string;
}

export interface ApiResponse<T> {
  data: T;
  error?: string;
}

겪은 문제

1. any 남발

초기엔 타입을 모르는 곳마다 any를 썼다. 점차 unknown으로 바꾸거나 제대로 된 타입을 정의하는 방향으로 개선 중이다.

2. 서드파티 라이브러리

@types 패키지가 없는 라이브러리들이 있었다. d.ts 파일을 직접 작성하거나, 일단 declare module로 우회했다.

// types/custom.d.ts
declare module 'some-library' {
  export function someFunc(param: string): void;
}

현재 상태

전체 파일의 약 30%를 TS로 전환했다. 타입 체크 덕분에 props 전달 실수나 undefined 에러를 몇 건 사전에 잡았다. 아직 strict: true는 부담스럽지만, 내년 초쯤엔 전환 완료가 목표다.

기존 JavaScript 프로젝트에 TypeScript 점진적으로 도입하기