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

인터페이스와 API 응답 타입

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

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

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

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

2. 학습 목표​

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

3. 핵심 개념​

interface와 type 모두 객체 형태를 표현할 수 있습니다. 이 과정에서는 확장될 공유 객체는 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 응답 타입 미완료 상태