DevLog 2024년 11월 25일
TypeScript로 타입 안전한 API 설계하기

TypeScript로 타입 안전한 API 설계하기

Zod와 TypeScript로 완벽한 타입 안전성을 가진 API를 구축한 경험

#TypeScript #API #Backend

TypeScript와 Zod를 활용하여 런타임과 컴파일 타임 모두에서 타입 안전성을 확보했습니다.

문제 상황

기존 REST API에서 다음과 같은 문제들이 있었습니다:

  1. 런타임 타입 에러: 클라이언트에서 보낸 데이터가 예상과 다른 경우
  2. 문서 불일치: API 문서와 실제 구현이 달라지는 문제
  3. 디버깅 어려움: 타입 관련 에러가 런타임에서만 발견

해결 방안

1. Zod 스키마 정의

import { z } from 'zod';

const CreateUserSchema = z.object({
  email: z.string().email(),
  password: z.string().min(8).max(100),
  name: z.string().min(2).max(50),
  age: z.number().min(18).max(120).optional(),
});

type CreateUser = z.infer<typeof CreateUserSchema>;

2. API 라우트에서 검증

app.post('/api/users', async (req, res) => {
  const result = CreateUserSchema.safeParse(req.body);
  
  if (!result.success) {
    return res.status(400).json({ 
      errors: result.error.flatten().fieldErrors 
    });
  }
  
  const user = await create_user(result.data);
  return res.json(user);
});

3. 자동 타입 생성

// API 클라이언트에서 사용할 타입
export type CreateUserRequest = z.infer<typeof CreateUserSchema>;
export type UserResponse = z.infer<typeof UserSchema>;

성과

타입 관련 버그

  • 개선 전: 월평균 15건의 런타임 타입 에러
  • 개선 후: 월평균 0건 (개발 단계에서 모두 포착)

개발 생산성

  • API 문서 자동 생성: Zod 스키마에서 Swagger 문서 생성
  • 타입 추론 자동화: 클라이언트/서버 간 타입 자동 동기화

핵심 교훈

“타입 안전성은 선택사항이 아니라 필수사항이다”

런타임 타입 에러는 사용자 경험을 심각하게 저해합니다. TypeScript + Zod 조합은 개발자 경험과 사용자 경험을 동시에 향상시키는 최고의 툴입니다.