형식이 안전한 양식과 API 응답 계약
Zod로 스키마에서 TypeScript 형식을 추론하고 양식 데이터와 API 응답을 모두 검증합니다.
형식이 안전한 양식과 API 응답 계약은(는) CoddyKit의 무료 React Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 React Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. React Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
타입 안전한 데이터 형태가 중요한 이유
폼과 API 응답은 신뢰할 수 없는 소스의 데이터가 애플리케이션으로 들어오는 경계입니다. Zod를 사용하면 실행 시 검증하면서 동시에 TypeScript 타입도 추론하는 스키마를 정의할 수 있습니다.
Zod 스키마 기초
Zod의 연쇄형 API로 스키마를 정의하십시오. z.infer<typeof schema>를 사용하여 TypeScript 타입을 추출하십시오.
import { z } from 'zod';
const UserSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1).max(100),
email: z.string().email(),
age: z.number().int().min(0).max(150).optional(),
role: z.enum(['admin', 'user', 'guest']),
});
type User = z.infer<typeof UserSchema>;
// { id: string; name: string; email: string; age?: number; role: 'admin'|'user'|'guest' }Zod 리졸버를 사용하는 React Hook Form
타입 안전한 폼 검증을 위해 Zod 스키마를 React Hook Form과 통합하십시오. TypeScript가 폼 데이터와 오류의 형태를 알고 처리할 수 있습니다.
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
const LoginSchema = z.object({
email: z.string().email('Invalid email'),
password: z.string().min(8, 'At least 8 characters'),
});
type LoginData = z.infer<typeof LoginSchema>;
function LoginForm() {
const { register, handleSubmit, formState: { errors } } = useForm<LoginData>({
resolver: zodResolver(LoginSchema),
});
const onSubmit = (data: LoginData) => {
// data is LoginData — fully typed, already validated
};
}API 응답 검증
Zod로 API 응답을 구문 분석하여 경계에서 형태 불일치를 포착하십시오. API가 예상하지 못한 데이터를 반환하면 컴포넌트 깊은 곳에서 실행 중 충돌이 발생하는 대신 자세한 오류를 확인할 수 있습니다.
async function fetchUser(id: string): Promise<User> {
const res = await fetch(`/api/users/${id}`);
const json = await res.json();
return UserSchema.parse(json); // throws ZodError if shape is wrong
}안전한 구문 분석으로 우아하게 오류 처리하기
예외를 발생시키는 대신 결과 객체를 얻으려면 schema.safeParse()를 사용하십시오. 사용자에게 오류를 표시하려는 폼 검증에 적합합니다.
const result = UserSchema.safeParse(formData);
if (!result.success) {
const errors = result.error.flatten().fieldErrors;
// { name: ['Must be at least 1 character'], email: ['Invalid email'] }
return errors;
}
const user = result.data; // User — fully typed판별된 유니온과 Zod
성공 또는 오류 플래그에 따라 형태가 달라지는 API 응답을 모델링하려면 z.discriminatedUnion을 사용합니다.
const ApiResponse = z.discriminatedUnion('ok', [
z.object({ ok: z.literal(true), data: UserSchema }),
z.object({ ok: z.literal(false), error: z.string(), code: z.number() }),
]);
type ApiResult = z.infer<typeof ApiResponse>;
// { ok: true; data: User } | { ok: false; error: string; code: number }Zod 변환
파싱하는 동안 데이터를 강제 변환하거나 형태를 바꾸려면 .transform()을 사용합니다. 예를 들어 날짜 문자열을 Date 객체로 변환할 수 있습니다.
const DateSchema = z.string().transform(s => new Date(s));
// Input: '2024-01-15' → Output: Date object
const EventSchema = z.object({
title: z.string(),
date: z.string().pipe(z.coerce.date()),
});
type Event = z.infer<typeof EventSchema>;
// { title: string; date: Date }스키마 재사용
중복을 피하려면 기본 스키마에서 생성 및 업데이트 스키마를 파생합니다.
const UserSchema = z.object({ name: z.string(), email: z.string().email() });
// For creation: add password
const CreateUserSchema = UserSchema.extend({ password: z.string().min(8) });
// For update: all fields optional
const UpdateUserSchema = UserSchema.partial();
type CreateUser = z.infer<typeof CreateUserSchema>;
type UpdateUser = z.infer<typeof UpdateUserSchema>;Zod를 사용하는 서버 작업
데이터베이스에 접근하기 전에 Zod를 사용해 Next.js 서버 작업에서 양식 데이터를 검증합니다.
async function createPost(formData: FormData) {
'use server';
const schema = z.object({ title: z.string().min(3), body: z.string().min(10) });
const result = schema.safeParse(Object.fromEntries(formData));
if (!result.success) return { errors: result.error.flatten().fieldErrors };
await db.post.create({ data: result.data });
revalidatePath('/blog');
redirect('/blog');
}프론트엔드와 백엔드 간 스키마 공유
공유 패키지에서 Zod 스키마를 내보내 프론트엔드와 백엔드가 동일한 검증 로직을 사용하도록 합니다. 하나의 스키마를 유일한 기준으로 삼을 수 있습니다.
// packages/schemas/src/user.ts
export const CreateUserSchema = z.object({ ... });
export type CreateUser = z.infer<typeof CreateUserSchema>;
// Frontend imports:
import { CreateUserSchema, CreateUser } from '@company/schemas';
// Backend imports:
import { CreateUserSchema } from '@company/schemas';Zod 오류 메시지
더 나은 사용자 경험을 위해 필드별 오류 메시지를 맞춤 설정할 수 있습니다. Zod는 리졸버를 통해 이러한 메시지를 양식의 오류 표시에 자동으로 전달합니다.
const RegistrationSchema = z.object({
username: z.string()
.min(3, 'Username must be at least 3 characters')
.max(20, 'Username cannot exceed 20 characters')
.regex(/^[a-z0-9_]+$/, 'Only lowercase letters, numbers, and underscores'),
});빠른 확인
z.infer<typeof MySchema>는 TypeScript에서 무엇을 제공합니까?
요약
Zod 스키마를 한 번 정의하고 z.infer를 사용해 TypeScript 타입을 파생합니다. 타입 안전한 검증을 위해 React Hook Form에서 zodResolver를 사용합니다. 경계에서 Zod로 API 응답을 파싱하고, 사용자에게 표시할 오류에는 safeParse를 사용하며, 공유 패키지를 통해 프론트엔드와 백엔드 간에 스키마를 공유합니다.
자주 묻는 질문
“형식이 안전한 양식과 API 응답 계약” 강의는 무료인가요?
네 — “형식이 안전한 양식과 API 응답 계약” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 React Academy 강의 전체를 잠금 해제할 수 있습니다. React Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“형식이 안전한 양식과 API 응답 계약”에서 뭘 배우나요?
Zod로 스키마에서 TypeScript 형식을 추론하고 양식 데이터와 API 응답을 모두 검증합니다. 브라우저에서 직접 실행하는 실습 코드로 React Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
React Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 React Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“형식이 안전한 양식과 API 응답 계약” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 React Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 React Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 컴포넌트 변형을 위한 판별된 유니언
- React의 조건부 형식과 매핑된 형식
- 'as' 속성을 사용하는 다형성 컴포넌트
- 형식이 안전한 양식과 API 응답 계약