How Do You Validate `unknown` in TypeScript Without a Schema Library? 🛡️
스키마 라이브러리 없이 TypeScript의 unknown을 검증하는 방법
TypeScript에서 외부 입력을 `unknown`으로 두고 런타임 타입 가드로 검증하는 방법을 소개합니다. `is-kit`으로 가드를 조합하고 `safeParse`와 JSON 파싱에 연결하는 예제를 보여주며, 풍부한 오류 처리나 변환이 필요할 때는 스키마 라이브러리가 더 적합하다고 구분합니다.
- 주제
에디터 노트
이 방식의 장점은 검증과 타입 좁히기를 같은 가드에 묶는 데 있습니다. `as User`와 달리 실제 런타임 검사를 하며, `optionalKey`와 `nullable`처럼 서로 다른 입력 조건도 따로 표현합니다. `safeParse`가 값을 변환하지 않는다는 점도 사용 범위를 분명히 합니다. 다만 가드가 알려주는 것은 값이 조건을 만족하는지 여부와 통과한 값의 타입입니다. 필드별 오류나 변환을 제공하지 않으므로 그런 요구가 있는 검증 흐름은 스키마 라이브러리와 역할이 다릅니다. 댓글은 가벼운 가드의 실용성을 지지하지만, 가벼운 방식이 모든 경계 검증에 충분하다는 근거까지 제시하지는 않습니다. 글도 그 차이를 인정하고 있어 `is-kit`의 가치를 단순히 스키마 라이브러리 대체재가 아니라 작은 검증 규칙을 조합하는 도구로 한정합니다.
AI 요약
API 응답, JSON.parse, 로컬 저장소처럼 신뢰할 수 없는 경계에서 들어온 값은 검증하기 전까지 unknown으로 다루는 편이 안전합니다. as User는 컴파일러의 판단만 바꾸며 실제 값이나 속성을 확인하지 않습니다. 입력이 예상한 모양과 다르면 실행 중 오류가 발생할 수 있습니다.
런타임 가드로 검증하기
글은 is-kit의 struct, isString, oneOfValues를 조합해 User 가드를 만듭니다. 검사가 성공하면 TypeScript가 값의 타입을 좁혀 name 같은 속성을 안전하게 다룰 수 있습니다. arrayOf로 배열을 확인하고 optionalKey와 nullable을 구분해 선택 속성과 null 허용 여부를 표현합니다. 기본 struct는 추가 속성을 허용하며, { exact: true }를 지정하면 정해진 키만 받습니다.
결과값과 JSON 경계
가드가 참·거짓과 타입 좁히기를 제공한다면 safeParse는 { valid: true, value } 또는 { valid: false } 형태로 결과를 반환합니다. 성공해도 값을 복제하거나 변환하지 않고, 검사에 통과한 원래 값을 돌려줍니다. safeJsonParse는 JSON 디코딩과 가드 검사를 연결하며, 잘못된 JSON과 검증 실패를 모두 실패 결과로 처리합니다.
글은 이 방식이 풍부한 필드별 오류, 여러 오류의 동시 반환, 강제 변환, 기본값, 데이터 변환, 스키마 기반 산출물이 필요한 경우를 대신하지 않는다고 설명합니다. 그런 작업에는 스키마 라이브러리가 더 적합하고, 단순한 런타임 확인과 타입 좁히기에는 조합 가능한 가드가 충분할 수 있다는 구분입니다.
dev.to 반응
- @johnnylemonny — 잘 읽었습니다, Nyaomaru! 잘 설계한 타입 가드가 스키마 라이브러리를 도입하기 전까지 어디까지 쓸 수 있는지 보여준 점이 좋습니다. 적절한 검증 방식은 유행이 아니라 해결하려는 문제에 달렸다는 점을 다시 떠올리게 합니다. 실용적인 TypeScript 글을 공유해 주셔서 감사합니다!
- @kate8382 — 무거운 스키마 라이브러리와 복잡한 제네릭에 집착하는 모습은 JavaScript를 그럴듯하게 보이게 하려고 기업식 관료주의를 들여오는 것처럼 느껴질 때가 많습니다. TypeScript가 기본이 되기 훨씬 전부터 JavaScript로 복잡한 시스템을 만들었는데, 요즘은 간단한 경계 검증에도 거대한 프레임워크를 가져오는 경우가 많습니다. 컴파일러를 만족시키려고 무거운 의존성을 더하는 대신 가볍고 조합 가능한 경계를 권하는 점이 좋습니다. 때로는 JavaScript가 제 역할을 하도록 방해하지 않는 코드가 가장 나은 TypeScript입니다. 늘 좋은 글입니다!
원문: dev.to / 번역·요약: Trawling