Frontend/TypeScript

[TypeScript] 5. 클래스

ayeongjin 2025. 1. 27. 00:01

자바스크립트의 클래스란?

2025.01.27 - [Frontend/JavaScript] - [JavaScript] 클래스

 

[JavaScript] 클래스

자바스크립트의 클래스클래스는 동일한 모양의 객체를 더 쉽게 생성하도록 도와주는 문법 // 사용 전 : 코드 중복let studentA = { name: "이정환", grade: "A+", age: 27, study() { console.log("열심히 공부 함");

ayeongjin.tistory.com

 

 

타입스크립트의 클래스

타입스크립트에서는 클래스의 필드를 선언할 때 타입 주석으로 타입을 함께 정의해주어야 한다.

  • 타입 주석으로 타입을 정의해주지 않으면 함수 매개변수와 동일하게 암시적 any 타입으로 추론 (엄격한 타입 검사 모드(strict 옵션이 true로 설정되어 있을 경우)일 때에오류 발생)
  • 추가로 생성자에서 각 필드의 값을 초기화 하지 않을 경우 초기값도 함께 명시해주어야 함
class Employee {
  // 필드
  name: string = "";
  age: number = 0;
  position: string = "";

  // 메서드
  work() {
    console.log("일함");
  }
}
  • 만약 생성자 함수에서 필드의 값들을 잘 초기화 해 준다면 필드 선언시의 초기값 생량 가능
class Employee {
  // 필드
  name: string = "";
  age: number = 0;
  position: string = "";

  // 생성자
  constructor(name: string, age: number, position: string) {
    this.name = name;
    this.age = age;
    this.position = position;
  }

  // 메서드
  work() {
    console.log("일함");
  }
}
  • 이 클래스가 생성하는 객체의 특정 프로퍼티를 선택적 프로퍼티로 만들고 싶다면 다음과 같이 필드의 이름 뒤에 물음표를 붙인다.
class Employee {
  // 필드
  name: string = "";
  age: number = 0;
  position?: string = "";

  // 생성자
  constructor(name: string, age: number, position: string) {
    this.name = name;
    this.age = age;
    this.position = position;
  }

  // 메서드
  work() {
    console.log("일함");
  }
}

 

1. 클래스는 타입이다.

타입스크립트의 클래스는 타입으로도 사용할 수 있다.

  • 클래스를 타입으로 사용하면 해당 클래스가 생성하는 객체의 타입과 동일한 타입이 된다.
class Employee {
  (...)
}

const employeeC: Employee = {
  name: "",
  age: 0,
  position: "",
  work() {},
};
  • 변수 employeeC의 타입을 Employee 클래스로 정의
  • 따라서 이 변수는 name, age, position 프로퍼티와 work 메서드를 갖는 객체 타입으로 정의됩니다.

 

1-1) 상속

  • 타입스크립트에서 클래스의 상속을 이용할 때 파생 클래스(확장하는 클래스)에서 생성자를 정의 했다면 반드시 super 메서드를 호출해 슈퍼 클래스(확장되는 클래스)의 생성자를 호출해야 하며, 호출 위치는 생성자의 최상단 이어야 한다.
class ExecutiveOfficer extends Employee {
  officeNumber: number;

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

 

 


 

접근 제어자 (Access Modifier)

타입스크립트에서만 제공되는 기능으로 클래스의 특정 필드나 메서드를 접근할 수 있는 범위를 설정하는 기능

  • 타입스크립트에서는 다음과 같은 3개의 접근 제어자를 사용할 수 있습니다.
    • public : 모든 범위에서 접근 가능
    • private : 클래스 내부에서만 접근 가능
    • proteced : 클래스 내부 또는 파생 클래스 내부에서만 접근 가능

 

1. public

공공의 라는 뜻으로 어디서든지 이 프로퍼티에 접근할 수 있음을 의미

  • 필드의 접근 제어자를 지정하지 않으면 기본적으로 public 접근 제어자를 갖게 됩니다.
class Employee {
  // 필드
  name: string;      // 자동으로 public
  age: number;       // 자동으로 public
  position: string;  // 자동으로 public

  // 생성자
  constructor(name: string, age: number, position: string) {
    this.name = name;
    this.age = age;
    this.position = position;
  }

  // 메서드
  work() {
    console.log("일함");
  }
}

const employee = new Employee("이정환", 27, "devloper");

employee.name = "홍길동";
employee.age = 30;
employee.position = "디자이너";
  • public 접근 제어자를 직접 명시하는것도 가능
class Employee {
  // 필드
  public name: string;
  public age: number;
  public position: string;

  ...
}

const employee = new Employee("이정환", 27, "devloper");

employee.name = "홍길동";
employee.age = 30;
employee.position = "디자이너";

 

2. Private

제한된, 사적인 이라는 뜻으로 특정 필드나 메서드의 접근 제어자를 private으로 설정하면 클래스 내부에서만 이 필드에 접근 가능

