-
TypeScript interface vs type 비교 1편JS & TS 2025. 3. 16. 19:00728x90반응형
TypeScript에서는 interface와 type을 사용해 타입을 정의할 수 있습니다.
이 둘은 비슷한 목적을 가지고 있지만 미묘한 차이가 있으며, 상황에 따라 더 적합한 선택이 있습니다.
interface와 type의 기본적인 차이점
정의 방식과 표현 범위
interface는 객체 형태(shape)를 정의하는 데 주로 사용되며, 선언 시 interface InterfaceName { ... } 형태를 사용합니다.
한편, type은 타입 별칭을 만드는 키워드로 type AliasName = ... 형태로 정의합니다.- 프리미티브와 복합 타입: type은 문자열, 숫자 등의 원시 타입에도 별칭을 붙일 수 있지만, interface는 객체 형태에만 사용할 수 있습니다. 예를 들어 type MyString = string;은 가능하지만 interface MyString extends string {}처럼 원시 타입 자체를 interface로 표현할 수는 없습니다.
- 유니온(Union)과 인터섹션(Intersection): 유니온 타입(A | B)은 type으로만 정의할 수 있습니다. interface는 이러한 합집합 타입을 직접 표현하지 못합니다. 반면 인터섹션 타입(A & B)은 type에서 주로 사용하지만, interface도 extends를 통해 비슷한 효과를 낼 수 있습니다 (여러 인터페이스를 상속하면 결과적으로 속성이 합쳐짐).
- 함수, 튜플 등의 표현: 함수 타입이나 튜플(tuple) 타입도 type으로 표현하는 편이 간단합니다. interface도 함수 시그니처를 지정하거나 튜플을 표현할 수는 있지만 문법이 복잡해 잘 활용되지 않습니다.
- 클래스와 구현: interface는 클래스를 통해 구현(implements)될 수 있어 객체 지향 프로그래밍에 자연스럽게 녹아듭니다. 클래스는 인터페이스를 여러 개 구현할 수도 있습니다. 반면 type 별칭은 직접 implements에 사용할 수 없지만, 별칭이 객체 형태인 경우 클래스에서 구현하는 데 활용할 수도 있습니다 (컴파일 시 객체 형태로 해석되므로 가능하나, interface를 쓰는 것이 관례입니다).
예시 – 기본 사용 비교:
// interface로 객체 타입 정의 interface User { name: string; age: number; } // type으로 객체 타입 별칭 정의 type UserType = { name: string; age: number; }; // 동일한 형태로 사용 가능 const user1: User = { name: "Alice", age: 25 }; const user2: UserType = { name: "Bob", age: 30 };
위 코드에서 User 인터페이스와 UserType 타입 별칭은 모두 { name: string; age: number; } 형태를 나타내며, 실제 사용에는 큰 차이가 없습니다. 문법적으로 type은 = 기호를 사용하고, interface는 그렇지 않다는 정도만 다릅니다.
선언 병합(Declaration Merging)과 확장성
선언 병합
interface의 큰 특징 중 하나는 선언 병합(declaration merging)입니다.
동일한 이름으로 여러 번 interface를 선언하면, 타입스크립트는 이를 자동으로 합쳐 하나의 인터페이스로 만듭니다.
반면 type은 동일한 이름으로 두 번 정의할 수 없으며, 중복 선언 시 에러가 발생합니다.
이 특징 때문에 interface는 전역 환경의 타입을 보강하거나(예: Express의 Request 객체에 사용자 정의 속성 추가) 제3자 라이브러리의 타입을 확장할 때 유용합니다.
예를 들어, Express 애플리케이션에서 Request 객체에 사용자 정보를 담는 user 속성을 추가하고 싶다면, 전역적으로 Express의 Request 인터페이스를 병합해야 합니다.// 전역 보강 (Express Request에 사용자 정보 속성 추가) declare global { namespace Express { interface Request { user?: MyUser; // MyUser 타입의 user 속성 추가 } } }
위처럼 동일한 이름의 인터페이스(Express.Request)에 새로운 필드를 선언하면 병합되어, 이후 코드에서 req.user를 타입 안전하게 사용할 수 있습니다.
type 별칭으로는 이런 병합이 불가능하므로, 이 경우 interface가 반드시 필요합니다.
확장(Extends)과 유연한 조합
interface는 extends 키워드로 다른 인터페이스를 확장할 수 있어, 계층적 구조나 객체 지향적 설계에 적합합니다.
예를 들어 여러 컴포넌트에서 공통으로 사용하는 프로퍼티를 베이스 인터페이스로 정의하고 확장하는 식으로 활용할 수 있습니다.
한편, type은 교집합(&)을 이용해 여러 타입을 조합함으로써 유사한 확장 효과를 낼 수 있고, 합집합(|)으로 타입들을 유연하게 결합할 수도 있습니다.이러한 특성 때문에 type은 복잡한 데이터 구조나 여러 형태를 가질 수 있는 타입(예: 문자열 또는 배열일 수 있는 경우 등)을 표현하는 데 유용합니다.
// 인터페이스 확장 interface Person { name: string; } interface Employee extends Person { company: string; } // 선언 병합 (동일 이름 인터페이스 두 번 선언하여 속성 추가) interface Employee { role: string; } // 결과적으로 Employee 인터페이스는 name, company, role 세 가지 속성을 가짐 const emp: Employee = { name: "Charlie", company: "TechCorp", role: "Engineer" }; // 타입 별칭의 교집합(Intersection)으로 확장 효과 내기 type PersonType = { name: string }; type EmployeeType = PersonType & { company: string }; // 같은 이름으로 type을 다시 선언하려 하면 에러 발생 (병합 불가) // type EmployeeType = PersonType & { role: string }; // 오류! // 대신 새 별칭으로 확장 내용을 정의 type EmployeeWithRole = EmployeeType & { role: string }; const emp2: EmployeeWithRole = { name: "Dave", company: "BizInc", role: "Manager" };
위 코드에서 Employee 인터페이스는 두 번 선언되어 name, company, role 모든 속성을 포함하게 되었습니다.
반면 type 별칭은 같은 이름으로 중복 선언할 수 없어, EmployeeType에 role을 추가하려면 별도의 EmployeeWithRole 타입을 정의해야 합니다.
이처럼 interface는 선언 병합을 통한 확장성이 높고, type은 유니온/인터섹션을 통한 유연한 타입 조합에 강점이 있습니다.
객체 지향 vs. 유틸리티 타입
객체 지향적으로 클래스와 상호작용하거나, 라이브러리의 타입을 확장하는 경우 interface가 자연스럽고 편리합니다.
반면 복잡한 유틸리티 타입(Mapped type, Conditional type 등)이나 제네릭 조합을 활용할 때는 type 별칭이 필수적입니다.
예를 들어, 특정 제네릭 T에 조건부로 속성을 추가하는 타입은 interface로 표현할 수 없고 type의 조건부 타입으로만 표현 가능합니다.
성능 차이 (컴파일러 및 실행 성능)
런타임 성능
interface와 type은 모두 컴파일 타임에만 존재하고 런타임에는 제거됩니다.
즉, 실행 성능에는 차이가 없습니다. JavaScript로 컴파일된 결과물을 보면 둘 다 순수한 JS 객체 형태만 남고 타입 정보는 사라지므로, 어느 쪽을 쓰든 런타임 오버헤드는 동일합니다.
컴파일러 성능
한때 "인터페이스를 쓰는 것이 타입 별칭보다 컴파일 속도가 빠르다"는 이야기가 있었습니다.
그 이유 중 하나로, 인터페이스는 이름 기반으로 타입 체크 결과를 캐싱하기 때문에 매우 큰 코드베이스에서는 약간 유리할 수 있다는 분석이 있었습니다.
그러나 최근 경험과 실험에 따르면 실제 성능 차이는 미미하거나 거의 없습니다.
TypeScript 팀과 커뮤니티의 논의 결과, 수천 개의 타입 선언을 실험해 봐도 interface vs type 사용 여부 자체가 빌드 시간이나 IDE 반응 속도를 크게 좌우하지는 않는 것으로 나타났습니다.
요약하면, 일반적인 프로젝트 규모에서는 interface를 쓰든 type을 쓰든 컴파일러의 타입 검사 성능에 큰 영향은 없습니다.
따라서 성능보다는 코드의 가독성, 일관성, 용도에 따라 선택하는 것이 좋습니다.
다음 편에서는 조금 더 개발자 적인 관점에서의 interface vs type 비교에 대해 다뤄보겠습니다.
참고 자료: TypeScript 공식 문서 및 위키, 커뮤니티 블로그, Reddit 토론 등.
반응형'JS & TS' 카테고리의 다른 글
TypeScript interface vs type 비교 2편 (0) 2025.03.17 TypeScript 유틸리티 타입 소개 (0) 2024.10.11 구조분해 사용 팁 4가지 (2) 2024.09.14 Javascript ES15(ECMAScript 2024) 문법정리 (0) 2024.08.14 자바스크립트 비동기 프로그래밍 패턴 (0) 2024.05.28