TypeScript 컴파일러 옵션 strict 모드 적용 후기

배경

6개월 전 JavaScript로 시작한 프로젝트를 TypeScript로 전환했지만, strict: false 상태로 운영하고 있었다. any 타입이 남발되면서 타입 안정성이 떨어지는 문제가 발생해 strict 모드 적용을 결정했다.

단계적 적용 전략

한 번에 모든 파일을 수정하는 건 불가능했다. tsconfig.json에서 개별 옵션을 하나씩 활성화하는 방식을 택했다.

{
  "compilerOptions": {
    "noImplicitAny": true,
    "strictNullChecks": false,
    "strictFunctionTypes": false,
    "strictPropertyInitialization": false
  }
}

주요 이슈

1. noImplicitAny

가장 많은 수정이 필요했던 옵션이다. 특히 이벤트 핸들러와 콜백 함수에서 any가 많았다.

// Before
const handleClick = (e) => {
  e.preventDefault();
};

// After
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
  e.preventDefault();
};

2. strictNullChecks

DOM 조작 코드에서 null 체크가 필요한 곳이 많았다.

// Before
const element = document.getElementById('root');
element.innerHTML = 'Hello';

// After
const element = document.getElementById('root');
if (element) {
  element.innerHTML = 'Hello';
}

3. API 응답 타입 정의

백엔드 응답을 interface로 정의하면서 optional 속성 처리가 명확해졌다.

interface UserResponse {
  id: number;
  name: string;
  email?: string;
}

const getUser = async (id: number): Promise<UserResponse> => {
  const response = await fetch(`/api/users/${id}`);
  return response.json();
};

결과

2주간 약 120개 파일을 수정했다. 컴파일 에러를 잡는 과정에서 실제 버그 3건을 발견했다. null 체크 누락과 잘못된 타입 변환이었다.

strict 모드는 초기 작업량이 많지만, 런타임 에러를 사전에 방지할 수 있어 충분히 가치있는 투자였다.

TypeScript 컴파일러 옵션 strict 모드 적용 후기