[TypeScript] 인터페이스 설계

인터페이스란

인터페이스는 객체의 모양을 정의하는 TypeScript의 타입 도구입니다. 속성과 그 타입, 메서드의 시그니처를 명시하여 코드가 예상대로 동작하도록 보장합니다.

interface Product {
  id: number;
  name: string;
}

const item: Product = {
  id: 1,
  name: "노트북",
};

console.log(`상품: ${item.name} (ID: ${item.id})`);
// 출력: 상품: 노트북 (ID: 1)

여기서 Product 인터페이스는 객체가 id와 name 속성을 반드시 가져야 함을 정의합니다.

선택적 속성과 읽기 전용 속성 활용

인터페이스는 유연성을 제공하기 위해 선택적 속성(`?`)과 읽기 전용 속성(`readonly`)을 지원합니다.

  • 선택적 속성: 물음표(?)를 사용하여 선택적 속성을 지정하면 해당 속성이 없어도 에러가 발생하지 않습니다.
  • 읽기 전용 속성: 읽기 전용(readonly)으로 선언하여 초기 할당 이후 수정이 불가능하게 만들 수 있습니다.
interface Task {
  readonly taskId: string; // 한 번 설정 후 변경 불가
  title: string;
  deadline?: Date; // 선택적 속성
}

const todayTask: Task = {
  taskId: "T123",
  title: "리포트 작성",
};

console.log(`작업 ID: ${todayTask.taskId}, 제목: ${todayTask.title}`);
// 출력: 작업 ID: T123, 제목: 리포트 작성

// todayTask.taskId = "T124"; // 오류: 읽기 전용 속성은 수정 불가

deadline은 필수가 아니므로 생략 가능하고, taskId는 읽기 전용으로 설정되어 값이 바뀌지 않습니다.

인터페이스 확장

인터페이스는 다른 인터페이스를 확장하여 재사용성과 모듈화를 높일 수 있습니다. 이는 공통 속성을 공유하는 객체를 설계할 때 특히 유용합니다.

interface User {
  username: string;
  email: string;
}

interface Admin extends User {
  role: string;
}

const adminUser: Admin = {
  username: "superuser",
  email: "admin@example.com",
  role: "관리자",
};

console.log(`${adminUser.username} (${adminUser.role})`);
// 출력: superuser (관리자)

함수와 클래스에서 인터페이스 사용

인터페이스는 함수 타입이나 클래스 구현에도 활용 가능합니다. 청사진 역할을 하여, 함수와 클래스가 반드시 구현해야 할 속성과 메서드를 강제할 수 있습니다.

함수 타입 정의

interface Logger {
  log(message: string): void;
}

const consoleLogger: Logger = {
  log: (message) => console.log(`[로그] ${message}`),
};

consoleLogger.log("서버 시작");
// 출력: [로그] 서버 시작

클래스 구현

interface Animal {
  name: string;
  makeSound(): string;
}

class Dog implements Animal {
  name: string;

  constructor(name: string) {
    this.name = name;
  }

  makeSound(): string {
    return "멍멍!";
  }
}

const myDog = new Dog("바둑이");
console.log(`${myDog.name}가 소리를 냅니다: ${myDog.makeSound()}`);
// 출력: 바둑이가 소리를 냅니다: 멍멍!