프로그래밍 언어/TypeScript

타입스크립트의 객체 지향 프로그래밍, 클래스, 인터페이스, 상속 정리 - TypeScript #4

eco7T 2025. 3. 18. 14:47
반응형

이번에는 TypeScript를 활용한 객체 지향 프로그래밍(OOP)에 대해 정리해 보겠습니다. TypeScript의 클래스, 인터페이스, 접근 제어자, 상속, 다형성, 추상 클래스, 데코레이터 같은 기능을 예시와 함께 살펴보겠습니다.

타입스크립트의 객체 지향 프로그래밍
타입스크립트의 객체 지향 프로그래밍

 

반응형


 
클래스와 인터페이스

객체 지향 프로그래밍(OOP)의 본질은 프로그램을 다양한 객체 간의 상호작용이라는 것에 있습니다. TypeScript는 JavaScript를 기반으로 하지만, 클래스(Class) 중심으로 전통적인 OOP 언어처럼 객체를 설계할 수 있도록 합니다.

예를 들어, 아래는 간단한 User 클래스를 만든 코드입니다.

class User {
  name: string;
  age: number;

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

  introduce(): string {
    return `안녕하세요, 저는 ${this.name}이고, 나이는 ${this.age}살이에요.`;
  }
}

이 코드에서는 User라는 클래스를 정의하고, nameage라는 두 개의 속성을 설정했습니다. 생성자(constructor)를 통해 객체를 만들 때 필요한 초기값을 지정할 수 있으며, introduce 메서드를 사용해 사용자 정보를 문자열로 나타낼 수 있습니다.

 

 

생성자와 클래스 속성

TypeScript에서는 클래스 속성과 메서드를 정의할 때 타입을 명확히 지정함으로써 나중에 코드를 수정하거나 관리를 편하게 하도록 합니다. 또한, 생성자에서 파라미터에 접근 제어자를 바로 붙이면 별도로 속성을 선언하지 않아도 됩니다.

class Product {
  constructor(
    public id: number,
    public name: string,
    private price: number
  ) {
    // 생성자에서 접근 제어자를 사용하면
    // 속성을 따로 선언하지 않고도 바로 초기화 가능
  }

  getPrice() {
    return this.price;
  }
}

 

인터페이스로 구조 설계

TypeScript의 인터페이스(interface)는 실제 코드를 구현하지 않고 객체의 모양을 정의하는 데 사용됩니다. 주로 객체의 형태를 규정하거나 클래스가 따라야 할 규칙을 정할 때 유용합니다.

interface IShape {
  width: number;
  height: number;
  getArea(): number;
}

class Rectangle implements IShape {
  constructor(
    public width: number,
    public height: number
  ) {}

  getArea(): number {
    return this.width * this.height;
  }
}

위 코드는 IShape라는 인터페이스를 만들어 width, height 속성과 getArea 메서드의 틀을 정의한 뒤, Rectangle 클래스가 이를 따르도록 설계한 경우입니다. implements 키워드를 통해 인터페이스의 요구사항을 충족하도록 강제하므로, 구조적인 실수를 미리 방지할 수 있습니다.

 

 

  접근 제어자 (public, private, protected)

접근 제어자는 객체 지향 프로그래밍에서 정보 은닉(Information Hiding)을 구현하는 데 중요한 도구입니다. TypeScript는 public, private, protected라는 세 가지 키워드를 제공하며, 이를 통해 클래스 내부 데이터를 보호하거나 외부에 노출할 범위를 조정할 수 있습니다.

  • public: 누구나 접근 가능
  • private: 클래스 내부에서만 사용 가능
  • protected: 클래스와 그 하위 클래스에서만 접근 가능

 

 

TypeScript에서 접근 제어자 사용법

TypeScript에서 접근 제어자를 활용하는 방법은 다음과 같습니다.

class BankAccount {
  public accountNumber: string;
  private balance: number;
  protected ownerName: string;

  constructor(accountNumber: string, ownerName: string, initialBalance: number) {
    this.accountNumber = accountNumber;
    this.ownerName = ownerName;
    this.balance = initialBalance;
  }

  public deposit(amount: number): void {
    this.balance += amount;
  }

  public getBalance(): number {
    return this.balance;
  }
}
  • accountNumber는 외부에서 자유롭게 접근할 수 있도록 public으로 설정했습니다.
  • balance는 외부에서 함부로 바꾸지 못하게 private로 제한했습니다.
  • ownerName은 하위 클래스에서도 사용할 수 있도록 protected로 지정했습니다.

 

  추상 클래스와 상속

추상 클래스(abstract class)는 직접 객체를 생성할 수 없으며, 반드시 하위 클래스가 상속받아 완성해야 하는 설계도 같은 클래스입니다. 인터페이스와 달리 일부 로직을 미리 구현할 수 있고, 나머지 구현은 abstract 키워드로 자식 클래스에 맡길 수 있습니다.

