Utilo

JSON to TypeScript Interfaces: API 응답을 입력하는 실용적인 안내서

JSON을 정확한 타입스크립트 인터페이스로 변환하고, 선택 필드, nulls, union 및 array을 처리하고, 타입을 실제 API와 동기화하는 방법을 배우십시오.

· 4분 분량

API와 대화하는 모든 타입스크립트 프로젝트가 결국 같은 질문에 직면합니다. 응답을 any로 남겨두면, 타이프스크립트의 주요 장점이 사라집니다. 200줄의 유해물량에 대해 손으로 인터페이스를 작성하는 것은 지루하고 오류가 발생할 수 있습니다. 이 가이드는 JSON에서 인터페이스를 생성하고 정제하고 시간이 지남에 따라 정직하게 유지하는 신뢰할 수 있는 워크플로를 안내합니다.

왜 JSON 타입이 중요한지

await res.json()을 호출할 때, 타입스크립트는 any를 제공합니다. 그 순간부터 user.adress.city와 같은 타이포는 불만 없이 컴파일되고 실행시, 종종 생산시, 종종 데이터 차이가 있는 사용자 하위 집합에 실패합니다. 입력된 응답은 백엔드가 필드를 다시 이름 붙일 때 자동 완료, 안전한 리팩터링 및 컴파일 시간 오류를 제공합니다.

타입은 또한 문서화 역할을 합니다. interface Order { id: string; items: OrderItem[]; total: number; couponCode?: string }을 읽는 새로운 팀원은 표본 응답을 스크롤하는 것보다 5초 안에 더 많은 것을 배울 수 있습니다.

단계 1: 실제, 대표적인 표본에서 시작

생성된 타입은 여러분이 입력한 샘플만큼이나 좋습니다. 변환하기 전에 가능한 한 많은 필드를 실행하는 응답을 수집합니다:

  • 쿠폰, 배송 주소 및 선물 메시지가 있는 주문과 같은 선택 필드가 채워진 레코드를 선택하세요.
  • 적어도 하나의 요소를 가진 배열을 포함하십시오. 빈 배열은 생성기에 그 내용에 대해 아무 것도 말하지 않습니다.
  • 만약 필드가 null이 될 수 있다면, null이 있는 한 예제와 그렇지 않은 한 예제를 포함하려고 노력하십시오.

네이버의 네트워크 탭이나 curl에서 응답 본부를 복사하여 [JSON 포맷] (/tools/json) 에 붙여서 유효성을 확인합니다. 다음 모드를 →TypeScript로 전환합니다.

단계 2: 첫 번째 초안을 작성

이 입력값을 감안하면

{
  "id": "ord_9f2",
  "createdAt": "2026-09-30T12:01:44Z",
  "customer": { "id": 42, "email": "ana@example.com" },
  "items": [
    { "sku": "TSHIRT-M", "qty": 2, "price": 19.5 },
    { "sku": "MUG", "qty": 1, "price": 12 }
  ],
  "coupon": null
}

발전기는 다음과 같은 것을 생산합니다.

export interface Customer {
  id: number;
  email: string;
}

export interface Item {
  sku: string;
  qty: number;
  price: number;
}

export interface Root {
  id: string;
  createdAt: string;
  customer: Customer;
  items: Item[];
  coupon: null;
}

이것은 견고한 출발점이지만 하나의 표본이 포함된 것을 반영합니다. 다음 단계에서는 API 계약과 일치하는 타입으로 변환합니다.

단계 3: 이름 변경 및 정제

생성자는 키의 이름을 따서 둥지를 틀어 놓은 인터페이스를 이름짓습니다. 도메인 용어로 이름을 바꾸면 Root이 Order, Item가 OrderItem가 됩니다. 그 다음 이 질문 들 을 가지고 각 필드 를 검토 해 보십시오.

실용되지 않을 수 있나요? API가 어떤 응답에서 키를 생략하면 ?로 선택적으로 표시하세요. 선택적 (coupon?: Coupon) 및 무효 (coupon: Coupon | null) 는 다릅니다: 첫 번째 의미는 키가 없을 수 있으며 두 번째는 항상 존재하지만 null를 보유 할 수 있음을 의미합니다. 많은 API는 둘 다 합니다. coupon?: Coupon | null로 표현하죠.

null이 유일한 값이었나요? null로 문자 그대로 입력된 필드는 거의 항상 표본이 대표적이지 않다는 것을 의미합니다. 진짜 타입과 | null로 교체하세요

** 문자열은 정말 문자열입니까?** 날짜는 ISO 8601 문자열로 나타납니다. 트랜스포트 타입에서 string로 보관합니다. Date로 변환하는 것은 매핑 레이어에 속합니다. 당신은 type ISODateString = string라는 형식 위명으로 의도를 문서화할 수 있습니다.

** 숫자가 enum인가?** 만약 status이 항상 몇 가지 값 중 하나라면, 문자들의 조합을 사용하라: status: "pending" | "paid" | "shipped". 이것은 switch를 철저하게 검사합니다.

**ID는 숫자로 안전합니까? ** 2^53 이상의 데이터베이스 ID는 자바스크립트에서 정확성을 잃습니다. 백엔드가 64비트 정수를 사용하는 경우 ID를 문자열로 보내 string로 입력하도록 요청합니다.

