티스토리 뷰

TypeScript를 사용하는 궁극적인 목적은 에러를 사전에 방지하고 안전한 코드를 작성하는 것입니다. 이를 위해 가장 먼저 선행되어야 할 것은 **컴파일러의 엄격한 검사(strict: true)**이며, 그 다음은 **런타임 데이터의 무결성(Zod)**을 확보하는 것입니다.
0. 시작하기 전에: strict: true 설정의 중요성
TypeScript의 진정한 힘은 tsconfig.json에서 strict: true 옵션을 켰을 때 발휘됩니다. 이 설정은 단순히 "까다로운 검사"가 아니라, 타입 시스템이 논리적으로 결함 없이 작동하기 위한 필수 조건입니다.
왜 모든 엄격 모드 옵션을 켜야 하는가?
- noImplicitAny: 타입을 명시하지 않아 암묵적으로 any가 되는 것을 막습니다. any는 타입 시스템의 구멍이며, 이를 방지해야만 코드 전체의 타입 추적이 가능해집니다.
- strictNullChecks: null과 undefined를 엄격히 구분합니다. 런타임 에러의 가장 흔한 원인인 "Cannot read property of undefined"를 컴파일 단계에서 99% 차단합니다.
- strictFunctionTypes: 함수의 매개변수와 반환 타입이 올바르게 상속되거나 할당되는지 체크하여 예기치 못한 함수 실행 에러를 방지합니다.
결론적으로, strict: true는 정적 분석의 완성도를 높여주며, Zod는 이 정적 분석이 미처 닿지 못하는 외부 데이터(런타임)를 보호합니다.
1. 왜 Zod인가? (TypeScript의 한계)
TypeScript는 strict: true 설정을 하더라도 "이 변수는 이 타입일 것이다"라고 가정하고 코드를 짭니다. 하지만 외부에서 들어오는 데이터는 통제할 수 없습니다.
interface User {
name: string;
age: number;
}
// strict 모드가 켜져 있어도, API 응답으로 { name: "John", age: "30" } (문자열 나이)이 온다면?
// TS 컴파일러는 이를 잡을 수 없으며, 실행 중에 age.toFixed() 호출 시 에러가 발생합니다.
const userData: User = await fetch('/api/user').then(res => res.json());
Zod는 데이터를 "믿는" 대신 "검증"하여 정적 타입과 실제 데이터 사이의 간극을 메웁니다.
2. Zod 기초: 스키마 정의 및 검증
Zod를 사용하면 먼저 스키마를 정의하고, 해당 스키마를 통해 데이터를 파싱(Parsing)합니다.
2.1. 기본 타입 정의
import { z } from 'zod';
const UserSchema = z.object({
id: z.string().uuid(), // UUID 형식의 문자열
name: z.string().min(2).max(20), // 2~20자 사이의 문자열
email: z.string().email(), // 이메일 형식
age: z.number().int().positive(), // 양의 정수
isPremium: z.boolean().default(false), // 기본값 설정
});
// 데이터 검증
const result = UserSchema.safeParse({
id: "550e8400-e29b-41d4-a716-446655440000",
name: "Kim",
email: "test@example.com",
age: 25,
});
if (result.success) {
console.log("검증 성공:", result.data);
} else {
// strict 모드와 결합 시 에러 객체의 타입도 안전하게 추론됩니다.
console.error("검증 실패:", result.error.format());
}
3. infer를 이용한 TypeScript와의 연결
Zod의 가장 큰 장점 중 하나는 정의한 스키마로부터 TypeScript 타입을 자동으로 추출할 수 있다는 점입니다. 이를 통해 중복 선언을 방지할 수 있습니다.
// 스키마로부터 타입 추출
type UserType = z.infer<typeof UserSchema>;
// 이제 UserType은 아래와 동일하게 동작합니다.
/*
type UserType = {
id: string;
name: string;
email: string;
age: number;
isPremium: boolean;
}
*/
4. 고급 검증 기법
단순한 타입 체크를 넘어 비즈니스 로직을 검증에 포함할 수 있습니다.
4.1. refine을 이용한 커스텀 검증
const PasswordSchema = z.string()
.min(8)
.refine((val) => /[0-9]/.test(val), {
message: "비밀번호는 숫자를 포함해야 합니다.",
});
const RegistrationSchema = z.object({
password: z.string(),
confirmPassword: z.string(),
}).refine((data) => data.password === data.confirmPassword, {
message: "비밀번호가 일치하지 않습니다.",
path: ["confirmPassword"],
});
5. 실무 활용: Next.js API Routes 적용
API로 들어오는 데이터(request body)를 Zod로 가드(Guard)하는 패턴입니다. strict: true와 함께 사용하면 req.body의 불확실성을 완벽히 제거할 수 있습니다.
import type { NextApiRequest, NextApiResponse } from 'next';
import { z } from 'zod';
const ContactSchema = z.object({
email: z.string().email(),
message: z.string().min(10, "메시지는 최소 10자 이상이어야 합니다."),
});
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== 'POST') return res.status(405).end();
// req.body는 기본적으로 any 타입이지만, Zod를 통해 안전한 타입을 획득합니다.
const validation = ContactSchema.safeParse(req.body);
if (!validation.success) {
return res.status(400).json({
error: "유효하지 않은 요청입니다.",
details: validation.error.flatten().fieldErrors
});
}
// validation.data는 이제 완벽하게 타입이 추론된 안전한 데이터입니다.
const { email, message } = validation.data;
res.status(200).json({ success: true });
}
요약: 2중 보안 체계 구축
- 내부 보호 (strict: true): 프로젝트 내부 코드 간의 모순을 막고, null/undefined 에러를 컴파일 타임에 차단합니다.
- 외부 보호 (Zod): API 응답, 사용자 입력 등 제어할 수 없는 외부 데이터를 런타임에 즉시 검증합니다.
- 효율성 (z.infer): 스키마 하나로 검증과 타입 정의를 동시에 해결하여 코드 중복을 제거합니다.
이 두 가지를 병행하는 것이 현대적인 TypeScript 개발의 표준이며, 가장 견고한 애플리케이션을 만드는 방법입니다.
'Frontend > Typescript' 카테고리의 다른 글
| TypeScript 완벽 보안 및 설계 가이드: strict 모드, 설계 철학, 그리고 Zod (0) | 2026.02.23 |
|---|---|
| TypeScript 완벽 보안 가이드: strict 모드, any 지양, 그리고 Zod (0) | 2026.02.23 |
| Zod를 활용한 런타임 타입 검증: 실행 시점의 데이터 무결성 확보하기 (0) | 2026.02.20 |
| Next.js API Routes 및 SSR 데이터 타입 완벽 가이드 (0) | 2026.02.20 |
| Redux/Zustand와 TS: 전역 상태 관리 도구의 타입 안정성 확보 (0) | 2026.02.20 |
- Total
- Today
- Yesterday
- CSR
- 협력
- 스마트안경
- 멀티모달
- on-device ai
- SSR
- It용어
- react
- 구글
- 카카오
- 엣지컴퓨팅
- CSS
- Rag
- Javascript
- 웹기초
- java
- LLM
- HTML
- MSA
- AI
- prompt engineering
- sLLM
- TypeScript
- HBM
- Nextjs
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |