Zod 검증이 실행되기도 전에 실패하는 이유와 해결 방법

발행: (2026년 6월 11일 PM 05:43 GMT+9)
3 분 소요
원문: Dev.to

Source: Dev.to

Why Your Zod Validation Fails Before It Even Runs (And How to Fix It) 표지 이미지

mohammad rostami

react-hook-form과 함께 Zod를 사용하고 있다면, 최소 한 번은 다음과 같은 메시지를 보았을 것입니다:

Invalid input: expected number, received NaN

언뜻 보기엔 단순한 검증 문제처럼 보입니다.

그게 아닙니다.

실제 문제

폼 입력을 다룰 때는:

  • 모든 값은 문자열로 들어옵니다
  • z.coerce.number()가 이를 변환하려고 시도합니다
  • 빈 입력("")이나 잘못된 값 → NaN

그리고 여기서 문제는:

Zod는 .min() / .max() 검증이 실행되기 전에 실패합니다.
따라서 커스텀 메시지 대신 일반적이고 (그다지 도움이 되지 않는) 오류를 얻게 됩니다.

상황이 더 복잡해집니다

TypeScript를 사용한다면:

  • z.inputz.output
  • react-hook-form입력 타입을 사용합니다
  • Zod는 파싱 후 출력 타입을 제공합니다

이 불일치는 혼란스러운 타입 오류와 데이터에 대한 잘못된 가정으로 이어질 수 있습니다.

해결 방법

Zod가 검증을 시도하기 전에 잘못된 입력을 처리해야 합니다:

readTime: z.preprocess((val) => {
  if (val === "" || val === undefined) return undefined;

  const num = Number(val);
  return isNaN(num) ? undefined : num;
},
z.number()
  .min(2, 'Minimum read time is 2 minutes')
  .max(60, 'Maximum read time is 60 minutes')
)

Enter fullscreen mode
전체 화면 모드로 전환

Exit fullscreen mode
전체 화면 모드 종료

이 해결책이 해결하는 문제

  • 빈 입력 → 올바르게 처리
  • 잘못된 숫자 → 더 이상 NaN 문제 없음
  • 커스텀 검증 메시지 → 실제로 표시됨
  • 전반적으로 깔끔한 UX

핵심 정리

폼에서 z.coerce.number()를 사용한다면, 무조건 신뢰하지 마세요.
항상 입력을 먼저 정규화하세요.

때때로 버그는 검증 규칙에 있는 것이 아니라… 검증이 시작되기 전 데이터가 들어오는 방식에 있습니다.

0 조회
Back to Blog

관련 글

더 보기 »