네, 10강에 오신 것을 환영합니다! 🎊 Part 2의 마지막 관문이자, 제네릭의 꽃이라고 할 수 있는 '실전 활용' 편입니다.

지난 시간에 함수에 <T>를 붙이는 걸 배웠죠? 오늘은 **인터페이스(Interface)**에 <T>를 붙여볼 겁니다. 이걸 배우면, React나 Next.js에서 **서버와 통신하는 코드(API)**를 짤 때 "와, 신세계다!"를 외치게 되실 겁니다.


🚀 제10강. 제네릭 실전 - 함수와 인터페이스에서의 활용

1. 제네릭 인터페이스: "마법의 상자 만들기"

인터페이스 이름 뒤에 <T>만 붙이면, **"내용물이 바뀔 수 있는 상자"**가 됩니다.

TypeScript
 
// <T>를 붙여서 '제네릭 인터페이스'로 변신!
interface Box<T> {
  value: T; // 이 value의 타입은 나중에 정해짐
}

// 1. 문자열 상자 만들기
const stringBox: Box<string> = { value: "선물" };

// 2. 숫자 상자 만들기
const numberBox: Box<number> = { value: 777 };

이렇게 설계도 하나(Box)로 여러 종류의 객체를 찍어낼 수 있습니다.

2. [실무 핵심] API 응답 데이터 처리하기 ⭐️⭐️⭐️

이 부분이 오늘 강의의 하이라이트입니다. 프론트엔드 개발자가 제네릭을 쓰는 가장 큰 이유가 바로 API 응답 타입 정의 때문입니다.

서버에서 데이터를 받아올 때 보통 이런 모양으로 옵니다.

  • 성공 여부 (status or code)
  • 메시지 (message)
  • 실제 데이터 (data) -> 이것만 매번 바뀜!

이걸 제네릭으로 한 방에 해결해 볼까요?

TypeScript
 
// 1. 공통 응답 형태 정의 (껍데기)
interface ApiResponse<T> {
  status: number;
  message: string;
  data: T; // 핵심! 여기만 매번 달라짐
}

// 2. 실제 데이터 타입들 정의 (알맹이)
interface User {
  name: string;
  age: number;
}

interface Product {
  id: number;
  price: number;
}

// 3. 실제 사용: 마치 레고 조립하듯이!
// 유저 정보를 가져왔을 때
const response1: ApiResponse<User> = {
  status: 200,
  message: "성공",
  data: { name: "김코딩", age: 30 } // User 타입이어야 함
};

// 상품 정보를 가져왔을 때
const response2: ApiResponse<Product> = {
  status: 200,
  message: "성공",
  data: { id: 1, price: 5000 } // Product 타입이어야 함
};

만약 제네릭이 없다면 UserResponse, ProductResponse... 이렇게 수십 개를 만들어야 했을 겁니다. 제네릭 덕분에 ApiResponse<T> 하나로 끝났죠? 아주 우아합니다. 😎

3. 제네릭 제약 조건 (Constraints): "아무거나 다 받진 않아!"

<T>는 기본적으로 모든 타입을 다 받지만, 가끔은 **"적어도 이건 지켜줘"**라고 제한(extends)을 걸고 싶을 때가 있습니다.

TypeScript
 
// <T extends { length: number }>
// 해석: T는 아무거나 다 되는데, 적어도 'length'(길이)라는 속성은 꼭 가지고 있어야 해!
function getLength<T extends { length: number }>(item: T): number {
  return item.length;
}

getLength("hello");   // OK (문자열은 length가 있음)
getLength([1, 2, 3]); // OK (배열도 length가 있음)
// getLength(100);    // 🚨 에러! (숫자는 length가 없음)

이렇게 하면 제네릭의 유연함을 유지하면서도 최소한의 안전장치를 걸 수 있습니다.


✍️ 10강 미니 퀴즈 & 실습

실무 코드를 봤으니 복습해 봅시다.

문제 1. (코드 완성) 다음은 블로그 게시글(Post)과 댓글(Comment)을 불러오는 API 타입을 정의하는 과정입니다. 빈칸을 채워주세요.

TypeScript
 
interface FetchResult<T> {
  data: T;
  loading: boolean;
}

interface Post { title: string; }
interface Comment { content: string; }

// 게시글 데이터를 담는 변수
const postResult: (   A   ) = {
  data: { title: "안녕하세요" },
  loading: false
};

(A)에 들어갈 코드는?

  1. FetchResult<Comment>
  2. FetchResult<Post>
  3. FetchResult<string>

문제 2. (응용) const box: Box<string> = { value: 100 }; 이 코드가 에러가 나는 이유는?


✅ 정답 및 해설

  • 문제 1 정답: 2번 (FetchResult<Post>)
    • 해설: data 안에 들어있는 내용이 { title: "안녕하세요" } 즉, Post 타입의 모양입니다. 그러니 제네릭 자리에 <Post>를 넣어줘야 짝이 맞습니다.
  • 문제 2 정답:
    • 해설: Box<string>이라고 선언했으면 value에는 반드시 문자열이 들어가야 합니다. 그런데 숫자 100을 넣었으니 타입 불일치 에러가 발생합니다.

고생 많으셨습니다! 👏👏👏 드디어 Part 2. 중급 기술 익히기가 모두 끝났습니다. 기본 타입부터 인터페이스, 그리고 제네릭까지! 이제 여러분은 타입스크립트의 문법적인 기초 공사를 탄탄하게 마쳤습니다.

이제 Part 3부터는 진짜 프로들의 영역, **"타입을 가지고 노는 고급 스킬"**로 넘어갑니다. 타입스크립트가 왜 똑똑하다고 하는지, 어떻게 하면 코드를 더 줄일 수 있는지 배우게 됩니다.

+ Recent posts