TypeScript 마이그레이션 시작하며 정리한 타입 기초
배경
회사 프로젝트에서 런타임 에러가 잦아 TypeScript 도입을 결정했다. 한 번에 전환하기보다 allowJs 옵션으로 점진적 마이그레이션을 시작했다.
tsconfig.json 설정
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": ["es2017", "dom"],
"allowJs": true,
"checkJs": false,
"jsx": "react",
"strict": false,
"esModuleInterop": true
}
}
처음엔 strict: false로 시작해 점진적으로 타입을 추가하기로 했다.
자주 사용한 패턴
API 응답 타입
interface User {
id: number;
name: string;
email: string;
createdAt: string;
}
interface ApiResponse<T> {
data: T;
status: number;
message?: string;
}
const getUser = async (id: number): Promise<ApiResponse<User>> => {
const response = await fetch(`/api/users/${id}`);
return response.json();
};
제네릭으로 API 응답을 타입화하니 재사용성이 좋았다.
Union 타입으로 상태 관리
type LoadingState = 'idle' | 'loading' | 'success' | 'error';
interface State {
status: LoadingState;
data: User | null;
error: Error | null;
}
문자열 리터럴 유니온 타입으로 상태값을 제한해 오타 실수를 방지할 수 있었다.
Optional과 Partial
interface UpdateUserParams {
name?: string;
email?: string;
}
// 또는
type UpdateUserParams = Partial<User>;
PATCH API 파라미터에는 Partial<T>가 유용했다.
마이그레이션 순서
- 유틸리티 함수부터
.ts로 변경 - API 클라이언트 레이어 타입 추가
- React 컴포넌트를
.tsx로 전환 - Redux 액션/리듀서 타입 정의
아직 any를 많이 쓰고 있지만, 점진적으로 개선할 예정이다. 타입 추론 덕분에 IDE 자동완성이 향상돼 생산성은 이미 체감된다.