정제된 결과:

export type ISODateString = string;

export interface Order {
  id: string;
  createdAt: ISODateString;
  status: "pending" | "paid" | "shipped" | "cancelled";
  customer: Customer;
  items: OrderItem[];
  coupon?: Coupon | null;
}

단계 4: 혼합된 내용의 배열을 처리합니다.

일부 API는 다양한 이벤트 유형을 가진 활동 피드와 같은 이질적인 배열을 반환합니다. 순진한 생성기는 모든 필드가 선택적으로 있는 하나의 인터페이스를 생성합니다. 차별이 없는 조합은 훨씬 낫습니다.

type FeedEvent =
  | { type: "comment"; id: string; text: string }
  | { type: "like"; id: string; userId: string }
  | { type: "follow"; id: string; followerId: string };

이제 타입스크립트는 if (event.type === "comment") 내부의 타입을 자동으로 좁혀줍니다. 혼합 배열을 변환할 때, 도구는 추론된 항목 유형을 결합합니다. 그 출력을 손으로 차별화된 조합을 설계하는 힌트로 사용하십시오.

단계 5: 실행시 확인

타입스크립트 타입은 컴파일 시에 사라집니다. 만약 백엔드가 바뀌면, 코드는 여전히 새로운 형태를 받게 되고, 타입은 침묵으로 누워 있습니다. 신뢰 경계를 넘는 데이터의 경우, Zod, Valibot 또는 ArkType와 같은 스키마 라이브러리로 런타임 검증을 추가하고 스키마에서 정적 타입을 도출합니다.

import { z } from "zod";

const OrderSchema = z.object({
  id: z.string(),
  createdAt: z.string().datetime(),
  items: z.array(z.object({ sku: z.string(), qty: z.number().int(), price: z.number() })),
  coupon: z.object({ code: z.string() }).nullable().optional(),
});

export type Order = z.infer<typeof OrderSchema>;
const order = OrderSchema.parse(await res.json());

당신은 여전히 생성기를 사용해서 인터페이스를 생성할 수 있습니다. 그 다음은 그것을 스키마에 필드별로 번역할 수 있습니다.

6단계: 진리 가 있을 때 그 진리 의 근원 을 선호 하라

만약 API가 OpenAPI (Swagger) 또는 GraphQL 스키마를 게시한다면 샘플 대신 그로부터 타입을 생성합니다. openapi-typescript과 GraphQL 코드 생성기와 같은 도구는 옵션 및 enums를 포함한 정확한 타입을 생성하고 CI에서 실행할 수 있으므로 스키마가 변경될 때마다 타입이 업데이트됩니다. 샘플 기반 생성은 스키마, 빠른 프로토타입, 웹 및 레거시 서비스 없이 제3자 API를 위해 빛난다.

인터페이스나 타입?

객체 모양의 경우, interface과 type는 거의 교환이 가능합니다. 인터페이스는 확장 및 통합 될 수 있으며 오류 메시지는 큰 객체에 도움이되는 이름을 참조합니다. 타입 위명들은 조합, 튜플 및 매핑된 타입에 필요합니다. 일반적인 규약은 객체 모양에 대한 인터페이스와 다른 모든 것에 대한 타입 위명입니다.

일반적인 함정

  • 모든 것을 선택적으로 입력합니다. 안전하다고 느껴지지만 모든 곳에 null 체크를 강요하고 실제 계약 위반을 숨깁니다. API가 필드를 실제로 생략할 때만 필드를 선택적으로 만듭니다.
  • ** 단일 표본을 신뢰합니다.** 선택권을 최종 결정하기 전에 문서 또는 여러 응답을 확인하십시오.
  • 교통과 도메인 타입을 혼합합니다. JSON을 반영하는 원형 OrderDTO을 보관하고 실제 Date 객체와 계산된 필드를 가진 도메인 Order로 매핑합니다.
  • ** 페이징 래퍼에 대해 잊어 버립니다.** 많은 API는 { data: [...], nextCursor: "..." }에서 래퍼 리스트를 사용합니다. interface Page<T> { data: T[]; nextCursor: string | null }라는 일반적인 모델로 한 번 해보죠.

빠른 체크리스트

  1. 풍부한 실제 샘플을 채취하고 검증합니다.
  2. [JSON에서 TypeScript 변환기] (/tools/json) 로 인터페이스를 생성합니다.
  3. 도메인 언어로 타입 이름을 변경합니다.
  4. 선택적 대 무효 필드, 문자 조합 및 ID 유형을 수정합니다.
  5. 혼합조직을 차별화된 노동조합으로 대체해야 합니다.
  6. 외부 데이터에 대한 실행 시간 검증을 추가합니다.
  7. OpenAPI 또는 GraphQL 스키마가 존재할 때 스키마 기반 생성으로 전환합니다.

이러한 단계를 수행하는 데는 단 몇 분 정도가 걸리고 자동으로 완료되는 더 안전한 리팩터와 사용자가 도달하기 전에 잡힌 버그로 몇 배 더 지불됩니다.

이 페이지는 영어에서 자동 번역되었습니다. 오류를 발견하시면 알려 주세요.

관련 가이드