JavaScript 프로젝트에 TypeScript 점진적으로 도입하기
배경
운영 중인 Node.js API 서버에 TypeScript를 도입하기로 했다. 전체 코드를 한 번에 마이그레이션할 수 없어서 점진적 도입 방식을 선택했다.
초기 설정
먼저 필요한 패키지를 설치했다.
npm install --save-dev typescript @types/node @types/express
tsconfig.json은 기존 JS와 공존할 수 있도록 설정했다.
{
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"allowJs": true,
"checkJs": false,
"outDir": "./dist",
"rootDir": "./src",
"strict": false,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
핵심은 allowJs: true와 strict: false다. 기존 JS 파일을 그대로 두고 새 파일만 TS로 작성할 수 있다.
적용 전략
- 새로 작성하는 파일은
.ts로 작성 - 유틸리티 함수부터 타입 적용
- 버그 수정 시 해당 파일을 TS로 전환
// utils/validator.ts
export interface ValidationResult {
isValid: boolean;
errors: string[];
}
export function validateEmail(email: string): ValidationResult {
const errors: string[] = [];
if (!email.includes('@')) {
errors.push('Invalid email format');
}
return {
isValid: errors.length === 0,
errors
};
}
마주친 문제들
기존 JS 모듈을 TS에서 import할 때 타입 추론이 안 되는 경우가 많았다. 당장은 any로 우회하고 나중에 정리하기로 했다.
const legacyModule = require('./legacy') as any;
Express 미들웨어 타입 정의도 처음엔 헷갈렸는데, @types/express가 제공하는 타입을 활용하니 편했다.
import { Request, Response, NextFunction } from 'express';
export function authMiddleware(req: Request, res: Response, next: NextFunction) {
// ...
}
결과
2주간 진행하면서 전체 코드의 약 30%를 TS로 전환했다. IDE의 자동완성과 타입 체크 덕분에 단순 실수가 줄었다. strict 모드는 팀원들이 적응한 후 단계적으로 활성화할 예정이다.