- Zod 4가 1년간의 개발 끝에 안정 버전으로 공개되며, Zod 3의 설계 한계를 고치고 성능·번들 크기·TypeScript 컴파일 효율을 크게 개선함
- 2021년 5월 나온 Zod 3는 GitHub 스타 2,700개·주간 다운로드 60만에서 현재 37.8k 스타·주간 3,100만 다운로드 규모로 성장했고, 24개 마이너 버전 이후 주요 개선에 호환성 깨지는 변경이 필요해짐
- 벤치마크에서 문자열 파싱은 14배, 배열 파싱은 7배, 객체 파싱은 6.5배 빨라졌으며,
tsc타입 인스턴스화도 간단한 예제에서 25,000회 초과에서 약 175회로 줄어듦 - 핵심 번들 크기는 gzip 기준 Zod 3
12.47kb에서 Zod 4 일반 버전5.36kb로 줄었고, 트리 셰이킹 가능한 함수형 API인 Zod Mini는1.88kb까지 작아짐 - 새 기능은 JSON Schema 변환, 메타데이터 레지스트리, 재귀 객체 타입 추론, 국제화, 에러 pretty-printing, 템플릿 리터럴 타입,
z.stringbool(), 통합error파라미터, 개선된z.discriminatedUnion()등을 포함함
Zod 4가 새 메이저 버전이 된 이유
- Zod 4는 1년간의 활발한 개발 끝에 안정 버전이 됐으며, 더 빠르고 작고
tsc효율이 높은 기반으로 오래 요청된 기능들을 구현함 - Zod v3.0은 2021년 5월 출시됐고, 당시 GitHub 스타는 2,700개, 주간 다운로드는 60만이었음
- 현재 Zod는 GitHub 스타 37.8k, 주간 다운로드 3,100만을 기록함
- 베타가 나온 6주 전에는 주간 다운로드가 2,300만이었음
- 24개 마이너 버전이 쌓이면서 Zod 3 코드베이스는 한계에 도달했고, 가장 많이 요청된 기능과 개선에는 호환성 깨지는 변경이 필요했음
- Zod 4는 가장 많은 추천을 받은 공개 이슈 10개 중 9개를 닫음
파싱 성능과 TypeScript 컴파일 효율
- Zod 4는 저장소에서 직접 실행 가능한 벤치마크를 제공함
- 파싱 성능 개선:
- 문자열 파싱: 14배 빨라짐
- 배열 파싱: 7배 빨라짐
- 객체 파싱: 6.5배 빨라짐
- 객체 파싱 벤치마크는 Moltar validation library benchmark를 실행함
tsc --extendedDiagnostics기준 간단한 파일 컴파일에서 타입 인스턴스화가 크게 줄어듦"zod/v3"사용 시 25,000회 초과"zod/v4"사용 시 약 175회
- Zod 4는
ZodObject와 다른 스키마 클래스의 제네릭을 재설계하고 단순화해 인스턴스화 폭증을 피함 .extend()와.omit()을 반복 연결하는 패턴은 Zod 3에서 컴파일에4000ms가 걸렸고, 추가.extend()호출은"Possibly infinite"오류를 유발할 수 있었음- 같은 패턴이 Zod 4에서는
400ms에 컴파일되어 10배 빨라짐 - 향후
tsgo컴파일러와 함께 쓰면 Zod 4의 에디터 성능은 더 큰 스키마와 코드베이스까지 확장될 수 있음
번들 크기와 Zod Mini
- 단순한
z.boolean()검증 스크립트를rollup으로 번들링해 핵심 번들 크기를 비교함 - gzip 기준 핵심 번들 크기:
- Zod 3:
12.47kb - Zod 4 일반 버전:
5.36kb
- Zod 3:
- Zod 4 일반 버전의 핵심 번들은 Zod 3보다 약 57% 작고, 2.3배 줄어듦
- Zod의 메서드 중심 API는 근본적으로 트리 셰이킹이 어렵고, 단순한
z.boolean()스크립트도.optional(),.array()같은 사용하지 않은 메서드 구현을 함께 끌어옴 - Zod Mini는
zod와 1:1로 대응하는 함수형·트리 셰이킹 가능 API를 제공함- Zod가 메서드를 쓰는 곳에서 Zod Mini는 일반적으로 래퍼 함수를 사용함
- 파싱 메서드는 Zod와 Zod Mini가 동일함
- 범용
.check()메서드로 정제(refinement)를 추가함
- 일반 Zod는 대부분의 사용 사례에 계속 권장되며, 비정상적으로 엄격한 번들 크기 제약이 있는 프로젝트는 Zod Mini를 고려할 수 있음
zod/mini사용 시 gzip 번들 크기는1.88kb임- Zod 3 대비 85%, 6.6배 감소함
- 비교 표: Zod 3
12.47kb, Zod 4 일반5.36kb, Zod 4 Mini1.88kb
- 자세한 내용은
zod/mini문서에서 볼 수 있음
메타데이터와 JSON Schema
- Zod 4는 스키마에 강타입 메타데이터를 추가하는 새 시스템을 도입함
- 메타데이터는 스키마 자체가 아니라, 스키마와 typed metadata를 연결하는 schema registry에 저장됨
z.registry()로 레지스트리를 만들 수 있고, 스키마의.register()메서드로 편의 등록도 가능함- Zod는 공통 JSON Schema 호환 메타데이터를 받는 전역 레지스트리
z.globalRegistry를 내보냄 .meta()메서드는 스키마를z.globalRegistry에 편리하게 추가함- Zod 3 호환성을 위해
.describe()는 계속 제공되지만, Zod 4에서는.meta()가 권장됨 - Zod 4는
z.toJSONSchema()를 통한 first-party JSON Schema 변환을 제공함 z.globalRegistry의 메타데이터는 JSON Schema 출력에 자동 포함됨- 생성되는 JSON Schema 커스터마이징 정보는 JSON Schema docs에 있음
새 스키마 표현과 타입 기능
- Zod 4는 재귀 객체 타입을 적절히 추론할 수 있음
- 재귀 타입과 상호 재귀 타입을 표현할 수 있음
- Zod 3의 재귀 타입 패턴과 달리 타입 캐스팅이 필요 없음
- 결과 스키마는 일반
ZodObject인스턴스이며 전체 메서드를 사용할 수 있음
File인스턴스 검증을 위한 File schema가 추가됨z.templateLiteral()은 TypeScript의 템플릿 리터럴 타입을 표현함- 문자열화 가능한 Zod 스키마 타입은 내부 정규식을 저장함
- 대상에는 문자열,
z.email()같은 문자열 포맷, 숫자, boolean, bigint, enum, literal, undefined/optional, null/nullable, 다른 template literal이 포함됨 z.templateLiteral생성자는 이들을 하나의 super-regex로 이어 붙임z.email()같은 문자열 포맷은 제대로 강제되지만, custom refinement는 강제되지 않음- 자세한 내용은 template literal docs에 있음
- 고정 폭 정수와 부동소수점 타입을 표현하는 새 숫자 포맷이 추가됨
- 적절한 inclusive minimum/maximum 제약이 이미 추가된
ZodNumber인스턴스를 반환함
- 적절한 inclusive minimum/maximum 제약이 이미 추가된
- JavaScript
number로 안전하게 표현할 수 있는 범위를 넘는 bigint 숫자 포맷도 추가됨- 적절한 inclusive minimum/maximum 제약이 이미 추가된
ZodBigInt인스턴스를 반환함
- 적절한 inclusive minimum/maximum 제약이 이미 추가된
z.literal()은 이제 여러 값을 선택적으로 받을 수 있음
에러, 국제화, 문자열 포맷
- Zod 4는 에러 메시지를 여러 언어로 전역 번역하는 새
localesAPI를 도입함 - 지원 로케일 전체 목록은 Customizing errors에 있으며, 지원 언어가 추가될 때 갱신됨
- Zod는
ZodError를 사용자 친화적인 형식의 문자열로 바꾸는 최상위z.prettifyError함수를 구현함- 현재 포맷은 설정할 수 없음
- 향후 변경될 수 있음
- 기존
zod-validation-error를 사용 중이면 계속 사용할 수 있음
- email 등 모든 문자열 포맷은
z모듈의 최상위 함수로 승격됨- 더 간결하고 트리 셰이킹에 유리함
z.string().email()같은 메서드 대응 API는 계속 사용할 수 있지만 deprecated 상태임- 다음 major 버전에서 제거될 예정임
z.email()API는 custom regular expression을 지원함- canonical email regex는 하나로 정해져 있지 않으며, 애플리케이션마다 더 엄격하거나 느슨한 기준을 택할 수 있음
- Zod는 편의를 위해 공통 정규식 몇 가지를 내보냄
불리언 변환과 에러 커스터마이징 단순화
- 기존
z.coerce.boolean()은 falsy 값을false, truthy 값을true로 바꾸는 단순한 API임false,undefined,null,0,"",NaN등은false가 됨- 이 동작은 다른
z.coerceAPI와 맞음
- Zod 4는 env 스타일의 더 정교한 boolean coercion을 위해
z.stringbool()을 도입함- truthy 값과 falsy 값을 커스터마이징할 수 있음
- 자세한 내용은
z.stringbool()docs에 있음
- Zod 4의 호환성 깨지는 변경 대부분은 에러 커스터마이징 API와 관련됨
- 에러 커스터마이징은 단일
error파라미터로 통합됨message는error로 대체됨message파라미터는 계속 지원되지만 deprecated 상태임invalid_type_error와required_error는 함수 문법의error로 대체됨errorMap도 함수 문법의error로 대체됨
조합성, 정제, 변환
z.discriminatedUnion()은 기존에 지원하지 않던 여러 스키마 타입을 지원함- union과 pipe가 포함됨
- discriminated union을 다른 discriminated union의 멤버로 사용할 수 있어 조합 가능해짐
- Zod 3에서는 refinement가 원본 스키마를 감싸는
ZodEffects클래스에 저장됐음- 이 구조 때문에
.refine()을.min()같은 다른 스키마 메서드와 섞어 쓰기 불편했음
- 이 구조 때문에
- Zod 4에서는 refinement가 스키마 내부에 저장되어
.refine()과 다른 스키마 메서드를 자연스럽게 함께 사용할 수 있음 - 새
.overwrite()메서드는 inferred type을 바꾸지 않는 transform을 표현함.transform()은 출력 타입이 런타임에서 introspectable하지 않고, transform 함수가 무엇이든 반환할 수 있는 블랙박스임- 이 때문에 JSON Schema로 안전하게 변환할 방법이 없음
.overwrite()는 원래 클래스의 인스턴스를 반환함- overwrite 함수는 refinement로 저장되며 inferred type을 수정하지 않음
- 기존
.trim(),.toLowerCase(),.toUpperCase()는.overwrite()를 사용해 다시 구현됨
라이브러리 작성자를 위한 기반
- Zod Mini 추가로 Zod와 Zod Mini가 공유하는 핵심 기능을 담은
zod/v4/core서브패키지가 만들어짐 zod/v4/core는 Zod를 단순 라이브러리에서 다른 라이브러리에 넣어 쓸 수 있는 빠른 검증 기반으로 확장함- 스키마 라이브러리를 만드는 경우 Zod와 Zod Mini 구현을 참고해
zod/v4/core위에 구축할 수 있음 - 라이브러리 작성자를 위해 For library authors 가이드가 제공됨
- Zod 위에 구축할 때의 best practice를 다룸
- Zod 3과 Zod 4, Mini를 동시에 지원하는 방법에 대한 공통 질문에 답함