2025.2.14 금요일의 공부기록
Zod는 문자열 검증뿐만 아니라 정규 표현식, 변환(transform
), 공백 제거(trim
), 소문자 변환(toLowerCase
) 등의 다양한 기능을 제공한다.
이 기능들을 활용하면 보다 정밀한 데이터 검증 및 변환이 가능하다.
📌 공식 문서 참고:
.regex()
)import { z } from "zod";
// **비밀번호 정규표현식 (소문자, 대문자, 숫자, 특수문자 포함)**
const passwordRegex = new RegExp(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*?[#?!@$%^&*-]).+$/);
const passwordSchema = z.string()
.min(8, { message: "비밀번호는 최소 8자 이상이어야 합니다." })
.regex(passwordRegex, { message: "비밀번호는 대문자, 소문자, 숫자, 특수문자를 포함해야 합니다." });
console.log(passwordSchema.safeParse("Abc123!@#")); // ✅ 통과
console.log(passwordSchema.safeParse("abc123")); // ❌ 실패 (대문자, 특수문자 없음)
console.log(passwordSchema.safeParse("ABC123!@#")); // ❌ 실패 (소문자 없음)
📌 설명:
.regex(passwordRegex, { message })
→ 정규 표현식을 사용하여 대소문자, 숫자, 특수문자 포함 여부를 검증..min(8, { message })
→ 비밀번호 최소 길이 검증.const phoneSchema = z.string().regex(/^010-\d{4}-\d{4}$/, {
message: "올바른 전화번호 형식이 아닙니다. (예: 010-1234-5678)",
});
console.log(phoneSchema.safeParse("010-1234-5678")); // ✅ 통과
console.log(phoneSchema.safeParse("123-456-7890")); // ❌ 실패
console.log(phoneSchema.safeParse("01012345678")); // ❌ 실패
📌 설명:
.regex(/^010-\d{4}-\d{4}$/)
→ "010-1234-5678"
형식인지 검증..toLowerCase()
, .trim()
)const emailSchema = z.string().email().toLowerCase();
console.log(emailSchema.parse("User@Example.com")); // ✅ "user@example.com"
console.log(emailSchema.parse("TEST@GMAIL.COM")); // ✅ "test@gmail.com"
📌 설명:
.toLowerCase()
→ 모든 문자를 소문자로 변환..trim()
)const usernameSchema = z.string().trim();
console.log(usernameSchema.parse(" user123 ")); // ✅ "user123"
console.log(usernameSchema.parse(" hello ")); // ✅ "hello"
📌 설명:
.trim()
→ 앞뒤 공백을 자동으로 제거..transform()
)Zod의 .transform()
을 활용하면 데이터를 변환하여 원하는 형식으로 저장할 수 있다.
const stringToNumber = z.string().transform((val) => val.length);
console.log(stringToNumber.parse("Hello")); // ✅ 5
console.log(stringToNumber.parse("Zod!")); // ✅ 4
📌 설명:
.transform((val) => val.length)
→ 문자열의 길이를 반환하는 스키마.const usernameSchema = z.string().transform((username) => `🔥 ${username} 🔥`);
console.log(usernameSchema.parse("John")); // ✅ "🔥 John 🔥"
console.log(usernameSchema.parse("Alice")); // ✅ "🔥 Alice 🔥"
📌 설명:
.transform((username) =>
🔥 ${username} 🔥)
→ 이모지를 추가한 변형된 값을 반환.const numberSchema = z.string()
.transform((val) => Number(val))
.refine((num) => num > 0, { message: "숫자는 0보다 커야 합니다." });
console.log(numberSchema.safeParse("10")); // ✅ 10
console.log(numberSchema.safeParse("-5")); // ❌ 실패 (음수는 허용되지 않음)
console.log(numberSchema.safeParse("abc")); // ❌ 실패 (숫자가 아님)
📌 설명:
.transform((val) => Number(val))
→ 문자열을 숫자로 변환..refine((num) => num > 0, { message })
→ 0보다 큰 숫자인지 검증.createAccount
서버 액션 (회원가입 검증)"use server";
import { z } from "zod";
function checkUsername(username: string) {
return !username.includes("admin");
}
const passwordRegex = new RegExp(
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#?!@$%^&*-]).+$/
);
const checkPasswords = ({
password,
confirm_password,
}: {
password: string;
confirm_password: string;
}) => password === confirm_password;
const formSchema = z
.object({
username: z
.string({
invalid_type_error: "Username must be a string",
required_error: "Username is required",
})
.min(3, "Way too short!!")
.max(10, " Way too long!!")
.toLowerCase()
.trim()
.transform((username) => `${username}🇰🇷`)
.refine(checkUsername, "Username cannot contain 'admin'"),
email: z.string().email(),
password: z
.string()
.min(10)
.regex(
passwordRegex,
"Password too weak, must contain at least one uppercase letter, one lowercase letter, and one special character"
),
confirm_password: z.string().min(10),
}) //아래의 refine은 form 전체에 대한 refine임을 주의 confirm_password에 붙은 게 아님
.refine(checkPasswords, {
message: "Passwords do not match",
path: ["confirm_password"],
});
export async function createAccount(prevState: any, formData: FormData) {
const data = {
username: formData.get("username"),
email: formData.get("email"),
password: formData.get("password"),
confirm_password: formData.get("confirm_password"),
};
const result = formSchema.safeParse(data);
if (!result.success) {
return result.error.flatten();
}
}
📌 설명:
trim()
→ 공백 제거.toLowerCase()
→ 이메일을 소문자로 변환..regex()
→ 비밀번호 복잡도 검사..refine()
→ 비밀번호 & 비밀번호 확인 일치 검증.✅ 기능 | 🛠 설명 |
---|---|
정규 표현식 검증 | .regex(/정규식/, { message }) |
소문자로 변환 | .toLowerCase() |
공백 제거 | .trim() |
데이터 변환 | .transform((val) => 변환 값) |
비밀번호 강도 검증 | .regex(passwordRegex, { message }) |
숫자로 변환 후 검증 | .transform((val) => Number(val)).refine((num) => num > 0, { message }) |
📌 더 자세한 내용은 Zod 공식 문서를 참고하자! 🚀