Programming Language/JS & TS

[TS] interface와 type 비교 및 상속, 그리고 Omit과 Pick 활용

monkeykim 2024. 10. 21. 23:03

TypeScript를 사용하다 보면 객체의 구조를 정의할 때 가장 자주 사용하는 것이 바로 interface와 type입니다. 이 둘은 매우 유사하지만, 용도와 사용 방식에서 미묘한 차이가 있습니다. 이번 글에서는 interface와 type의 차이를 살펴보고, 어떻게 상속받거나 확장할 수 있는지 알아보겠습니다. 또한, Omit과 Pick 같은 유틸리티 타입을 통해 좀 더 유연하게 타입을 관리하는 방법을 배워보겠습니다.


1. interface와 type의 차이

interface란?

interface는 주로 객체의 구조를 정의할 때 사용합니다. 특히 객체 지향 프로그래밍 스타일에 익숙하다면, 상속을 통해 인터페이스를 확장하는 방식이 매우 자연스러울 것입니다.

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

interface Employee extends Person {
  position: string;
}

const john: Employee = {
  name: "John",
  age: 30,
  position: "Developer"
};

type이란?

type은 타입 별칭을 정의하는 도구입니다. type을 사용하면 단순히 객체의 구조뿐만 아니라 유니언, 튜플, 기타 복잡한 타입을 정의할 수 있습니다. interface와 다르게 직접적인 상속은 불가능하지만, 유니언(|)과 인터섹션(&)을 사용하여 타입을 확장할 수 있습니다.

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

type Employee = Person & {
  position: string;
};

const jane: Employee = {
  name: "Jane",
  age: 28,
  position: "Designer"
};

 

Employee는 Person 타입을 확장해 새로운 타입을 정의하고, position 속성을 추가합니다. & 연산자를 사용해 인터섹션 타입으로 타입을 결합할 수 있습니다.


2. interface와 type의 주요 차이점

특징interfacetype

확장 상속을 통해 확장 가능 &(인터섹션) 또는 `
중복 선언 가능 (자동 병합됨) 불가능 (중복 선언 시 오류 발생)
사용 범위 주로 객체의 구조 정의 객체, 원시 타입, 유니언, 튜플 등 다양한 타입 정의 가능
유틸리티 타입과의 호환성 Omit, Pick 등을 사용할 수 있음 마찬가지로 유틸리티 타입을 사용할 수 있음

3. Omit과 Pick을 활용한 타입 조작

Omit: 특정 속성 제외하기

Omit은 기존 타입에서 특정 속성을 제외하여 새로운 타입을 만들 때 사용합니다. 예를 들어, Person 타입에서 age 속성만 제외하고 싶다면 Omit을 사용할 수 있습니다.

type Person = {
  name: string;
  age: number;
  address: string;
};

type PersonWithoutAge = Omit<Person, "age">;

const tom: PersonWithoutAge = {
  name: "Tom",
  address: "123 Street"
};
 

Pick: 특정 속성만 선택하기

반대로 Pick은 기존 타입에서 특정 속성만 선택하여 새로운 타입을 만들 때 사용됩니다. Person에서 name과 address만 선택하고 싶다면 다음과 같이 사용할 수 있습니다.

type Person = {
  name: string;
  age: number;
  address: string;
};

type PersonWithNameAndAddress = Pick<Person, "name" | "address">;

const anna: PersonWithNameAndAddress = {
  name: "Anna",
  address: "456 Avenue"
};
 

실전 예시: 사용자 데이터 관리

기본 사용자 타입 정의

예를 들어, 우리가 사용자 데이터를 관리하는 애플리케이션을 만든다고 가정해보겠습니다. 이때, 각 사용자의 정보를 표현하기 위해 기본적인 User 타입을 정의할 수 있습니다.

type User = {
  id: number;
  name: string;
  email: string;
  password: string;
  address: string;
  phone: string;
  role: 'admin' | 'user';
};

이 타입은 사용자마다 고유한 id, name, email, password, address, phone, 그리고 사용자 권한인 role을 포함하고 있습니다.

 

예시 1: Omit을 사용하여 비밀번호 제거하기

서버에서 사용자 데이터를 클라이언트로 전송할 때 보안상의 이유로 **비밀번호(password)**를 포함하지 않으려면, Omit을 사용하여 비밀번호를 제거한 타입을 만들 수 있습니다.

// User 타입에서 password를 제외한 새로운 타입
type PublicUser = Omit<User, 'password'>;

const publicUser: PublicUser = {
  id: 1,
  name: "Alice",
  email: "alice@example.com",
  address: "123 Wonderland Ave",
  phone: "555-1234",
  role: 'user'
};

PublicUser는 User에서 비밀번호를 제외한 모든 속성을 가진 타입입니다. 이제 클라이언트에게 전송할 때는 이 타입을 사용하여 비밀번호 유출을 방지할 수 있습니다.

예시 2: Pick을 사용하여 필수 정보만 선택하기

때로는 사용자 목록을 관리할 때 모든 정보가 필요하지 않을 수 있습니다. 예를 들어, 사용자 목록에서 기본적인 정보(이름, 이메일, 전화번호)만 표시하려면, Pick을 사용해 필요한 속성만 선택할 수 있습니다.

// User 타입에서 이름, 이메일, 전화번호만 선택한 타입
type BasicUserInfo = Pick<User, 'name' | 'email' | 'phone'>;

const basicUserInfo: BasicUserInfo = {
  name: "Bob",
  email: "bob@example.com",
  phone: "555-5678"
};
 

BasicUserInfo 타입은 사용자 목록에 표시할 때 필요한 정보만 포함합니다. 이렇게 필요한 정보만 선택해서 처리하면 불필요한 데이터를 제거하여 성능을 최적화할 수 있습니다.


추가 예시: 관리자 데이터를 위한 타입 확장

관리자(admin)는 일반 사용자와 달리 추가적인 권한이 필요합니다. 예를 들어, 관리자는 다른 사용자를 생성, 수정, 삭제할 수 있는 권한이 있어야 합니다. 이를 위해, User 타입을 확장해 새로운 Admin 타입을 정의해보겠습니다.

type Admin = User & {
  permissions: string[];
};

이때, Admin 타입은 기존 User 타입을 확장하여 추가적인 permissions 배열을 포함하게 됩니다. 이제 각 관리자는 특정 권한을 가진 리스트를 가질 수 있습니다.

const adminUser: Admin = {
  id: 2,
  name: "Carol",
  email: "carol@example.com",
  password: "secret123",
  address: "456 Tech Blvd",
  phone: "555-7890",
  role: 'admin',
  permissions: ["create", "edit", "delete"]
};

이렇게 새로운 타입을 확장하거나 조합하여 다양한 사용자 역할에 따라 필요한 데이터를 관리할 수 있습니다.


요약

  • Omit은 객체 타입에서 특정 속성을 제외할 때 유용하며, 예를 들어 비밀번호와 같은 민감한 데이터를 처리하지 않으려면 사용할 수 있습니다.
  • Pick은 객체 타입에서 특정 속성만 선택하여 필요한 정보만 남길 때 유용합니다. 사용자 목록에서 최소한의 정보만 보여줄 때 사용할 수 있습니다.
  • 타입 확장을 통해 User 타입을 확장해 관리자 등 특정 역할에 맞춘 추가적인 속성을 정의할 수 있습니다.

Omit과 Pick은 객체 타입을 관리하고 확장할 때 매우 유용한 도구입니다. 이를 통해 코드를 더욱 간결하고 안전하게 작성할 수 있습니다.