JSON을 TypeScript로 변환: 타입 안정성의 완벽 가이드
JSON 데이터에서 TypeScript 타입과 인터페이스를 자동 생성하는 모든 방법을 배워보세요. 도구, 기법, 모범 사례까지 완벽 정리.
Big JSON Team
• Technical WriterExpert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.
# JSON을 TypeScript로 변환: 타입 안정성의 완벽 가이드
JSON 데이터에서 TypeScript 타입을 생성하면 타입 안정성과 자동 완성을 얻을 수 있습니다. 이 가이드에서 모든 방법을 배워보세요.
왜 JSON을 TypeScript로 변환하나요?
주요 이점
사용 사례
- 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 사용법:- Interface vs Type
- Readonly 속성
- Optional 속성
- 네이밍 규칙
{
"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
설치:JSON을 복사하고 명령 실행하면:
export interface Root {
name: string;
age: number;
address: Address;
}
export interface Address {
city: string;
country: string;
}
JSON to TS
설치:"JSON to TS" 확장 설치
사용법:명령줄 도구
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 타입을 생성해보세요!
관련 글
온라인 JSON 도구: 2026년 최고의 무료 도구 TOP 15
JSON 작업을 위한 최고의 온라인 도구를 발견하세요. 포맷터, 검증기, 에디터, 변환기 등 - 모든 무료 도구를 한 곳에서 비교합니다.
JavaScript와 JSON: 완벽한 가이드 2026
JavaScript에서 JSON을 마스터하세요. JSON.parse(), JSON.stringify(), 오류 처리, fetch API 및 모범 사례에 대한 완벽한 가이드입니다.
JSON Schema 이해하기: 완벽한 가이드 2026
JSON Schema로 데이터를 검증하고 문서화하는 방법을 배우세요. 기본부터 고급 패턴까지 다루는 종합 가이드입니다.