FormData 는 느슨함: 모든 필드가 문자열 또는 File, TypeScript 가 어떤 필드 있는지 모름. Zod 가 캐논 답 — schema 선언, 들어오는 데이터 파싱, 타입 잡힌 객체 (또는 타입 잡힌 에러) 받음.
모양
Zod schema 가 유효한 데이터 모양 묘사: z.object({ email: z.string().email(), age: z.coerce.number().min(18) }). .parse() (fail 시 throw) 또는 .safeParse() (success/failure 의 discriminated union 반환) 호출. Action 안에선 .safeParse 가 유효성 에러를 state 의 일부로 반환 가능하게.
FormData → 타입 잡힌 객체
Zod 가 FormData 네이티브로 모름, 다만 필드를 먼저 plain object 로 추출 가능: Object.fromEntries(formData). 그 후 safeParse 돌림. 결과: 모두 타입 잡힌 { success: true, data } 또는 필드 레벨 에러 메시지 가진 { success: false, error }.
에러 모양
Zod 에러가 필드별 그룹: error.flatten().fieldErrors 가 { email: ['invalid email'], age: ['must be a number'] } 줌. 이 객체를 state 의 일부로 반환하면 form 이 각 필드 개별 하이라이트 가능.
Actions 스토리와의 composition
Action 이 됨: 파싱 → invalid 면 에러 반환; valid 면 작업 수행, success 반환. 컴포넌트가 state 에서 에러 메시지 직접 렌더. 별도 유효성 라이브러리 없음, 수동 필드 반복 없음 — Zod 가 호출 하나로 타입 잡힌 입력 + 타입 잡힌 에러.