TypeScript 4.0 적용 후기 - 재택 근무 중 레거시 코드베이스 마이그레이션

배경

재택 근무가 시작된 후 3개월간 진행했던 레거시 프로젝트의 TypeScript 마이그레이션을 완료했다. 2년 전 작성된 JavaScript 코드베이스(약 3만 줄)를 TypeScript 4.0으로 전환하는 작업이었다.

적용 전략

한 번에 전환하는 것은 리스크가 컸기 때문에 점진적 접근을 택했다.

  1. allowJs, checkJs 옵션으로 시작
  2. 핵심 유틸리티 함수부터 .ts 전환
  3. API 타입 정의 작성
  4. 컴포넌트 단위로 순차 전환
// 초기 tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "allowJs": true,
    "checkJs": false,
    "strict": false,
    "noImplicitAny": false
  }
}

마주한 문제들

1. 암묵적 any 남발

레거시 코드에서 가장 많이 발견된 패턴이었다. API 응답 타입이 정의되지 않아 모든 곳에서 any로 추론되었다.

// Before
const fetchUser = async (id) => {
  const res = await api.get(`/users/${id}`);
  return res.data; // any
};

// After
interface User {
  id: number;
  email: string;
  role: 'admin' | 'user';
}

const fetchUser = async (id: number): Promise<User> => {
  const res = await api.get<User>(`/users/${id}`);
  return res.data;
};

2. 타입 가드 필요성

런타임 체크가 없던 코드에 타입 가드를 추가해야 했다.

function isErrorResponse(res: unknown): res is { error: string } {
  return typeof res === 'object' && res !== null && 'error' in res;
}

3. 빌드 시간 증가

초기에는 빌드 시간이 2배 가까이 증가했다. skipLibCheck: true 추가와 incremental 컴파일로 개선했다.

결과

  • 런타임 에러 30% 감소 (프로덕션 로그 기준)
  • IDE 자동완성으로 개발 속도 체감상 향상
  • 리팩토링 시 타입 에러로 사이드 이펙트 사전 발견

재택 근무 중이라 커뮤니케이션 오버헤드가 걱정됐는데, 타입 정의가 문서 역할을 해서 오히려 도움이 되었다. 다음 프로젝트는 처음부터 TypeScript로 시작할 예정이다.

TypeScript 4.0 적용 후기 - 재택 근무 중 레거시 코드베이스 마이그레이션