TypeScript 프로젝트에 strict 모드 점진적으로 도입하기
문제 상황
회사 프로젝트가 TypeScript 2.x 시절부터 시작되어 strict: false 상태로 운영되고 있었다. 타입 안정성을 높이기 위해 strict 모드를 켜려고 했더니 300개가 넘는 에러가 발생했다.
// tsconfig.json
{
"compilerOptions": {
"strict": true // 이거 하나로 지옥행
}
}
팀원들과 논의 끝에 일괄 적용은 불가능하다고 판단했다. 신규 개발을 멈출 수 없었고, 에러를 //@ts-ignore로 때우는 건 의미가 없었다.
해결 방법
strict는 사실 여러 옵션의 묶음이다. 하나씩 켜기로 했다.
{
"compilerOptions": {
"strict": false,
"noImplicitAny": true,
"strictNullChecks": false,
"strictFunctionTypes": false,
"strictBindCallApply": false,
"strictPropertyInitialization": false,
"noImplicitThis": false,
"alwaysStrict": true
}
}
1주차: noImplicitAny
가장 기본적인 옵션부터 시작했다. any 타입이 암묵적으로 추론되는 경우를 잡아낸다.
// Before
function getUser(id) { // Parameter 'id' implicitly has an 'any' type
return users.find(u => u.id === id);
}
// After
function getUser(id: string) {
return users.find(u => u.id === id);
}
약 80개 에러가 발생했고, 2일 정도 걸려서 수정했다. 대부분 함수 파라미터 타입 지정이었다.
3주차: strictNullChecks
이게 제일 고됐다. null과 undefined를 명시적으로 처리해야 한다.
// Before
const user = users.find(u => u.id === id);
return user.name; // Object is possibly 'undefined'
// After
const user = users.find(u => u.id === id);
if (!user) throw new Error('User not found');
return user.name;
약 180개 에러가 나왔다. 1주일 동안 모듈별로 나눠서 수정했다. Optional chaining이 TS 3.7에서 나온다는 소식을 들어서 기다려볼까 했지만, 그냥 진행했다.
결과
5주 정도 걸려서 모든 strict 옵션을 활성화했다. 그 과정에서 실제 버그를 3건 발견했다. undefined 처리가 안 된 부분에서 프로덕션 에러가 간헐적으로 발생하고 있었다.
점진적 도입이 정답이었다. 한 번에 했으면 팀원들의 반발도 있었을 것이고, 에러를 대충 처리했을 가능성이 크다.