← Back to list

TypeScript 설계: Interface vs Type Alias & Generics

Interface vs Type의 구분 기준과 Generics를 활용한 API 설계 패턴을 작성해보았습니다.

DevOZ · 2026-01-23 07:08 · 0 claps · 5.5 min read
#typescript #interfaces #generics #typealias
Open on Medium ↗
Wiki topics: 🌐 · Web Development

TypeScript 설계: Interface vs Type Alias & Generics

이번 글에서는 협업하기 좋은 코드를 만드는 두 가지 핵심 무기, Interface vs Type의 구분 기준과 Generics를 활용한 API 설계 패턴에 대해 작성해보겠습니다.

Interface vs Type Alias

“객체 타입을 정의할 때 interface를 써야 해요, type을 써야 해요?” 이 질문에 대한 답은 명확합니다. 목적에 따라 다릅니다.

Interface

Interface는 ‘객체의 모양’을 정의하는 데 특화되어 있습니다. 가장 큰 특징은 선언 병합(Declaration Merging)이 가능하다는 점입니다. 똑같은 이름으로 Interface를 두 번 선언하면, 자동으로 하나로 합쳐집니다.

// 라이브러리 개발자나 확장성 높은 설계를 할 때 유리
interface User {
  name: string;
}

// 나중에 누군가 같은 이름으로 기능을 추가함 (오류 아님!)
interface User {
  age: number;
}
// 결과: User는 name과 age를 모두 가짐 (자동 병합)
const kim: User = { name: 'Kim', age: 30 };
┌────────────────┐      ┌────────────────┐
│ interface User │      │ interface User │
│  name: string  │      │  age: number   │
└───────┬────────┘      └───────┬────────┘
        │                       │
        └───────────┬───────────┘
                    ▼
            최종 User Interface
        ┌───────────────────────┐
        │  name: string         │
        │  age: number          │
        └───────────────────────┘

따라서 확장이 열려 있어야 하는 모델(Model) 정의나 객체 지향적인 상속(extends)이 필요할 때는 Interface가 유리합니다.

Type Alias

Type은 새로운 이름을 붙이는 것입니다. Interface가 할 수 없는 유니온(Union, OR 연산)이나 튜플, 원시 값에 이름을 붙일 때 강력합니다.

// 1. 유니온 타입 (Interface로는 불가능)
type Status = 'SUCCESS' | 'ERROR' | 'LOADING';

// 2. 복잡한 타입 조합 (Intersection)
type UserInfo = { name: string };
type UserAuth = { token: string };

// 두 타입을 합쳐서 새로운 타입을 만듦 (& 연산자)
type Admin = UserInfo & UserAuth;

Type은 선언 병합이 불가능합니다. 따라서 데이터의 값 자체를 한정하거나, 유틸리티 타입으로 데이터를 가공할 때 주로 사용합니다.

설계 원칙

  • Interface: 객체 모델 정의 (확장성, 상속이 필요한 경우)
  • Type Alias: 단순 데이터, Union, 튜플, 함수 타입 (엄격한 정의가 필요한 경우)

Generics

함수가 데이터를 인자로 받아 유연하게 동작하듯, Generics는 타입을 인자로 받아 유연하게 재사용하게 해줍니다. 특히 서버와 통신할 때 API 응답 타입을 표준화하는 데 필수적입니다.

흔한 비유보다는 실무적인 관점에서 보자면, Generics는 데이터를 담는 규격화된 봉투(Envelope) 역할을 합니다.

서버에서 내려주는 응답 구조가 보통 이렇다고 가정해봅시다.

{
  "code": 200,
  "message": "성공",
  "data": { ...실제 데이터... }
}

Generics를 쓰지 않으면 UserResponse, ProductResponse 등을 일일이 다 만들어야 하며, 이는 엄청난 중복입니다.

이러한 문제를 해결하려면 ApiResponse<T>로 표준화하면 됩니다. T(Type)라는 자리를 비워두고, 실제 데이터가 들어올 때 타입을 주입하는 방식입니다.

// 1. 공통 껍데기(Envelope) 만들기
interface ApiResponse<T> {
  code: number;
  message: string;
  data: T; // 여기가 핵심! T에 실제 데이터 타입이 주입됨
}

// 2. 실제 데이터 모델 정의
interface User {
  id: number;
  name: string;
}

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

// 3. 조립해서 사용 (재사용성 200%)
// T 자리에 User를 주입 -> data는 User 타입이 됨
const userRes: ApiResponse<User> = {
  code: 200, 
  message: 'OK',
  data: { id: 1, name: 'Kim' }
};

// T 자리에 Product를 주입 -> data는 Product 타입이 됨
const productRes: ApiResponse<Product> = {
  code: 200, 
  message: 'OK',
  data: { id: 1, price: 50000 }
};

console.log(userRes.data.name);     // 자동 완성 지원
console.log(productRes.data.price); // 자동 완성 지원
1. 봉투 준비 (ApiResponse<T>)
   ┌───────────────────────────────┐
   │ RESPONSE ENVELOPE             │
   │ - code: 200                   │
   │ - message: "OK"               │
   │ - data: [     T     ] ◀── (구멍 뚫린 공간)
   └───────────────────────────────┘

2. 내용물 주입 (Type Injection)
   만약 <User>를 넣으면?        만약 <Product>를 넣으면?
   ┌──────────────────┐        ┌─────────────────────┐
   │ ...              │        │ ...                 │
   │data: [ User 객체 ]│        │data: [ Product 객체 ]│
   └──────────────────┘        └─────────────────────┘
   (타입이 딱 맞게 들어감)         (자동 완성 & 검사 가능)

만약 Generics가 없었다면 data: any를 썼을 것이고, 그랬다면 자동 완성도 안 되고 타입 안전성도 사라졌을 것입니다.

마치며

TypeScript 설계의 핵심은 ‘유연함’과 ‘엄격함’의 조화입니다.

  1. Interface를 사용해 객체의 뼈대를 잡고 확장 가능성을 열어야합니다.
  2. Type Alias를 사용해 구체적인 값의 범위(Union)나 조합을 엄격하게 정의해야합니다.
  3. Generics를 사용해 중복 코드를 없애고, 어떤 데이터가 들어오든 유연하게 받아주는 표준화된 틀을 만들어야합니다.

메타데이터
post_id
371da0c3349a
slug
typescript-설계-interface-vs-type-alias-generics-371da0c3349a
url
https://medium.com/@DevOZ/typescript-%EC%84%A4%EA%B3%84-interface-vs-type-alias-generics-371da0c3349a
canonical_url
https://medium.com/@DevOZ/typescript-%EC%84%A4%EA%B3%84-interface-vs-type-alias-generics-371da0c3349a
author_url
https://medium.com/@DevOZ
status
ok
fetched_at
2026-06-22 00:13:37