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

배경

회사 메인 프로젝트가 JavaScript + React로 2년간 운영되면서 코드베이스가 커졌다. 런타임 에러가 잦아지고 리팩토링 부담이 증가해 TypeScript 도입을 결정했다.

한 번에 전환하는 것은 일정상 불가능해서 점진적 마이그레이션 전략을 택했다.

마이그레이션 단계

1. 설정 준비

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

tsconfig.json에서 allowJs: true, checkJs: false로 설정해 기존 JS 파일과 공존 가능하게 했다.

2. 우선순위 정하기

  • 유틸 함수부터 시작 (의존성 적음)
  • 자주 수정되는 컴포넌트
  • 타입 에러가 자주 발생하는 영역

3. 실제 변환 작업

// Before: utils/format.js
export const formatPrice = (price) => {
  return `${price.toLocaleString()}원`;
};

// After: utils/format.ts
export const formatPrice = (price: number): string => {
  return `${price.toLocaleString()}원`;
};

간단한 함수부터 .ts 확장자로 변경하고 타입을 추가했다.

4. Props 타입 정의

interface ProductCardProps {
  id: number;
  name: string;
  price: number;
  onAddToCart: (id: number) => void;
}

const ProductCard: React.FC<ProductCardProps> = ({ id, name, price, onAddToCart }) => {
  // ...
};

React 컴포넌트는 Props 인터페이스를 먼저 정의하니 자동완성과 에러 검출이 확실히 개선됐다.

마주친 문제들

any 남발 유혹

복잡한 타입은 처음엔 any로 우회하고 싶었지만, 나중에 더 힘들어진다. 모르면 unknown을 쓰고 타입 가드를 추가하는 방식으로 접근했다.

라이브러리 타입 정의 누락

일부 라이브러리는 @types가 없어서 직접 .d.ts 파일을 작성해야 했다.

결과

3개월간 약 40%의 파일을 TypeScript로 전환했다. 타입 관련 버그가 배포 전에 잡히기 시작했고, IDE 자동완성으로 생산성도 올랐다.

완벽한 타입 커버리지보다는 점진적으로 개선하는 것이 현실적이었다.

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