TypeScript 인터페이스 vs 타입 별칭¶
개요¶
객체의 모양을 정의하는 방법이 TypeScript에는 두 가지예요. interface로 선언할 수도 있고, type 별칭으로 이름을 붙일 수도 있죠. 캔버스 노드나 문서 블록처럼 도메인 구조를 코드 전체의 계약으로 고정할 때, 둘 중 어떤 걸 쓸지 매번 헤깔리기 쉬워요. 사실은 대부분 상황에서 둘이 비슷하고, 거의 대부분은 아무 거나 골라도 괜찮아요.
핵심 개념¶
interface와 type 별칭은 비슷해 보이지만 중요한 차이들이 몇 가지 있어요.
- 인터페이스는 확장 가능(declaration merging) —
interface는 같은 이름으로 다시 선언하면 병합돼요. 라이브러리의 타입을 쓸 때 기존 인터페이스를 추가로 확장하는 패턴이 가능하죠. 반면type별칭은 같은 이름을 다시 선언할 수 없어요. - type은 더 넓은 표현력 —
type은 유니온(A | B), 인터섹션(A & B), 튜플, 기존 타입에서 파생된 타입 등 객체 모양 외의 다양한 타입에 이름을 붙일 수 있어요.interface는 객체/클래스 모양에 초점이 맞춰져 있어요. - 확장 방식 —
interface는extends로,type은 인터섹션(&)으로 확장해요. 인터페이스는 클래스로implements할 수 있고,type으로 만든 객체 타입도 구조적 타입 시스템에서는 클래스로 구현 가능해요.
// interface: 병합 가능
interface Node { id: string; }
interface Node { label: string; } // OK, 병합됨
// type: 유니온처럼 객체 모양 밖의 타입도 표현
type Position = { x: number; y: number } | "center";
type NodeRef = Node & { ref: HTMLDivElement };
공식 핸드북의 실용 조언은 이래요. 대부분의 경우 경험에 맞지 않는 걸 골라도 되고, 일반적인 원칙은 객체의 모양을 정의하고 병합 등으로 확장할 가능성이 있으면 interface, 그것이 아니라면 type을 쓰는 거예요. 확장 가능성이 있는 프로젝트 구조를 설계할 땐 interface가, 유니온을 비롯한 넓은 타입 표현이 필요할 땐 type이 자연스러워요.
실제 적용(데이터스케쳐스 관점)¶
데이터스케쳐스에서는 객체 모양의 도메인 구조는 interface로, 그 외의 파생 타입은 type으로 쓰는 걸 기본 골격으로 삼아요. 캔버스 노드나 JSON Canvas 형식처럼 저장·렌더링 로직이 공유하는 데이터 구조는 명시적으로 정의하고, 같은 모양을 여러 곳에서 확장해야 할 때 interface의 병합·extends가 유리하거든요. 실제로는 React 컴포넌트 props도 객체 모양이라 interface로 정의하는 게 흔해요.
반면 "노드의 좌표는 {x,y}이거나 center다" 같은 유니온이나, "노드 타입에 DOM ref를 더한다" 같은 파생형은 type으로 잡아요. 이런 건 interface로 표현할 수 없으니 type 별칭이 정답이에요. 이렇게 기준을 하나로 고정해 두면, 팀에서 "이건 왜 interface지?" 같은 합의가 줄어들어요. 딱 하나 기억해 두면 돼요 — 같은 이름을 다시 선언해 확장해야 한다면 interface를 써야 한다는 것, 그리고 type은 그런 재선언이 불가능하다는 점이에요.
더 알아보기¶
- 공식 문서 (1차): TypeScript — Everyday Types (타입 별칭 vs 인터페이스 차이), TypeScript — Object Types
- 상위 개념: TypeScript
- 관련 챕터: 유틸리티 타입 · 타입 추론