JavaScript 프로젝트에 TypeScript 점진적으로 도입하기
배경
회사 프로젝트가 JavaScript로만 작성되어 있었는데, 코드베이스가 커지면서 런타임 에러가 잦아졌다. 특히 API 응답 구조가 변경되거나 함수 인자를 잘못 넘기는 실수가 반복됐다. TypeScript 도입을 검토했지만, 한 번에 전환하기엔 규모가 커서 점진적 마이그레이션 전략을 택했다.
설정
tsconfig.json에서 핵심은 allowJs와 checkJs 옵션이었다.
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"allowJs": true,
"checkJs": false,
"jsx": "react",
"strict": false,
"esModuleInterop": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
allowJs를 켜면 .js와 .ts 파일을 함께 빌드할 수 있다. strict는 나중에 켜기로 했다.
진행 방식
- 유틸 함수부터
.ts로 전환 - 타입 정의가 명확한 모듈 우선 작업
- API 응답 인터페이스 작성
// types/api.ts
export interface User {
id: number;
name: string;
email: string;
createdAt: string;
}
export interface ApiResponse<T> {
data: T;
status: number;
message?: string;
}
기존 JavaScript 파일에서도 import해서 JSDoc으로 타입 힌트를 줄 수 있었다.
// legacy.js
/** @type {import('./types/api').User} */
const user = fetchUser();
마주친 문제
- 써드파티 라이브러리 타입 정의 부족:
@types/패키지가 없으면declare module로 임시 처리 - any 남발 유혹: 급할 땐 any 쓰되, TODO 주석 남겨서 나중에 개선
- 빌드 속도: ts-loader 대신 babel-loader + @babel/preset-typescript 조합이 더 빨랐다
결과
2개월간 핵심 모듈 30% 정도를 TypeScript로 전환했다. 런타임 에러가 눈에 띄게 줄었고, IDE 자동완성 품질이 올라가 개발 속도도 개선됐다. 남은 코드는 내년 상반기까지 순차적으로 전환할 예정이다.