Zod로 유효성 검증과 타입 선언의 두 마리 토끼 잡기
이전 포스팅에서 타입스크립트로 코드를 작성하는 것과 무관하게 왜 자바스크립트 프로그램에서 유효성 검증이 필요한지에 대해서 알아보았는데요.
이번 포스팅에서는 최근 개발자들로부터 많은 인기를 끌고 있는 Zod를 사용하는 전반적인 방법에 대해서 알아보겠습니다.
라이브러리 설치
프로젝트에 zod
라는 패키지를 npm으로 설치합니다.
$ npm i zod
그리고 Zod를 사용하실 때는 가급적 타입스크립트는 strict 모드로 쓰시기를 추천드릴게요.
{
"compilerOptions": {
"strict": true
}
}
이제 zod
패키지에서 z
를 불러올 수 있으며, 이 녀석만 있으면 우리는 Zod의 모든 기능을 활용할 수 있습니다.
import { z } from "zod";
스키마 정의
Zod를 사용할 때 제일 먼저 해야되는 것은 스키마(schema)를 정의하는 것입니다.
여기서 스키마란 쉽게 말해서 데이터의 형태와 구조를 뜻하는데요. 예를 들어, 이메일, 나이, 활성화 여부로 이루어진 사용자 객체를 나타내는 스키마를 Zod로 정의해보겠습니다.
const User = z.object({
email: z.string(),
age: z.number(),
active: z.boolean(),
});
z.object()
를 사용하여 User
스키마가 객체의 형태이고, z.string()
으로 email
속성은 문자열, age
속성은 z.number()
로 숫자, active
속성은 z.boolean()
으로 불리언 형태입니다.
뭐, 별 거 없죠? 그런데 API가 굉장히 간단하고 명료하지 않나요?
Zod를 처음 사용하시는 분들도 이러한 직관적인 API 덕분에 큰 어려움 없이 배울 수 있답니다.
유효성 검증
Zod 스키마를 정의하고 나면 유효성 검증을 해볼 수 있는데요.
스키마의 parse()
함수에 검증하고 싶은 값을 넘겨서 호출하면 됩니다.
User.parse({
email: "user@test.com",
age: 35,
active: true,
}); // ✅ 유효성 검증 통과
User.parse({
email: "user@test.com",
age: "35",
}); // ❌ 유효성 검증 실패
검증이 실패할 경우에는 parse()
함수는 오류(error)를 발생시키는데요.
정확히 어느 부분에서 어떤 검증을 통과하지 못했는지가 나와서 매우 유용합니다.
ZodError: [
{
code: "invalid_type",
expected: "number",
received: "string",
path: ["age"],
message: "Expected number, received string",
},
{
code: "invalid_type",
expected: "boolean",
received: "undefined",
path: ["active"],
message: "Required",
},
];
여기서 한 가지 주의할 부분은 검증이 성공했을 경우 parse()
함수가 반환하는 객체에는 검증에 통과한 속성만 포함된다는 것입니다.
예를 들어, 다음과 같이 스키마에 정의되지 않은 password
속성을 입력 객체에 포함한 경우,
const user = User.parse({
email: "user@test.com",
age: 35,
active: true,
password: "abcd1234",
});
console.log(user);
parse()
함수가 반환한 결과 객체에는 해당 속성이 제외되어 있는 것을 볼 수 있습니다.
{
email: "user@test.com",
age: 35,
active: true,
}
이것은 parse()
함수의 반환 타입이 정의된 스키마에 의해서 결정이 되기 때문입니다.
타입에 password
속성이 없는데 값에만 password
속성이 들어있다면 타입 에러가 발생했을 것입니다.
console.log(user);
// ^? const user: { email: string; age: number; active: boolean; }
이처럼 Zod는 타입스크립트에 아주 친화적으로 설계되어 있어서 견고한 코드를 작성하는데도 도움을 줍니다.
타입 추론
뿐만 아니라 Zod는 스키마를 기준으로 타입스크립트 타입을 알아서 추론할 수도 있는데요. 이 기능을 잘 활용하면 아예 타입을 따로 작성할 필요가 없어지고 따라서 타입을 스키마와 서로 맞춰 줄 걱정이 사라집니다.
예를 들어서, 사용자 객체를 입력으로 받는 함수를 타입스크립트로 작성하려면 아래와 같이 입력 타입을 작성해줘야하는데요.
// 내가 직접 타입을 작성
interface User {
email: string;
age: number;
active: boolean;
}
function processUser(user: User) {
User.parse(user); // 유효성 검증
// 사용자 처리 로직
}
하지만 Zod의 infer
과 자바스크립트의 typeof
연산자를 사용하면 이미 정의한 스키마로 부터 타입을 뽑아낼 수 있습니다.
// 스카마로부터 타입을 추론 👍
type User = z.infer<typeof User>;
function processUser(user: User) {
User.parse(user); // 유효성 검증
// 사용자 처리 로직
}
스키마 하나 작성해서 유효성 검증도 하고 타입스크립트 타입도 뽑아내고 완전 꿩먹고 알먹고 아닌가요? 😁
예제의 스키마는 단순해서 타입을 직접 작성하시는 게 대수롭지 않게 느껴질 수도 있는데요. 실제 프로젝트에서는 훨씬 복잡한 스키마를 다루실 때는 Zod의 이러한 편리함이 훨씬 크게 느껴질 것입니다.
직접 작성한 타입과 스키마가 항상 서로 일치하도록 관리한다는 게 여간 번거로운 일이 아니며 까먹기도 참 쉽거든요. Zod를 사용하면 스키마 활용을 극대화하고 불필요한 타입을 작성을 최소화할 수 있어서 개발 생산성이나 유지 보수 측면에서 큰 도움을 받을 수 있습니다.
마치면서
지금까지 Zod를 사용하여 어떻게 유효성 검증과 타입 선언이라는 두 마리의 토끼를 잡을 수 있는지에 대해서 살펴보았습니다.
다음 포스팅에서는 Zod의 스키마를 작성하는 방법에 대해서 좀 더 상세히 알아보도록 하겠습니다.
Zod 관련 포스팅은 Zod 태그를 통해서 쉽게 만나보세요!