TypeScript
TypeScript optional 값이 null일 때 디버깅하기
optional 체이닝이 예상과 다르게 동작할 때 확인해야 할 것들을 정리했습니다.
로컬에서는 잘 동작하던 TypeScript 코드가 배포 환경에서 갑자기 타입 에러를 던질 때가 있다. 대부분 optional 체이닝과 null 체크 관련이다.
먼저 빌드 검증부터
TypeScript 타입 에러는 로컬 개발 환경과 배포 환경이 다를 수 있다. 환경마다 다른 tsconfig.json을 사용하거나, npm 패키지 버전이 다를 때는 타입 정의가 달라질 수 있다.
먼저 프로덕션 빌드가 제대로 되는지 확인하는 게 첫 단계다.
npm run build
npx tsc --noEmit
npm run build는 실제로 번들링되고, tsc --noEmit은 타입만 검사한다. 두 명령이 다른 결과를 주면 빌드 도구와 TypeScript 버전이 맞지 않을 가능성이 높다.
optional 체이닝 vs 옵셔널 프로퍼티
optional 문제는 보통 세 가지에서 비롯된다.
첫 번째는 타입 정의 자체가 애매한 경우다. 어떤 값이 undefined일 수 있는데 타입에는 string이라고만 쓰여 있으면 런타임에 에러가 난다. type User = { name: string } 대신 { name?: string } 또는 { name: string | undefined }로 명확히 해야 한다.
두 번째는 optional 체이닝을 과신하는 것이다. user?.profile?.name은 user나 profile이 undefined면 undefined를 반환하지만, 그다음 코드에서 name이 string이라고 가정하면 안 된다.
세 번째는 API 응답 구조가 배포 환경에서 달라지는 경우다. 로컬에서는 항상 있는 필드가 특정 조건에서는 서버에서 생략될 수 있다.
정상 상태 먼저 정의하기
타입 문제를 찾으려면 먼저 정상 상태를 명확히 해야 한다.
- 확인할 값: 타입 가드 결과 (즉, 실제로 어떤 타입이 들어왔는가)
- 비교 기준: 배포되는 타입 정의와 실제 데이터의 일치 여부
- 기록할 것: 에러 메시지, 해당 시점의 입력값, 수정 전후 타입 정의
런타임에 값을 로깅해보는 게 가장 빠르다.
if (user) {
console.log(typeof user.profile, user.profile)
console.log(user.profile?.name)
}
이렇게 보면 실제로 어떤 타입이 오는지 알 수 있다.
배포 전 체크리스트
- 원래 에러가 같은 조건에서 다시 재현되는지 확인한다.
- 에러 메시지에서 실제 타입과 예상 타입의 차이를 정리한다.
- tsconfig.json, API 응답 타입 정의, 실제 데이터를 한 줄로 설명할 수 있을 때까지 좁혀본다.
TypeScript는 정확할수록 좋다. 한 번 타입을 명확히 하면 다음 문제는 훨씬 빨리 찾을 수 있다.