zod | Zod를 활용하여 타입 검증하기 (2)

2025. 3. 2. 22:29·FrontEnd/기타

zod에서 타입 검증 후 수행할 수 있는 데이터 처리 및 에러 메시지 등을 커스텀하는 방법에 대해 알아보려 한다.

 

.transform()

transform은 스키마 검증을 통과한 데이터를 입맛에 맞게 변경하고 싶을 때 사용할 수 있다.

입력된 문자열이 스키마 검증을 통과했을 때, 문자열의 길이로 변환하고 싶다면 transform() 내부에 length를 리턴하도록 함수를 작성해 주면 된다.

// 입력된 문자열을 문자열의 길이로 변환 
const stringToNumber = z.string().transform((val) => val.length); 

stringToNumber.parse("string"); // 6

 

이전 글에서 사용했던 userSchema에서 사용자의 이름을 입력받은 후 이름의 길이를 필요로 한다면 다음처럼 작성할 수 있다.

const userSchema = z.object({
  id: z.number(),
  name: z.string().transform((name) => name.length);, // 문자열의 길이를 리턴함
  email: z.string().email(),
  admin: z.boolean().default(false).nullish(),
  createdAt: z.date().default(() => new Date()),
});

 

 

.enum()

만약, 정해진 값에 한해서만 입력을 받아야 한다면 zod를 활용해서 값을 제한해 둘 수는 없을까?

enum을 사용하면 해당 필드에 들어올 수 있는 값을 미리 설정할 수 있다.

const Options = z.enum(['a', 'b', 'c']);

Options.parse('a'); // 'a'

Options.parse('d'); // 에러

위 코드에서 Options에 문자열 a, b, c가 아닌 값이 입력되면 에러를 던지게 되는 것이다.

 

 

검증 커스텀

다양한 방법을 사용해 스키마를 정의하고 검증을 수행할 수 있는데, 오류가 발생했을 때 특정 필드에 메시지를 보여주고 싶다면 .refine()을 활용할 수 있다.

 

.refine(검증 조건, 에러 메시지)

사용자 정보를 입력받을 때, 사용자 이름에 50자 이상이 입력되는 경우는 이상적이지 않다.

 

name 필드에 다음과 같이 스키마를 작성하면 50자 이상의 문자열이 입력되었을 때 에러와 함께 "이름은 50자 이하의 문자열만 가능합니다!"라고 에러 메시지를 던질 수 있다.

const userSchema = z.object({
  id: z.number(),
  name: z.string().refine((name) => name.length <= 50, {
    message: "이름은 50자 이하의 문자열만 가능합니다!",
  });,
  email: z.string().email(),
  admin: z.boolean().default(false).nullish(),
  createdAt: z.date().default(() => new Date()),
});

 

 

refine은 transform으로 변환한 값을 검증하는데도 사용할 수 있다.

const nameToGreeting = z
  .string()
  .transform((val) => val.toUpperCase())
  .refine((val) => val.length > 15)
  .transform((val) => `Hello ${val}`)
  .refine((val) => val.indexOf("!") === -1);

 

 

위 스키마에 michaeljordan23이라는 문자열이 입력되었을 때의 과정을 살펴보자

nameToGreeting.parse("michaeljordan23")

1. "michaeljordan23" → "MICHAELJORDAN23" (대문자로 변환)

2. "MICHAELJORDAN23".length = 16 (15자 이상 통과 ✅)

3. "MICHAELJORDAN23" → "Hello MICHAELJORDAN23" (변환)

4. 느낌표 없음 (최종 통과 ✅)

 

이 경우에는 모든 데이터 변환과 검증을 성공적으로 통과했으므로 Hello MICHAELJORDAN23이 리턴될 것이다.

 

 

그렇다면 다음과 같은 경우엔 어떻게 될까?

nameToGreeting.parse("michaeljordan!!!!")

1. "michaeljordan!!!!" → "MICHAELJORDAN!!!!"

2. 길이 18 (15자 이상 통과 ✅)

3. 변환 후 → "Hello MICHAELJORDAN!!!!"

4. "!" 포함 (에러 발생 ❌)

 

