19P by xguru 23일전 | ★ favorite | 댓글과 토론
  • JavaScript/TypeScript 기반 스키마 라이브러리들이 공통 인터페이스를 구현하도록 설계된 스펙
  • 라이브러리마다 사용자가 정의한 타입 검증 로직을 재사용할 수 있게 하여, 툴들이 별도의 어댑터 없이 서로 호환 가능하게 만드는게 목적
  • Zod, Valibot, ArkType 등 주요 라이브러리 제작진이 공동 설계함

주요 인터페이스 (StandardSchemaV1)

  • ~standard라는 객체 속성을 통해 모든 사양을 구현
  • ~standard 내부에 version, vendor, validate, types 등의 필수 프로퍼티 존재
  • validate 함수가 성공 시 value를, 실패 시 issues 배열을 반환
  • types 프로퍼티로 TypeScript에서 스키마의 입력(input)과 출력(output) 타입을 추론할 수 있음
  • 모든 업데이트는 메이저 버전이 아닐 경우 호환성을 유지

설계 목표

  • 런타임 검증 지원: 스탠다드 방식으로 에러 정보를 표준화해 전달함
  • 정적 타입 추론 지원: 타입스크립트 기반 라이브러리들이 추론한 타입 정보를 명시적으로 노출함
  • 간결성: 기존 라이브러리 함수에 몇 줄만으로 추가해 구현 가능함
  • API 충돌 회피: ~standard 이름 공간 하나에만 모든 내용을 넣어 기존 API와 충돌하지 않도록 함
  • 개발자 경험 유지: ~standard처럼 틸드(~)로 시작해 자동완성에서 우선순위를 낮춤

어떤 라이브러리가 구현하고 있는가

  • 이미 Zod, Valibot, ArkType, Arri Schema, TypeMap 등에서 표준 스키마를 지원 중임
  • tRPC, TanStack Form, TanStack Router, Hono Middleware 등도 표준 스키마를 기반으로 유저 스키마를 수용함

자신의 라이브러리에 스펙을 구현하는 방법

  • StandardSchemaV1 인터페이스를 라이브러리에 복사해 ~standard 속성을 추가함
  • validate 함수를 기존 검증 함수에 연결해 성공 시 { value }, 실패 시 { issues }를 반환하도록 처리함
  • 필요 시 비동기 검증도 가능하지만, 동기 검증을 권장

표준 스키마로 유저 정의 스키마를 받는 방법

  • 스키마 라이브러리 없이 직접 사용하려면, @standard-schema/spec을 설치하거나 인터페이스를 복사해 사용함
  • 예시 함수 standardValidate처럼 표준 인터페이스를 가진 스키마라면 어떤 라이브러리든 동일한 방식으로 유효성 검증 가능함
  • 동기 검증만 허용하려면 validate 반환값이 Promise인지 확인 후 예외 처리를 하면 됨

FAQ

  • @standard-schema/spec 의존성을 추가해야 하나?: 반드시 의존성으로 추가할 필요는 없고, 복사 후 사용 가능함
  • dev dependency로 추가 불가함: 라이브러리의 퍼블릭 API가 되므로 실제 배포 환경에서도 사용 가능해야 함
  • ~standard 앞에 틸데(~)를 사용한 이유: 자동완성에서 다른 속성보다 뒤에 나오도록 의도함
  • Symbol 대신 문자열 키를 사용한 이유: 타입스크립트에서 Symbol 키는 자동완성 정렬이나 타입 추론에 문제가 발생하기 때문