← 전체 글로 돌아가기

TypeScript

TypeScript 타입 가드에서 놓치기 쉬운 부분

타입 가드는 null 체크와 제대로 구분해야 하고, 빌드 타임에 오류를 모두 잡아낼 수는 없으므로 런타임 검증이 필요하다.

TypeScript를 쓰다 보면 타입 가드를 무시해서 버그가 생기는 일이 생긴다. 특히 외부 API 응답처럼 런타임에 타입이 달라질 수 있는 상황에서 타입 가드를 느슨하게 작성하면 나중에 터진다.

null 체크와 타입 가드는 다르다

optional 체크와 타입 가드를 헷갈리는 경우가 많다. null 체크는 값이 있는지 없는지만 확인하지만, 타입 가드는 값의 형태가 기대하는 모양인지까지 확인한다.

npm run build
npx tsc --noEmit

빌드를 실행해보면 TypeScript가 놓친 부분을 알려준다. 하지만 실제 동작 환경에서는 타입 정보가 사라지므로, 런타임에 타입을 다시 확인해야 한다.

응답 타입이 달라질 때를 대비하자

API 응답 타입을 정의했어도 서버 코드가 바뀌거나 버전이 다르면 실제 데이터는 다를 수 있다. 응답을 받으면 먼저 기대하는 구조인지 확인하고 사용해야 안전하다.

Type guard 함수를 작성할 때는 구체적으로 작성한다.

function isValidUser(data: unknown): data is User {
  return (
    typeof data === 'object' &&
    data !== null &&
    'id' in data &&
    'name' in data &&
    typeof (data as any).id === 'string' &&
    typeof (data as any).name === 'string'
  );
}

이렇게 명시적으로 확인하면 나중에 데이터 구조가 바뀌었을 때 런타임 오류 대신 제어된 방식으로 처리할 수 있다.

빌드 타임 오류와 런타임 오류

TypeScript 컴파일은 정적 검사만 한다. 코드에서 타입 오류가 없다고 해도 런타임에는 예상 밖의 데이터가 들어올 수 있다.

빌드는 성공했는데 화면이 깨지는 경우는 보통 이런 상황이다. 타입스크립트는 맞다고 했지만, 실제 데이터 형태가 달랐기 때문이다.

작은 확인을 자동화하자

타입 관련 문제는 반복적이다. 비슷한 API를 여러 개 쓰면서 같은 실수를 반복하지 않으려면, 가드 함수를 라이브러리화하거나 테스트를 자동화하는 게 좋다.

타입 가드를 철저히 하고, 빌드 결과를 정기적으로 점검하면 대부분의 타입 관련 버그는 미리 찾을 수 있다.