문자열에 !가 포함되어 있어 마지막 refine 조건인 val.indexOf("!")에서 -1이 아닌 다른 값이 리턴되어 검증에 실패하게 된다.

 

 

에러 커스텀

검증 로직이 없어도 required_error와 invalid_type_error 옵션을 사용해 모든 Zod 스키마 타입에서 에러를 커스텀할 수 있다.

const ageSchema = z.number({
  required_error: "Age is required", // 값이 입력되지 않았을 때
  invalid_type_error: "Age must be a number", // 잘못된 타입이 입력되었을 때
});

const nameSchema = z.string({
  required_error: "Name is required",
  invalid_type_error: "Name must be a string",
});

const isActiveSchema = z.boolean({
  required_error: "isActive is required",
  invalid_type_error: "isActive must be true or false",
});

const tagsSchema = z.array(z.string(), {
  required_error: "Tags are required",
  invalid_type_error: "Tags must be an array of strings",
});

required_error에는 필수인 값이 입력되지 않았을 때 나타낼 메시지를,

invalid_type_error에는 잘못된 타입이 입력되었을 때 나타낼 메시지를 설정할 수 있다.

** optional을 쓰면 해당 필드는 선택적인 필드가 되므로 required_error는 무시된다.

 

 

lte(), gte(), min(), max() 등을 사용하여 값의 범위를 설정할 수도 있는데, 범위를 벗어나는 값이 입력되었을 때는 다음처럼 에러 메시지를 설정할 수 있다.

const schema = z.number().lte(100, { message: "100 이하만 가능합니다!" });

schema.parse(50);  // 통과
schema.parse(100); // 통과
schema.parse(101); // "100 이하만 가능합니다!"

 

const passwordSchema = z.string()
  .min(8, { message: "비밀번호는 최소 8자 이상이어야 합니다!" })
  .regex(/[A-Z]/, { message: "비밀번호에 대문자가 포함되어야 합니다!" });

passwordSchema.parse("abc123");  // "비밀번호는 최소 8자 이상이어야 합니다!"
passwordSchema.parse("abcdef12"); // "비밀번호에 대문자가 포함되어야 합니다!"

refine과 같은 방식으로 message 옵션을 사용하여 에러 메세지 커스텀이 가능하다.

 

 

이처럼 zod는 입력 값에 대해 먼저 데이터 처리를 할 수 있다.

API 응답에 대해 전처리를 먼저 수행한 후 컴포넌트에 데이터가 전달된다면 컴포넌트단에서 필요한 형태로 데이터 가공을 하는 훅을 만드는 과정을 축소시킬 수 있을 것이다.

간단한 함수는 refine을 통해 완전히 zod로 대체하는 것도 충분히 가능하다.

단순한 타입 검증만이 아닌 데이터 전처리까지 가능하다는 점이 굉장히 매력적인 라이브러리라고 생각된다.

반응형
저작자표시 (새창열림)
'FrontEnd/기타' 카테고리의 다른 글
  • 반응형 디자인에 사용되는 useMediaQuery와 @media
  • Tailwind | w-screen과 w-full 비교
  • zod | Zod를 활용하여 타입 검증하기 (1)
  • CSS | border와 outline의 차이
dduniverse
dduniverse
  • dduniverse
    dduniverse
    dduniverse
  • 전체
    오늘
    어제
    • 분류 전체보기 (242)
      • Algorithm (123)
        • 알고리즘 이론 (8)
        • 백준 (19)
        • 프로그래머스 (83)
        • 구름 알고리즘 먼데이 챌린지 (13)
      • 빅데이터분석기사 (10)
        • 통계 (4)
        • 실기 (6)
      • KT에이블스쿨 (26)
      • FrontEnd (11)
        • React (5)
        • 기타 (6)
      • BackEnd (18)
        • Django (15)
        • Spring (3)
      • DS & ML (11)
        • Machine Learning (9)
        • Kaggle (2)
      • TIL (43)
        • python (22)
        • javascript (3)
        • 오류해결 (10)
        • 기타 (7)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 관리
    • 글쓰기
  • 링크

  • 인기 글

  • hELLO· Designed By정상우.v4.10.0
dduniverse
zod | Zod를 활용하여 타입 검증하기 (2)
상단으로

티스토리툴바