본문 바로가기

새소리

zod 의 사용에 대한 뇌피셜

길거리 의자 위의 참새들. Unsplash 에 Christopher Le 님이 올림.

들어가는 말

Zod를 아시나요? 저는 얼마 전까진 몰랐습니다. 처음 접했을 때는 정말 좋다고 생각했었고, 컴포넌트 한두개 정도에 사용하는 정도로 찍먹했을 때는 좋기도 하고 불편하기도 한 양가감정이 들었습니다. 이후에 회사 내에서 이 라이브러리를 사용하는 게 어떻겠냐는 의견이 고개를 들었어요. 그래서 '과연 이 라이브러리가 필요한가?' 라는 주제로 살짝 조사를 했고, 거기에 대한 제 생각을 적어 봅니다. 실제로 많이 사용해보고 적는 게 아니라 문서를 훑어보고 드는 생각들을 적은 것이니 참고해 주세요!

Zod?

먼저 이게 뭔지 간단하게 적겠습니다. Zod의 공식 홈페이지에서는 자기 자신을 TypeScript-first 스키마 선언과 검증 라이브러리라고 요약합니다. 타입 구조를 선언하고, 그걸 바탕으로 타입스크립트의 정적 타입과 해당 타입을 검사하는 parser를 손쉽게 만들 수 있습니다.

 

import { z } from "zod";

const User = z.object({
  username: z.string(),
  level: z.number().int().gt(0),
});

type UserType = z.infer<typeof User>;

User.parse({
  username: 'sparrow',
  level: '999',
});

 

이런 느낌으로요. 조금 더 나아가면 parse에서 발생하는 에러에 대해 어디서 생긴 문제인지 직접 메시지를 작성할 수도 있고, 나만의 검증 함수를 추가로 적용할 수 있는 기능도 있습니다.

Zod 공식 문서에 적혀 있는 핵심 개념들은 아래와 같아요.

 

  • 스키마 선언과 검증
  • 개발자 친화적인 사용법
  • 목표: 타입 중복 선언 제거
  • Zod 로 타입 검사기(validator)를 만들면 타입스크립트 정적 타입을 자동으로 만들 수 있음
  • Zod 객체를 조합해서 더 복잡한 타입 역시 간단하게 표현 가능

그렇다면 이런 개념들이 실제로 필요한 것인가? 에 대한 생각을 할 차례군요.

타입 선언과 검증

사실 타입스크립트를 쓴다는 것 자체부터 타입 선언의 필요성을 인지한다는 것이라고 생각해요. 저는 개인적으로 예전에 파이썬 시절 다른 라이브러리에서 제공하는 함수들의 출력 타입에 고통받았던 적이 있어서 정적 타입은 진짜 필요하다고 생각하고 있습니다.

 

문제는 타입 '검증'이 필요한지일 겁니다. 타입스크립트의 구조적 타이핑을 생각해 보면 개발 단계에서는 사실 타입을 잘못 쓰면 즉시 빨간 줄이 나오면서 저의 마음을 아프게 합니다. 이래 놓고 런타임에서는 언제 그랬냐는 듯 제대로 돌아가는 '척' 할 때도 많구요. 즉 일반적인 상황에서는 개발 단계에서 인지하고 있다면 충분히 타입 검증이 없어도 어플리케이션이 타입에 맞게 돌아가는지 확인이 가능합니다. Github Actions 같은 장치를 이용한다면 미처 찾지 못한 타입 오류를 빌드 단계에서 검증할 수도 있죠.

 

하지만 타입 검증이 필요한 경우가 있습니다. 저는 크게 두 가지 경우라는 생각이 들어요. 첫 번째는 양식(form) 검증입니다. 전화번호부터 이메일까지 귀찮은 입력 형태만을 통과시키고 싶어 하는 입력은 지천이에요. 물론 검증 자체는 정규 표현식을 사용한다면 가능하지만 그걸 위한 함수들을 만들고 조립하는 과정이 귀찮을 수 있죠. 저는 이런 점에서 Zod 가 괜찮다는 생각이 들었습니다. 타입의 형태를 잡을 행동이 곧 검증 함수를 만드는 행동이고, 거기에 항목 별 오류 메시지까지 적을 수 있으니까요.

 

