본문 바로가기
language/typescript

🧱 객체 타입 선언 – interface vs type 완전 비교

by 죄니안죄니 2025. 4. 27.
📚 타입스크립트 입문 시리즈
🟢 ① tsconfig.json 완전 정복 | 🟢 ② 개발 환경 세팅 | 🟢 ③ 기본 타입 정복 | 🔵 ④ 객체 타입 선언 (interface vs type)

🧱 객체 타입 선언 – interface vs type 완전 비교

TypeScript에서 객체 타입을 선언할 수 있는 방법은 대표적으로 두 가지가 있습니다: interfacetype.
두 문법 모두 유사하지만, 쓰임새와 확장성에서 약간의 차이가 있습니다. 이 글에서는 차이점과 실제 사용 사례를 통해 어떤 상황에서 무엇을 써야 하는지 깔끔하게 정리해드립니다.


🧩 기본 문법 비교

우리가 다룰 데이터가 아래와 같은 생겼다고 한다면, 이 데이터 구조를 정의하는 방법이 2가지가 있습니다.

{
  name: "홍길동",
  age: 30
}

✅ 1. interface를 사용하는 방법

interface User {
  name: string;
  age: number;
}

✅ 2. type을 사용하는 방법

type User = {
  name: string;
  age: number;
};

// 타입을 새로 만드는 것(정의). 이후 변수, 매개변수에서 재사용

// 사용할 땐 아래 처럼 사용(변수: 타입명)
const user: User = {...

기본적인 객체 선언에서는 거의 차이가 없습니다. 생김새와 타입체크도 동일하게 합니다.


🔄 확장(extends)과 합성

✔ interface는 확장에 강하다 : 객체 구조만 정의하고 싶고 확장하고 싶다. 클래스 설계하듯, 명세정의

 

  • 확장해서 쓰기 편함 (부모-자식 구조처럼)
  • 클래스랑 같이 쓰기 좋아요
  • 다른 파일에서 선언한 걸 병합(합치기) 가능

 

interface Animal {
  name: string;
}
interface Dog extends Animal {
  breed: string;
}

interface는 여러 개를 중첩해서 선언 가능합니다. 아래처럼 기존 선언을 확장하는 것도 가능합니다:

interface Dog {
  bark(): void;
}

✔ type은 확장보다 조합에 강하다 : 여러 타입을 조합하거나 함수/리터럴 표현 등 다양하게 쓰고 싶다

  • 여러 타입을 조합할 수 있어요 (&, |)
  • 터럴 타입 선언
type Status = 'loading' | 'success' | 'error';  // 유니언, 리터럴 조합
type Response = { data: string } & { status: Status }; // 인터섹션

// interface로는 이런 표현이 불가능함!

 

  • 문자열 리터럴, 함수 타입 등도 표현 가능(간결)
type Add = (a: number, b: number) => number;

const add: Add = (a, b) => a + b;

// interface로도 가능하지만 문법이 좀 더 복잡해요:
interface Add {
  (a: number, b: number): number;
}
  • 객체 외에도 배열, 유니언, 튜플 다 표현 가능
type Point = [number, number]; // x, y 좌표

const pos: Point = [10, 20];
//interface는 튜플 선언 자체를 지원하지 않습니다.
  • 복잡한 타입 연산이 필요한 경우
type A = { id: number; name: string };
type B = Omit<A, 'id'>;  // name만 남김

type C = A & { createdAt: string };
// type은 Pick, Omit, Partial 등 유틸리티 타입과 조합해서 정교한 타입 구성이 가능합니다.
// & 연산자를 사용해 유니언/인터섹션 타입과 함께 조합 가능. 타입 연산에 유리합니다.

 

 


📐 유연성 & 제약 비교

구분 interface type
객체 타입 선언
확장 (상속 extends) ⭕ (다중 선언으로 합침 가능) 🔺 type은 & | 연산자로 조합 새타입생성. 상속은 안 됨
Union / Intersection
제네릭 사용
리터럴 타입 선언 ⭕ (예: type Role = 'admin' | 'user')

💼 실무에서는 언제 뭘 써야 할까?

💡 interface 추천 상황

  • 클래스와 함께 사용할 객체 타입 선언
  • 여러 사람이 같은 타입을 확장해서 사용해야 하는 경우
  • 확장성과 명세 중심 설계에 적합

💡 type 추천 상황

  • 복잡한 조합(union, intersection 등)이 필요한 경우
  • 함수 타입, 튜플, 유니언 타입 등 비객체 구조 선언
  • 한번 정의하고 더 이상 확장하지 않을 타입 선언

🎯 정리

  • interface명세를 정의하는 느낌 – 확장, 통합에 강함
  • type유형을 표현하는 느낌 – 유니언, 연산에 강함
  • 혼용 가능하지만 팀 내 컨벤션 통일 권장

📌 보충 설명: JavaScript에는 type 키워드가 없다?

많은 분들이 궁금해하시는 부분인데, type은 오직 TypeScript에서만 존재하는 키워드입니다.

JavaScript 자체에는 type이라는 키워드가 존재하지 않으며, JS 코드에서 "type"이란 단어가 쓰이는 유일한 곳은 typeof 연산자입니다.

✅ JavaScript에서의 타입 관련 연산자

  • typeof 변수: 런타임 시 변수의 타입을 문자열로 반환
  • instanceof: 어떤 객체가 특정 클래스(생성자 함수)의 인스턴스인지 확인
typeof 'hello'      // 'string'
typeof 42           // 'number'
typeof undefined    // 'undefined'
typeof null         // 'object'
typeof []           // 'object'
typeof function(){} // 'function'

new Date() instanceof Date // true

✅ TypeScript에서의 type

TypeScript의 type 키워드는 타입 별칭(Type Alias)을 선언하는 키워드입니다. 런타임엔 존재하지 않고, 컴파일 시 타입 체크에만 쓰인 뒤 사라집니다.

// TypeScript
type ID = string;
const userId: ID = 'abc123';

➡️ 컴파일된 JavaScript 코드에서는 type ID = string;은 사라지고 const userId만 남습니다.

📌 정리

  • JavaScript에는 type 키워드가 존재하지 않습니다.
  • typeTypeScript의 전용 문법으로, 타입 체크를 위한 "설명서"일 뿐 실행 시에는 사라집니다.
  • JS에서 타입 체크는 typeof, instanceof로 해야 합니다.

 


📘 다음 글 예고

👉 함수의 타입 선언 (매개변수, 반환, 옵셔널 등) 에서 함수 중심 타입 선언 패턴을 알아봅니다!

 

댓글