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 자동완성으로 생산성도 올랐다.
완벽한 타입 커버리지보다는 점진적으로 개선하는 것이 현실적이었다.