  • name 필드를 private으로 설정했으므로 클래스 외부에서는 접근이 불가능하다.
  • 그러나 클래스 내부에서는 work 메서드 처럼 접근이 자유롭게 가능합니다.
class Employee {
  // 필드
  private name: string; // private 접근 제어자 설정
  public age: number;
  public position: string;

  ...

  // 메서드
  work() {
    console.log(`${this.name}이 일함`); // 여기서는 접근 가능
  }
}

const employee = new Employee("이정환", 27, "devloper");

employee.name = "홍길동"; // ❌ 오류
employee.age = 30;
employee.position = "디자이너";

 

3. Protected

private과 public의 중간으로 클래스 외부에서는 접근이 안되지만 클래스 내부와 파생 클래스에서 접근이 가능하도록 설정하는 접근 제어자

  • Employee 클래스를 확장(상속)하는 파생 클래스 ExecutiveOfficer를 선언한 다음 메서드 func를 만들었다.
  • 이 메서드에서는 name과 age에 접근하는데 이때 name은 private으로 접근이 불가하지만 age는 protected이므로 파생 클래스에서는 접근이 가능
  • 그러나 클래스 외부에서는 접근이 불가합니다.
class Employee {
  // 필드
  private name: string; // private 접근 제어자 설정
  protected age: number;
  public position: string;

  ...

  // 메서드
  work() {
    console.log(`${this.name}이 일함`); // 여기서는 접근 가능
  }
}

class ExecutiveOfficer extends Employee {
 // 메서드
  func() {
    this.name; // ❌ 오류 
    this.age; // ✅ 가능
  }
}

const employee = new Employee("이정환", 27, "devloper");

employee.name = "홍길동"; // ❌ 오류
employee.age = 30; // ❌ 오류
employee.position = "디자이너";

 

4. 필드 생략하기

접근 제어자는 다음과 같이 생성자의 매개변수에도 설정 가능

// 생성자의 매개변수에 접근 제어자 설정 후 중복 필드 제거 전

class Employee {
  // 필드
  private name: string;    // ❌
  protected age: number;   // ❌
  public position: string; // ❌

  // 생성자
  constructor(
    private name: string,
    protected age: number,
    public position: string
  ) {
    this.name = name;
    this.age = age;
    this.position = position;
  }

  // 메서드
  work() {
    console.log(`${this.name} 일함`);
  }
}
  • 그러나 생성자에 접근 제어자를 설정하면 동일한 이름의 필드를 선언하지 못하게 된다.
    • 생성자 매개변수에 name, age, position 처럼 접근 제어자가 설정되면 자동으로 필드도 함께 선언되기 때문
    • 따라서 동일한 이름으로 필드를 중복 선언할 수 없게 되고, 중복된 필드 선언을 모두 제거해 줘야한다.
// 생성자의 매개변수에 접근 제어자 설정 후 중복 필드 제거 후

class Employee {
  // 생성자
  constructor(
    private name: string,
    protected age: number,
    public position: string
  ) {
    this.name = name;
    this.age = age;
    this.position = position;
  }

  // 메서드
  work() {
    console.log(`${this.name} 일함`);
  }
}
  • 또 다음과 접근 제어자가 설정된 매개변수들은 this.필드 = 매개변수가 자동으로 수행된다.
    • 따라서 위 코드의 name, age, position은 모두 this 객체의 프로퍼티 값으로 자동 설정되기 때문에 다음과 같이 생성자 내부의 코드를 제거해도 된다.
// 생성자 내부 코드 제거 후

class Employee {
  // 생성자
  constructor(
    private name: string,
    protected age: number,
    public position: string
  ) {}

  // 메서드
  work() {
    console.log(`${this.name} 일함`);
  }
}
  • 그러므로 타입스크립트에서 클래스를 사용할 때에는 보통 생성자 매개변수에 접근 제어자를 설정하여 필드 선언과 생성자 내부 코드를 생략하는것이 훨씬 간결하고 빠르게 코드를 작성할 수 있다.

 


 

인터페이스를 구현하는 클래스

타입스크립트의 인터페이스는 클래스의 설계도 역할을 할 수 있다.

  • 다음과 같이 인터페이스를 이용해 클래스에 어떤 필드들이 존재하고, 어떤 메서드가 존재하는지 정의 가능
interface CharacterInterface {
  name: string;
  moveSpeed: number;
  move(): void;
}

class Character implements CharacterInterface {
  constructor(
    public name: string,
    public moveSpeed: number,
    private extra: string
  ) {}

  move(): void {
    console.log(`${this.moveSpeed} 속도로 이동!`);
  }
}
  • 인터페이스 CharacterInterface는 name, moveSpeed 프로퍼티와 move 메서드를 갖는 객체 타입을 정의한다.
  • 그런데 이 인터페이스를 클래스에서 implements 키워드와 함께 사용하면 이제부터 이 클래스가 생성하는 객체는 모두 이 인터페이스 타입을 만족하도록 클래스를 구현해야 한다.