JavaScript 프로젝트에 TypeScript 점진적으로 도입하기
배경
3년간 운영 중인 Node.js API 서버에 TypeScript를 도입하기로 했다. 런타임 에러가 잦았고, 팀원이 늘면서 코드베이스 파악이 어려워졌기 때문이다.
적용 전략
전체를 한 번에 마이그레이션하는 대신 점진적 적용 방식을 택했다.
1. tsconfig.json 설정
{
"compilerOptions": {
"allowJs": true,
"checkJs": false,
"noEmit": true,
"target": "es2017",
"module": "commonjs",
"strict": false
},
"include": ["src/**/*"]
}
allowJs를 true로 두어 .js와 .ts 파일이 공존할 수 있게 했다. strict는 나중에 켜기로 했다.
2. 우선순위 정하기
- 유틸 함수부터 시작 (의존성 적음)
- 새로 작성하는 코드는 무조건 .ts
- 버그 수정 시 해당 파일만 마이그레이션
3. 타입 정의 추가
// before (utils/validator.js)
function validateEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
// after (utils/validator.ts)
function validateEmail(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
간단한 함수부터 타입을 명시했다.
4. any 타입 허용
초반엔 복잡한 객체는 any로 두고 넘어갔다. 완벽주의를 추구하면 진행이 안 된다.
function processData(data: any) {
// 일단 any로 두고 나중에 interface 정의
}
마주친 문제들
라이브러리 타입 정의 없음
@types/ 패키지가 없는 라이브러리들이 많았다. .d.ts 파일을 직접 작성하거나 declare module로 임시 처리했다.
빌드 프로세스 변경
ts-node로 개발 서버를 띄우고, 배포 시엔 tsc로 컴파일하도록 수정했다. CI/CD 파이프라인도 함께 변경했다.
결과
2개월간 전체 코드의 약 40%를 마이그레이션했다. 타입 체크 덕분에 배포 전 잡아낸 버그가 여럿 있었고, VSCode의 자동완성이 확실히 정확해졌다.
아직 갈 길이 멀지만, 점진적 접근이 정답이었다고 생각한다.