본문으로 건너뛰기
프론트엔드 기초집LESSON 16

인터페이스와 API 응답 타입

난이도초급
예상 시간35분
선수지식이전 강의

16강. 인터페이스와 API 응답 타입

1. 이번 강의에서 해결할 문제

response.json() 결과에 Game[] 타입을 붙이기만 하면 서버가 잘못된 데이터를 보내도 런타임에서는 막지 못합니다. 외부 데이터 경계를 안전하게 다룹니다.

2. 학습 목표

  • interface로 공유 객체 형태를 정의한다.
  • API 응답 래퍼와 UI 모델을 구분한다.
  • unknown 응답을 타입 가드로 검사한다.

3. 핵심 개념

interfacetype 모두 객체 형태를 표현할 수 있습니다. 이 과정에서는 확장될 공유 객체는 interface, 유니온과 별칭은 type을 사용합니다. 중요한 것은 팀 안에서 일관된 기준입니다.

TypeScript 타입은 실행 시 사라집니다. 외부 JSON은 unknown으로 받아 필요한 속성을 검사한 뒤 사용해야 합니다. 실제 서비스에서는 스키마 검증 도구를 고려할 수 있지만, 여기서는 라이브러리 없이 경계의 원리를 익힙니다.

4. 단계별 코드 예시

파일 경로: game-release-dashboard/src/types/game.ts

export interface Game {
id: string;
title: string;
platform: 'PC' | 'Console' | 'Mobile';
releaseDate: string;
score: number;
}

export interface GamesResponse {
games: Game[];
updatedAt: string;
}

파일 경로: game-release-dashboard/src/api/games.ts

import type { Game, GamesResponse } from '../types/game';

function isGame(value: unknown): value is Game {
if (typeof value !== 'object' || value === null) return false;
const item = value as Record<string, unknown>;
return (
typeof item.id === 'string' &&
typeof item.title === 'string' &&
typeof item.releaseDate === 'string' &&
typeof item.score === 'number' &&
['PC', 'Console', 'Mobile'].includes(String(item.platform))
);
}

export async function fetchGames(signal?: AbortSignal): Promise<Game[]> {
const response = await fetch(
import.meta.env.BASE_URL + 'data/games.json',
{ signal },
);
if (!response.ok) throw new Error('HTTP ' + response.status);

const body: unknown = await response.json();
if (
typeof body !== 'object' ||
body === null ||
!Array.isArray((body as GamesResponse).games) ||
!(body as GamesResponse).games.every(isGame)
) {
throw new Error('게임 데이터 형식이 올바르지 않습니다.');
}
return (body as GamesResponse).games;
}

JSON도 { "games": [...], "updatedAt": "2026-07-29" } 형태로 감쌉니다.

5. 코드가 동작하는 이유

응답은 처음에 unknown이므로 검사 없이는 속성에 접근할 수 없습니다. isGame의 반환 타입 value is Game은 true 분기에서 TypeScript가 값을 Game으로 좁히게 합니다. fetchGames는 검증된 배열만 반환하므로 컴포넌트는 HTTP 세부 사항을 몰라도 됩니다.

6. 자주 하는 실수와 해결법

  • await response.json() as Game[]로 끝냄: 단언은 런타임 데이터를 검사하지 않습니다.
  • API 타입을 컴포넌트마다 중복: types 폴더에 공유 계약을 둡니다.
  • 날짜를 곧바로 Date라고 선언: JSON 날짜는 문자열입니다. 파싱 시점에 유효성을 확인합니다.
  • 검증 함수가 일부 필드만 확인: 화면에서 실제 사용하는 필드는 모두 검사합니다.

7. 직접 실습

GamesResponse의 updatedAt을 검사하고 화면에 “데이터 갱신일”로 표시하세요. score를 문자열로 바꾼 잘못된 JSON에서 사용자 오류 상태가 나타나는지 확인하세요.

8. 이해 점검 질문 3개

  1. TypeScript 타입만으로 외부 JSON을 보장할 수 없는 이유는 무엇인가요?
  2. 타입 가드의 value is Game 반환 타입은 어떤 역할을 하나요?
  3. API 요청 함수를 컴포넌트 밖으로 분리하면 무엇이 좋아지나요?

9. 핵심 요약

API 응답은 신뢰 경계입니다. 공유 인터페이스로 계약을 문서화하고 unknown 값을 런타임에서 검사한 뒤 UI에 전달합니다.

MINI QUIZ

인터페이스와 API 응답 타입 미니 퀴즈

선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.

0 / 2
  1. 문제 1“인터페이스와 API 응답 타입” 작업 전 검토에서 채택해야 할 안전 기준은 무엇인가요?
  2. 문제 2‘await response.json() as Game[]로 끝냄’ 실수를 판단할 때 “인터페이스와 API 응답 타입” 강의가 제시한 기준은 무엇인가요?
LESSON STATUS

학습을 마쳤나요?

직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.

16강. 인터페이스와 API 응답 타입 미완료 상태