← 블로그로 돌아가기

JSON을 TypeScript로 변환: 타입 안정성의 완벽 가이드

JSON 데이터에서 TypeScript 타입과 인터페이스를 자동 생성하는 모든 방법을 배워보세요. 도구, 기법, 모범 사례까지 완벽 정리.

Big JSON Team12분 소요tools
B

Big JSON Team

Technical Writer

Expert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.

12 분 읽기

# JSON을 TypeScript로 변환: 타입 안정성의 완벽 가이드

JSON 데이터에서 TypeScript 타입을 생성하면 타입 안정성과 자동 완성을 얻을 수 있습니다. 이 가이드에서 모든 방법을 배워보세요.

왜 JSON을 TypeScript로 변환하나요?

주요 이점

  • 타입 안정성: 컴파일 시 오류 발견
  • 자동 완성: IDE에서 속성 제안
  • 리팩토링: 안전한 코드 변경
  • 문서화: 타입이 곧 문서
  • 버그 감소: 런타임 오류 방지
  • 사용 사례

    • API 응답 타입 정의
    • 설정 파일 타입
    • 데이터베이스 스키마
    • 테스트 데이터
    • Mock 데이터

    수동 변환

    간단한 객체

    JSON:
    {
    

    "name": "홍길동",

    "age": 30,

    "email": "hong@example.com"

    }

    TypeScript 인터페이스:
    interface User {
    

    name: string;

    age: number;

    email: string;

    }

    TypeScript 타입:
    type User = {
    

    name: string;

    age: number;

    email: string;

    };

    중첩 객체

    JSON:
    {
    

    "user": {

    "name": "홍길동",

    "address": {

    "city": "서울",

    "zipCode": "12345"

    }

    }

    }

    TypeScript:
    interface Address {
    

    city: string;

    zipCode: string;

    }

    interface UserProfile {

    user: {

    name: string;

    address: Address;

    };

    }

    배열

    JSON:
    {
    

    "users": [

    { "name": "홍길동", "age": 30 },

    { "name": "김철수", "age": 25 }

    ]

    }

    TypeScript:
    interface User {
    

    name: string;

    age: number;

    }

    interface UserList {

    users: User[];

    }

    // 또는

    type UserList = {

    users: Array<{

    name: string;

    age: number;

    }>;

    };

    온라인 도구

    1. Quicktype

    quicktype.io 사용법:
  • JSON 붙여넣기
  • 언어로 "TypeScript" 선택
  • 옵션 설정
  • 생성된 코드 복사
  • 옵션:
    • Interface vs Type
    • Readonly 속성
    • Optional 속성
    • 네이밍 규칙

    예제: 입력 JSON:
    {
    

    "name": "홍길동",

    "age": 30,

    "hobbies": ["독서", "여행"]

    }

    출력 TypeScript:
    export interface User {
    

    name: string;

    age: number;

    hobbies: string[];

    }

    2. JSON to TypeScript

    transform.tools 기능:
    • 실시간 변환
    • 깔끔한 인터페이스
    • 간단한 옵션

    3. JSON Simplify

    JSON Simplify 기능:
    • JSON 검증
    • TypeScript 생성
    • 한국어 지원

    VS Code 확장

    Paste JSON as Code

    설치:
  • VS Code에서 Extensions
  • "Paste JSON as Code" 검색
  • 설치
  • 사용법:
  • JSON 복사
  • Cmd/Ctrl + Shift + P
  • "Paste JSON as Code" 실행
  • 언어로 TypeScript 선택
  • 예제:

    JSON을 복사하고 명령 실행하면:

    export interface Root {
    

    name: string;

    age: number;

    address: Address;

    }

    export interface Address {

    city: string;

    country: string;

    }

    JSON to TS

    설치:

    "JSON to TS" 확장 설치

    사용법:
  • JSON 선택
  • Cmd/Ctrl + Alt + V
  • 자동으로 TypeScript 생성
  • 명령줄 도구

    quicktype CLI

    설치:
    npm install -g quicktype
    사용법:
    # 파일에서 변환
    

    quicktype data.json -o types.ts

    # 여러 파일

    quicktype user.json product.json -o types.ts

    # 옵션

    quicktype data.json -o types.ts \

    --lang typescript \

    --just-types \

    --nice-property-names \

    --prefer-unions \

    --runtime-typecheck

    고급 옵션:
    # URL에서 가져오기
    

    quicktype https://api.example.com/users -o types.ts

    # JSON Schema에서

    quicktype schema.json -o types.ts

    # 여러 소스 합치기

    quicktype user.json product.json --src-lang json -o types.ts

    json2ts

    npm install -g json2ts
    # stdin에서
    

    cat data.json | json2ts

    # 파일에서

    json2ts < data.json > types.ts

    # 인터페이스 이름 지정

    json2ts --prefix I < data.json

    프로그래밍 방식

    quicktype 라이브러리

    npm install quicktype-core
    import {
    

    quicktype,

    InputData,

    jsonInputForTargetLanguage,

    JSONSchemaInput,

    FetchingJSONSchemaStore

    } from "quicktype-core";

    async function jsonToTypeScript(jsonString: string, typeName: string) {

    const jsonInput = jsonInputForTargetLanguage("typescript");

    await jsonInput.addSource({

    name: typeName,

    samples: [jsonString]

    });

    const inputData = new InputData();

    inputData.addInput(jsonInput);

    const result = await quicktype({

    inputData,

    lang: "typescript",

    rendererOptions: {

    "just-types": "true",

    "nice-property-names": "true",

    "prefer-unions": "true"

    }

    });

    return result.lines.join("\n");

    }

    // 사용

    const json = JSON.stringify({

    name: "홍길동",

    age: 30

    });

    jsonToTypeScript(json, "User").then(ts => {

    console.log(ts);

    });

    json-schema-to-typescript

    npm install json-schema-to-typescript
    import { compile } from 'json-schema-to-typescript';
    
    

    const schema = {

    type: 'object',

    properties: {

    name: { type: 'string' },

    age: { type: 'integer', minimum: 0 }

    },

    required: ['name']

    };

    compile(schema, 'User')

    .then(ts => console.log(ts))

    .catch(err => console.error(err));

    고급 기능

    Optional 속성

    일부 JSON에만 있는 속성:

    {
    

    "name": "홍길동",

    "age": 30,

    "email": "hong@example.com"

    }

    {
    

    "name": "김철수",

    "age": 25

    }

    TypeScript:
    interface User {
    

    name: string;

    age: number;

    email?: string; // Optional

    }

    Union 타입

    다른 타입이 올 수 있는 경우:

    [
    

    { "type": "admin", "permissions": ["all"] },

    { "type": "user", "limits": 100 }

    ]

    TypeScript:
    type Admin = {
    

    type: "admin";

    permissions: string[];

    };

    type RegularUser = {

    type: "user";

    limits: number;

    };

    type User = Admin | RegularUser;

    Enum

    제한된 값:

    {
    

    "status": "active",

    "role": "admin"

    }

    TypeScript:
    enum Status {
    

    Active = "active",

    Inactive = "inactive",

    Pending = "pending"

    }

    enum Role {

    Admin = "admin",

    User = "user",

    Guest = "guest"

    }

    interface User {

    status: Status;

    role: Role;

    }

    // 또는 리터럴 타입

    type Status = "active" | "inactive" | "pending";

    type Role = "admin" | "user" | "guest";

    Generics

    재사용 가능한 타입:

    {
    

    "data": [

    { "id": 1, "name": "홍길동" },

    { "id": 2, "name": "김철수" }

    ],

    "total": 2,

    "page": 1

    }

    TypeScript:
    interface Pagination<T> {
    

    data: T[];

    total: number;

    page: number;

    }

    interface User {

    id: number;

    name: string;

    }

    type UserList = Pagination<User>;

    Readonly

    불변 속성:

    interface User {
    

    readonly id: number;

    name: string;

    readonly createdAt: string;

    }

    // 전체 readonly

    type ReadonlyUser = Readonly<User>;

    // 배열도 readonly

    interface UserList {

    readonly users: readonly User[];

    }

    API 응답 타입

    실용 예제

    API 응답:
    {
    

    "status": "success",

    "data": {

    "user": {

    "id": 1,

    "name": "홍길동",

    "email": "hong@example.com",

    "profile": {

    "avatar": "https://example.com/avatar.jpg",

    "bio": "안녕하세요"

    },

    "posts": [

    {

    "id": 101,

    "title": "첫 게시물",

    "createdAt": "2026-01-16T10:00:00Z"

    }

    ]

    }

    },

    "meta": {

    "timestamp": 1642348800

    }

    }

    TypeScript:
    interface Post {
    

    id: number;

    title: string;

    createdAt: string;

    }

    interface Profile {

    avatar: string;

    bio: string;

    }

    interface User {

    id: number;

    name: string;

    email: string;

    profile: Profile;

    posts: Post[];

    }

    interface ApiResponse<T> {

    status: "success" | "error";

    data: T;

    meta: {

    timestamp: number;

    };

    }

    type UserResponse = ApiResponse<{ user: User }>;

    // 사용

    async function getUser(id: number): Promise<UserResponse> {

    const response = await fetch(/api/users/${id});

    return response.json();

    }

    오류 응답

    interface ErrorResponse {
    

    status: "error";

    error: {

    code: string;

    message: string;

    details?: unknown;

    };

    meta: {

    timestamp: number;

    };

    }

    type ApiResult<T> = ApiResponse<T> | ErrorResponse;

    // 타입 가드

    function isErrorResponse(

    response: ApiResult<unknown>

    ): response is ErrorResponse {

    return response.status === "error";

    }

    // 사용

    const result = await getUser(1);

    if (isErrorResponse(result)) {

    console.error(result.error.message);

    } else {

    console.log(result.data.user.name);

    }

    타입 검증

    Zod

    런타임 타입 검증:

    npm install zod
    import { z } from 'zod';
    
    

    // 스키마 정의

    const UserSchema = z.object({

    name: z.string(),

    age: z.number().int().positive(),

    email: z.string().email(),

    hobbies: z.array(z.string()).optional()

    });

    // 타입 추론

    type User = z.infer<typeof UserSchema>;

    // 검증

    const data = JSON.parse(jsonString);

    const result = UserSchema.safeParse(data);

    if (result.success) {

    const user: User = result.data;

    console.log(user.name);

    } else {

    console.error(result.error);

    }

    io-ts

    npm install io-ts fp-ts
    import  as t from 'io-ts';
    

    import { isRight } from 'fp-ts/Either';

    const UserCodec = t.type({

    name: t.string,

    age: t.number,

    email: t.string

    });

    type User = t.TypeOf<typeof UserCodec>;

    const result = UserCodec.decode(jsonData);

    if (isRight(result)) {

    const user: User = result.right;

    console.log(user.name);

    } else {

    console.error(result.left);

    }

    모범 사례

    1. 명확한 네이밍

    // 좋음
    

    interface UserProfile {

    name: string;

    email: string;

    }

    interface ApiResponse<T> {

    data: T;

    status: string;

    }

    // 나쁨

    interface Data {

    a: string;

    b: string;

    }

    2. 타입 재사용

    // 기본 타입
    

    interface User {

    id: number;

    name: string;

    email: string;

    }

    // 확장

    interface UserWithPosts extends User {

    posts: Post[];

    }

    // Partial (모든 속성 optional)

    type PartialUser = Partial<User>;

    // Pick (일부만 선택)

    type UserPreview = Pick<User, "id" | "name">;

    // Omit (일부 제외)

    type UserWithoutId = Omit<User, "id">;

    3. 주석 추가

    /
    

    사용자 정보

    /

    interface User {

    / 고유 ID /

    id: number;

    /* 사용자 이름 /

    name: string;

    /* 이메일 주소 /

    email: string;

    /*

    생성 날짜

    @format date-time

    /

    createdAt: string;

    }

    4. 타입 vs 인터페이스

    인터페이스 사용 (객체):
    interface User {
    

    name: string;

    age: number;

    }

    // 확장 가능

    interface Admin extends User {

    permissions: string[];

    }

    타입 사용 (유니온, 유틸리티):
    type Status = "active" | "inactive";
    

    type ID = string | number;

    type ReadonlyUser = Readonly<User>;

    5. 엄격한 타입

    // 좋음
    

    interface Config {

    apiUrl: string;

    timeout: number;

    retries: number;

    }

    // 나쁨 (any 사용)

    interface Config {

    apiUrl: any;

    timeout: any;

    }

    자동화

    Pre-commit Hook

    #!/bin/bash
    

    # .git/hooks/pre-commit

    # JSON 파일에서 TypeScript 생성

    for file in schemas/.json; do

    filename=$(basename "$file" .json)

    quicktype "$file" -o "types/${filename}.ts"

    git add "types/${filename}.ts"

    done

    npm 스크립트

    {
    

    "scripts": {

    "generate-types": "quicktype schemas/.json -o src/types/generated.ts",

    "prebuild": "npm run generate-types"

    }

    }

    GitHub Actions

    name: Generate Types
    

    on:

    push:

    paths:

    - 'schemas/*/.json'

    jobs:

    generate:

    runs-on: ubuntu-latest

    steps:

    - uses: actions/checkout@v2

    - name: Setup Node

    uses: actions/setup-node@v2

    - name: Install quicktype

    run: npm install -g quicktype

    - name: Generate types

    run: quicktype schemas/*.json -o types/generated.ts

    - name: Commit

    run: |

    git config user.name "GitHub Actions"

    git config user.email "actions@github.com"

    git add types/generated.ts

    git commit -m "Update generated types" || exit 0

    git push

    결론

    JSON을 TypeScript로 변환하면 타입 안정성과 개발자 경험이 크게 향상됩니다. 온라인 도구로 빠르게 시작하고, CLI 도구로 자동화하세요.

    핵심 요약:
    • ✅ 온라인 도구로 빠른 변환
    • ✅ VS Code 확장으로 편리하게
    • ✅ CLI로 자동화
    • ✅ 런타임 검증 추가
    • ✅ 명확한 네이밍과 주석

    지금 바로 JSON Simplify에서 TypeScript 타입을 생성해보세요!

    Share:

    관련 글

    Read in English