프로젝트에 TypeScript 도입하기 - 점진적 마이그레이션 전략
배경
회사 프로젝트가 커지면서 타입 관련 버그가 잦아졌다. API 응답 구조 변경, 함수 파라미터 실수 등 런타임 에러가 반복되어 TypeScript 도입을 검토했다.
전체 코드베이스를 한 번에 마이그레이션하기엔 리스크가 컸다. 점진적 적용 방식을 택했다.
설정
// tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": ["es2015", "dom"],
"allowJs": true,
"checkJs": false,
"jsx": "react",
"outDir": "./dist",
"strict": false,
"noImplicitAny": false,
"esModuleInterop": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
allowJs를 켜고 strict는 끈 상태로 시작했다. 기존 JS 파일과 새로 작성하는 TS 파일이 공존할 수 있다.
마이그레이션 순서
- 유틸리티 함수부터: 의존성이 적고 테스트가 있는 파일을 먼저
.ts로 변환 - 타입 정의 파일 작성: API 응답, Props 등 자주 쓰는 타입을
types.ts에 정의 - 신규 컴포넌트는 TS로: 새로 만드는 파일은 무조건 TypeScript로 작성
- 점진적 strict 옵션 활성화: 안정화되면
noImplicitAny등을 하나씩 켬
실제 적용 예시
// Before (JS)
function fetchUser(userId) {
return fetch(`/api/users/${userId}`).then(res => res.json());
}
// After (TS)
interface User {
id: number;
name: string;
email: string;
}
function fetchUser(userId: number): Promise<User> {
return fetch(`/api/users/${userId}`).then(res => res.json());
}
API 함수에 타입을 붙이니 호출하는 쪽에서 자동완성이 동작했다. VSCode의 인텔리센스 지원도 확실히 좋아졌다.
소감
처음엔 러닝커브가 부담스러웠지만, 일주일 정도 적응하니 생산성이 오히려 올랐다. 특히 리팩토링할 때 타입 에러로 사이드 이펙트를 미리 발견할 수 있었다.
당장 전체를 마이그레이션하지 않아도 된다는 점이 가장 큰 장점이었다. 팀원들도 부담 없이 따라올 수 있었다.