TypeScript interface vs type 차이: 언제 무엇을 쓸까
TypeScript interface vs type, 무엇이 다를까?
TypeScript interface vs type 차이는 입문자가 가장 자주 묻는 질문입니다. 결론부터 말하면 객체 형태를 정의할 때는 둘 다 거의 같게 동작하지만, 확장 방식·선언 병합·표현할 수 있는 범위에서 차이가 있습니다. interface는 객체의 구조를 정의하는 데 특화되어 있고, type(타입 별칭)은 객체뿐 아니라 유니온, 튜플, 원시 타입 등 더 넓은 표현을 할 수 있습니다.
// interface
interface User {
name: string;
age: number;
}
// type 별칭 (같은 객체 형태)
type UserType = {
name: string;
age: number;
};확장(extends) 방식의 차이
둘 다 확장할 수 있지만 문법이 다릅니다. interface는 extends, type은 교차 타입(&)을 사용합니다.
// interface 확장
interface Animal { name: string; }
interface Dog extends Animal { breed: string; }
// type 확장 (교차 타입)
type AnimalT = { name: string };
type DogT = AnimalT & { breed: string };type만 할 수 있는 것: 유니온·튜플·원시 별칭
type은 객체가 아닌 형태도 표현할 수 있습니다. 이 부분은 interface로 불가능합니다.
// 유니온 타입
type Status = 'loading' | 'success' | 'error';
// 튜플
type Point = [number, number];
// 원시 타입 별칭
type ID = string | number;
// 함수 타입
type Handler = (e: Event) => void;interface만 할 수 있는 것: 선언 병합
같은 이름의 interface를 여러 번 선언하면 자동으로 합쳐집니다(declaration merging). 라이브러리 타입을 확장할 때 유용합니다. type은 같은 이름을 중복 선언하면 오류가 납니다.
interface Box { width: number; }
interface Box { height: number; }
// 결과: Box는 width와 height를 모두 가짐
const b: Box = { width: 10, height: 20 };
// type ID = string;
// type ID = number; // 오류: 식별자 'ID' 중복interface vs type 비교 표
| 기능 | interface | type |
|---|---|---|
| 객체 형태 정의 | 가능 | 가능 |
| 확장 | extends | & (교차 타입) |
| 유니온 타입 | 불가능 | 가능 |
| 튜플 / 원시 별칭 | 불가능 | 가능 |
| 선언 병합 | 가능 | 불가능 |
| computed/매핑 타입 | 제한적 | 유연함 |
실전: 어떤 것을 선택할까?
- 객체나 클래스의 형태(shape)를 정의한다면
interface를 기본으로 쓰는 것이 무난합니다(확장과 선언 병합이 자연스러움). - 유니온, 튜플, 함수 시그니처, 조건부/매핑 타입 등 복잡한 타입 조합이 필요하면
type을 씁니다. - 팀에 정해진 규칙이 있다면 그 컨벤션을 따르세요. 일관성이 가장 중요합니다.
실전 예제: 함수, 인덱스 시그니처, 제네릭
두 문법 모두 객체 형태 외에 함수나 동적 키를 표현할 수 있습니다. 문법이 조금 다를 뿐입니다.
// 함수 타입: interface
interface Adder {
(a: number, b: number): number;
}
// 함수 타입: type (더 간결)
type AdderT = (a: number, b: number) => number;
// 인덱스 시그니처 (동적 키)
interface StringMap {
[key: string]: string;
}
type StringMapT = { [key: string]: string };
// 제네릭도 둘 다 지원
interface Box<T> { value: T; }
type BoxT<T> = { value: T };
const b1: Box<number> = { value: 1 };
const b2: BoxT<string> = { value: 'hi' };유니온과의 조합은 type이 유리
API 응답처럼 "성공 또는 실패" 형태를 표현할 때는 type의 유니온이 자연스럽습니다. 이런 판별 유니온(discriminated union)은 interface만으로는 직접 만들 수 없습니다.
type ApiResult =
| { status: 'success'; data: string }
| { status: 'error'; message: string };
function handle(res: ApiResult) {
if (res.status === 'success') {
console.log(res.data); // 타입이 좁혀짐
} else {
console.log(res.message);
}
}흔한 실수
- type으로 객체를 확장하며 extends 사용: type은
extends가 아니라&로 합칩니다. - 같은 이름의 type 중복 선언: 병합되지 않고 "중복 식별자" 오류가 납니다. interface와 헷갈리지 마세요.
- 유니온을 interface로 표현하려는 시도: 불가능합니다. 유니온은 반드시 type을 사용하세요.
자주 묻는 질문
Q1. 둘 중 무엇을 기본으로 쓰는 게 좋나요?
공식 핸드북은 "객체 형태에는 interface를 먼저 고려하고, interface로 표현이 안 될 때 type을 쓰라"고 권합니다. 다만 실무에서는 팀 컨벤션 일관성이 더 중요합니다.
Q2. 성능 차이가 있나요?
대규모 프로젝트에서 interface가 컴파일 시 캐싱에 유리한 경우가 있지만, 일반적인 규모에서는 체감 차이가 없습니다.
Q3. React 컴포넌트 props에는 무엇을 쓰나요?
둘 다 가능합니다. 단순 객체 형태라면 interface, 유니온이 섞인 props라면 type이 편합니다. 핵심은 프로젝트 전체에서 한 가지 스타일을 일관되게 유지하는 것입니다.