
콜린 맥도널이 8월 28일 Zod 4.5를 냈습니다. 간판 기능은 하나예요. z.compile(). 스키마를 미리 컴파일해두면 3~9배 빠르게 파싱합니다.
Zod는 자바스크립트와 타입스크립트에서 데이터 모양을 검사하는 라이브러리입니다. 받은 값이 약속한 형태가 맞는지 문 앞에서 걸러내는 물건이에요. 깃허브 스타 43.6k를 받았고, npm 주간 다운로드로 봐도 개발자들이 이 바닥에서 가장 많이 쓰는 검문소예요.
사람들은 발표 트윗을 112,982번 봤습니다. 숫자보다 제 눈에 걸린 건 발표문 한 줄이었어요. "컴파일된 스키마에는 특별한 규칙이 없습니다. 그냥 더 빠를 뿐입니다."
미리 컴파일하면 무엇을 아끼나요?
검사기는 두 가지 일을 합니다. 스키마를 읽어서 무엇을 봐야 하는지 정하는 일, 그리고 실제 데이터를 그 기준에 대보는 일. 지금까지는 파싱할 때마다 이 두 일을 같이 했습니다.
z.compile()은 앞의 일을 미리 끝내둡니다. 스키마를 한 번 훑어 검사 절차를 굳혀두고, 이후 파스는 굳어진 절차만 돌려요. 같은 스키마로 백만 번 검사한다면, 백만 번 하던 준비를 한 번으로 줄이는 셈입니다.
스키마가 복잡할수록 더 크게 이득을 봅니다. Zod는 객체, 배열, 유니온 모두 빠르게 검사하고, 발표문 예시의 20개 넘는 필드짜리 객체는 약 9배 빠르게 처리했어요. 단순한 스키마는 3배 쪽에 가깝고요. 준비 작업이 무거울수록 미리 해두는 값어치가 크니까요.
적용은 얼마나 손이 갑니까?
한 줄입니다.
엔트리 파일 맨 위에 import "zod/compile"을 넣으면 그 뒤로 만들어지는 모든 스키마를 첫 파스 때 알아서 컴파일합니다.
노드는 node --import zod/compile 플래그로, Bun은 preload 설정으로 똑같이 켤 수 있습니다.
기존 스키마 코드는 한 글자도 안 고칩니다.
Zod는 첫 파스에서 한 번만 컴파일합니다. 그래서 같은 스키마를 몇 번이고 다시 쓰는 코드에서 효과를 봅니다. API 응답 검사, 큐에서 꺼낸 메시지 검사, 모델이 돌려준 JSON 검사처럼 하루에 수만 번 같은 문을 지나는 코드요. 한 번 쓰고 버리는 스키마라면 굳이 켤 이유가 없습니다.
저는 이 대목을 이번 발표에서 제일 실무적인 부분으로 봅니다. 성능을 개선하려면 보통 이런 순서를 밟거든요. 새 API를 배우고, 기존 코드를 갈아엎고, 갈아엎은 코드가 예전과 같게 도는지 다시 확인하는 순서예요. 콜린 맥도널은 그 세 단계를 한 줄로 줄였습니다.
왜 테스트를 두 번 돌렸을까요?
빠르게 만들었다는 발표에는 늘 각주가 따라옵니다. "단, 이 경우에는 동작이 조금 다릅니다" 같은 각주요. 검문소에서 그런 각주는 사고로 이어집니다. 통과시키면 안 될 값을 통과시키니까요.
Zod 팀은 그 각주를 아예 없애는 쪽으로 갔습니다. 전체 테스트 스위트를 두 번 돌렸어요. 한 번은 평소대로, 한 번은 전역 자동 컴파일을 켠 채로. 양쪽이 똑같이 통과해야 "특별한 규칙이 없다"는 문장을 쓸 수 있습니다.
저는 이 절차가 이번 발표에서 가장 배울 만한 대목이라고 봅니다. 빠르게 만드는 일과 동작이 그대로임을 증명하는 일은 다른 작업이에요. 속도만 올리고 내놓으면, 확인 부담은 전부 쓰는 사람에게 넘어갑니다. 테스트를 두 번 돌리는 비용은 만든 쪽에서 한 번 치르면 끝나는데 말입니다.
파싱 말고 무엇을 더 빠르게 했나요?
z.validate()가 새로 들어왔습니다. 풀 파스를 건너뛰고 맞다 아니다만 돌려주는 함수예요. 무효 데이터에서 최대 16배 빠릅니다.
z.validate()는 파스보다 일을 덜 하거든요. 파스는 값을 검사하고, 변환하고, 실패하면 어디가 왜 틀렸는지 오류 객체까지 만들어 돌려줍니다. 들어온 요청을 버릴지 말지만 정할 때는 그 오류 객체를 아무도 안 씁니다. 불리언 하나면 될 때도 파스를 부르던 습관을 겨눈 함수입니다.
Zod 팀은 메모리 사용량도 9분의 1로 줄였습니다. 스키마 수천 개를 띄워두는 서버라면 이쪽이 더 반가운 숫자일 겁니다.
부가 기능도 여럿 왔습니다. z.creditCard()는 카드번호를 룬 체크섬으로 검사합니다. z.properties()가 들어왔고, Zod 4에서 빠졌던 .deepPartial()이 돌아왔어요. .exactPartial()은 키가 아예 없는 경우와 키에 undefined가 든 경우를 구분해 뒤쪽을 거부합니다. 로케일도 8종 늘려서 벵골어, 힌디어, 브라질 포르투갈어로도 오류 문구를 보여줍니다.
에이전트한테 이게 왜 큰 뉴스입니까?
요즘 개발자들은 Zod를 모델 출력 검사에도 많이 씁니다.
LLM에 구조화 출력을 시킬 때, 툴콜 인자를 정의할 때, 개발자들은 그 스키마를 대체로 Zod로 적어요. 모델이 뱉은 JSON이 약속한 모양인지 확인할 때도 Zod를 쓰고요. 에이전트 한 턴에 이 문을 몇 번 지나는지 따져보면 감이 옵니다. 툴 하나 부를 때마다 인자 검사 한 번, 결과 검사 한 번, 상태를 다시 넣을 때 또 한 번.
루프가 길어질수록 검사 횟수도 선형으로 늘어납니다. 초당 수천 번 도는 검사라면 3배도 손에 잡힐 차이예요. 모델을 바꾸지 않고, 프롬프트를 손대지 않고, 임포트 한 줄로 얻는 3배라면 더 그렇습니다.
한 가지는 짚어둬야 합니다. 에이전트 루프에서 제일 오래 걸리는 구간은 여전히 모델 응답을 기다리는 시간입니다. 파싱을 아홉 배 빠르게 해도 전체 응답 시간을 아홉 배 줄이진 못해요. 다만 대량 배치, 검증 파이프라인, 스트리밍 파싱처럼 모델을 기다리지 않는 구간에서는 이 숫자를 그대로 누립니다.
남는 생각
저는 이 발표를 속도 소식보다 검증 소식으로 읽습니다.
저는 한 가지 축을 계속 따라왔습니다. 에이전트가 만든 결과를 누가 확인하느냐, 그 확인을 기계가 대신 도느냐는 축이에요. z.compile()은 데이터가 시스템에 들어오는 첫 문을 개선합니다.
이 라이브러리를 만든 쪽은 자기 개선을 자기 규칙으로 검사했습니다. 빨라진 물건이 조용히 다르게 굴지 않는다는 증거를 먼저 만들고, 그다음에 3~9배를 말했어요. 저는 이 순서가 숫자보다 오래 남는다고 봅니다.
빠르게 만든 사람은 많이 봤어도, 동작이 그대로라는 것까지 증명하고 내놓는 사람은 별로 못 봤습니다.
원문·소스
- Zod 4.5 발표 트윗 (@colinhacks): https://x.com/colinhacks/status/2093725420462182512
- Zod 4.5 릴리스 노트: https://zod.dev/blog/zod-4-5
FAQ
자주 묻는 질문
- Zod는 컴파일로 무엇을 바꿔 아홉 배 속도를 낼까요?
- 스키마를 읽어 검사 절차를 미리 굳혀두고, 이후 파스는 굳어진 절차만 돌립니다. 같은 스키마로 백만 번 검사한다면 백만 번 하던 준비를 한 번으로 줄이는 셈이에요. 20개 넘는 필드짜리 객체는 약 9배, 단순한 스키마는 3배 쪽에 가깝습니다.
- 적용은 얼마나 손이 갑니까?
- 한 줄입니다. 엔트리 파일 맨 위에 import "zod/compile"을 넣으면 그 뒤로 만들어지는 모든 스키마가 첫 파스 때 알아서 컴파일돼요. 기존 스키마 코드는 한 글자도 안 고칩니다.
- 왜 테스트를 두 번 돌렸을까요?
- 빨라진 물건이 조용히 다르게 굴지 않는다는 증거를 만들기 위해서입니다. 전체 테스트 스위트를 한 번은 평소대로, 한 번은 전역 자동 컴파일을 켠 채로 돌렸어요. 양쪽이 똑같이 통과해야 '특별한 규칙이 없다'는 문장을 쓸 수 있습니다.
- 에이전트한테 이게 왜 큰 뉴스입니까?
- LLM 구조화 출력, 툴콜 인자 정의, 모델이 뱉은 JSON 검사를 대체로 Zod가 맡기 때문입니다. 툴 하나 부를 때마다 인자 검사, 결과 검사, 상태 재삽입까지 검문을 여러 번 지나요. 모델을 바꾸지 않고 임포트 한 줄로 얻는 3배라면 손에 잡히는 차이입니다.

SEASON 3
시즌3 「콘텐츠로 팔기」
AI와 콘텐츠를 만들고 고객에게 연결하는 4주
제가 에이전트로 조사하고 쓰고 파는 과정을 그대로 보여 드려요. 그다음 각자의 주제로 같이 만들어 봐요.
10월 2일 OT · 10월 5일부터 월·수 4주 · 10월 31일 오프라인
시즌3 커리큘럼 보기