abstract class Shape {
  abstract getArea(): number;
  printArea() {
    console.log(`이 도형의 면적은 ${this.getArea()}예요.`);
  }
}

Shape 클래스는 getArea()를 하위 클래스에서 반드시 정의하도록 요구하며, printArea()라는 공통 메서드를 제공해 모든 자식 클래스에서 활용할 수 있게 합니다.

 

상속과 다형성의 힘

  • 상속(Inheritance): 부모 클래스의 속성과 메서드를 자식 클래스가 물려받아 사용하는 구조입니다.
  • 다형성(Polymorphism): 동일한 틀(인터페이스나 추상 클래스)을 기반으로 서로 다른 구현을 가능하게 하는 특성입니다.

 

예를 들어, Shape를 상속받은 CircleRectangle은 각기 다른 방식으로 getArea()를 구현할 수 있습니다.

class Circle extends Shape {
  constructor(private radius: number) {
    super();
  }

  getArea(): number {
    return Math.PI * this.radius * this.radius;
  }
}

 

상속과 다형성을 잘 활용하면 동일한 타입으로 객체를 다루면서도 상황에 따라 다른 동작을 유연하게 처리할 수 있어 코드의 확장성이 높아집니다.

 

 

  데코레이터

데코레이터(Decorator)는 클래스, 메서드, 속성 등에 붙여서 기능을 확장하거나 설정을 추가할 수 있는 도구입니다. TypeScript에서 공식 지원되지만, 실험적 기능으로 일부 설정이 필요합니다.

  • tsconfig.json에서 experimentalDecorators를 활성화해야 합니다.
  • 메타데이터 활용 시 emitDecoratorMetadata도 설정할 수 있습니다.

데코레이터는 네 가지로 나눌 수 있습니다.

  1. 클래스 데코레이터: 클래스 자체를 수정하거나 새로운 특성을 추가합니다.
  2. 메서드 데코레이터: 메서드 실행 전후에 로직을 삽입할 수 있습니다.
  3. 프로퍼티 데코레이터: 속성 접근을 제어하거나 메타데이터를 관리합니다.
  4. 파라미터 데코레이터: 메서드 파라미터에 추가 정보를 붙여 검증이나 로깅에 활용합니다.

예를 들어, 메서드 호출을 기록하는 간단한 로그 데코레이터를 만들 수 있습니다.

function LogMethod(
  target: any,
  propertyKey: string,
  descriptor: PropertyDescriptor
): PropertyDescriptor {
  const originalMethod = descriptor.value;
  descriptor.value = function (...args: any[]) {
    console.log(`호출된 메서드: ${propertyKey}(${JSON.stringify(args)})`);
    return originalMethod.apply(this, args);
  };
  return descriptor;
}

class ExampleService {
  @LogMethod
  fetchData(param: string) {
    return `결과값: ${param}`;
  }
}

 

 

React Native에서 데코레이터 사용 시 주의점

React Native에서 데코레이터를 사용할 때는 몇 가지를 고려해야 합니다.

  • 빌드 환경: babel이나 tsc에서 experimentalDecorators 설정이 필요하며, 프로젝트마다 다를 수 있습니다.
  • 성능 문제: 데코레이터를 과도하게 쓰면 코드가 복잡해져 성능에 영향을 줄 수 있습니다.
  • 호환성: 일부 라이브러리가 데코레이터를 지원하지 않을 수 있으니 확인이 필요합니다.

 


2025.03.12 - [프로그래밍 언어/TypeScript] - TypeScript 고급 타입 활용, React 에서 제네릭과 유니온 타입으로 안전성 높이기 - TypeScript #3

 

TypeScript 고급 타입 활용, React 에서 제네릭과 유니온 타입으로 안전성 높이기 - TypeScript #3

이번에는 TypeScript 코드를 다룰 때 타입 안전성을 높이고, 유지보수와 확장성을 강화하는 방법 중 "고급 타입" 활용에 대해 정리해 보겠습니다.  TypeScript 고급 타입 활용  유니온 타입과 인터

eco7t.tistory.com

2025.03.07 - [프로그래밍 언어/TypeScript] - TypeScript 변수 선언부터 객체 인터페이스까지 기본 문법과 타입 시스템 - TypeScript #2

 

TypeScript 변수 선언부터 객체 인터페이스까지 기본 문법과 타입 시스템 - TypeScript #2

TypeScript의 기본 문법과 타입 시스템에 살펴보고, 코드를 더 안전하고 효율적으로 작성할 수 있는 방법에 대해 정리해 보겠습니다.   TypeScript 기본 문법과 타입 시스템  기본 타입 (number, string, b

eco7t.tistory.com

 

반응형