두 번째는 api 데이터 검증입니다. 물론 이론 상 이 타입은 틀릴 수가 없습니다. 외부 api 라면 본인들의 공식 문서에 다 정리되어 있을 것이고 여기는 잘못되었을 때 문제를 금방 발견할 사람들이 정말 많습니다. 프로젝트 백엔드 api라면 협업해서 만들었든 일방적으로 주어졌든 어떤 형태로든 문서에 정리되어 있겠죠. 하지만 현실은 api 문서의 업데이트가 한 발짝 늦을 수도 있고, 반대로 문서에는 미리 반영했지만 아직 merge가 되지 않았을 수도 있습니다. 어쩌면 전임자가 바꾼 후 알리는 걸 깜빡하고 퇴사했을 수도 있구요. 레거시 코드이고, 자주 사용하지 않고, json 타입을 봤더니 항목들이 많을수록 이런 의심은 커집니다. 이런 상황에서는 Zod 를 이용한 타입 검증이 굉장히 강력하다고 생각해요. api 타입이 틀려서 화면이 잘못 그려지는 경우 자체를 확실하게 잡아낼 수 있어서요.

 

결국 외부에서 오는 값들을 의심해야 한다면 Zod 가 도움이 된다는 생각입니다. 내부 코드에서 사용하는 값은 타입스크립트를 사용한다면 굳이 이 라이브러리가 없어도 오류를 찾을 수 있다고 생각해요.

타입 중복 선언 제거와 더 복잡한 타입 선언

이건 솔직히 모르겠어요. 타입스크립트를 사용한다면 단순한 타입 합치기 뿐만 아니라 제네릭이나 유틸리티 타입이라는 강력한 도구들이 이미 있는데, 어떤 점에서 중복을 없앤다는 것인지는 모르겠습니다.

 

'복잡한 타입' 역시 무엇이 '복잡하다'고 느끼는지는 모르겠지만 Zod 는 타입 검증을 간단하게 해 주는 것이지 복잡한 타입의 선언 자체를 간단하게 해 준다는 느낌은 받지 못했습니다.

타입 검사기와 정적 타입 생성을 동시에

이게 제가 들어가는 말에 적었던 '좋은데 불편한' 점입니다. 동시에 해서 작업량이 줄어드는 건 좋아요. 근데 정적 타입 자체를 보기에 힘듭니다. 그냥 타입스크립트의 타입이나 인터페이스를 썼다면 쭉쭉 읽으면 되는데 이 친구는 z.뭐시기() 이런 식으로 달려 있고 검증 관련된 로직이 들어가면 위아래로 길어지면서 한 눈에 들어오지 않더라구요. 그냥 개인적인 취향 문제긴 합니다.

 

분리되어 있던 관심사를 합치면서 복잡해지는 감이 없잖아 있다고 생각합니다. '타입 검증'은 런타임 행동에 가깝고, '정적 타입'은 그보다 한 발짝 빠른 컴파일 또는 코드 작성 단계 자체에서 하는 행동이니까요.

개인의견) 그래서 쓰는 게 좋을까?

저는 조사하면서 나름의 결론을 짓긴 했어요.

1. API 문서에 적혀 있는 자료형을 믿을 수 있는가?

정말 사람마다 그리고 상황에 따라가는 내용이에요. 하지만 저는 믿을 수 없다는 생각이 들면 Zod 를 도입해서 api 문서에 적혀 있는대로 오는 게 맞는지 검증을 하는 게 맞다고 생각합니다. 다만 이 검증 로직 자체는 실제 프로덕션 빌드에서는 돌아갈 이유가 없다고 생각해요(정적 타이핑이라는 관점에서). 그래서 zod-dev 같은 걸 추가해서 개발 환경에서 미리 API 값을 검증하고 실제 배포했을 때는 생략하는 방향으로 가고 싶어요.

2. 자바스크립트를 쓰는가?

Zod 는 자바스크립트에도 문제 없이 적용되기 때문에 알 수 없는 이유로 타입스크립트를 사용하지 않는다면 이 라이브러리를 통해 타입에 관련된 실수들을 잡을 의향이 있어요.

양식 입력에는..

입력값 검증을 위해서 Zod 를 도입하는 건 사실 이 라이브러리의 핵심 개념들과 살짝 맞지는 않는 것 같아요. 만약 이미 프로젝트에 Zod 가 도입되어 있다면 양식 검증에 사용할 것 같아요.

전반적으로는..

타입스크립트를 사용하는 일반적인 상황에서 꼭 도입해야 할 라이브러리는 아니라고 생각합니다. 다만 외부 자료에 대한 의심이 필요한 상황에서는 강력한 무기가 되어줄 수 있겠네요.

'새소리' 카테고리의 다른 글

디자인 시스템이 필요한가에 대한 개인 의견  (0) 2024.06.29
관심사란 무엇일까?  (8) 2023.04.30
[경고] 야생참새 주의  (0) 2023.04.30