[TS] 클래스 (class)



01


자바스크립트의 클래스

자바스크립트에서 클래스는 객체를 쉽게 만들 수 있도록 도와주는 템플릿 같은 것이죠.

 

예를 들어, 여러 명의 학생을 관리한다고 할 때, 학생들의 이름, 나이, 성적 등을 매번 하나씩 쓰는 대신에 클래스를 사용하면 학생을 만드는 틀(템플릿)을 만들고, 그 틀을 바탕으로 여러 명의 학생 객체를 만들 수 있어요.

1. 클래스 선언

클래스는 객체의 틀을 정의하는 것입니다. 클래스 선언은 class 키워드로 시작합니다.

class Student {
  // 클래스의 내용
}

 

2. 필드 (프로퍼티) 선언

클래스 안에서 객체가 가질 속성들을 정의할 수 있습니다.

class Student {
  name;
  age;
  grade;
}

 

3. 생성자

생성자는 객체를 만들 때 사용되는 특수한 메서드입니다. 객체의 프로퍼티 값을 초기화하는 역할을 합니다.

class Student {
  name;
  age;
  grade;

  constructor(name, grade, age) {
    this.name = name;
    this.grade = grade;
    this.age = age;
  }
}

 

4. 객체 생성

new 키워드를 사용해 클래스로부터 객체를 만듭니다.

const studentB = new Student("홍길동", "A+", 27);
console.log(studentB); // { name: '홍길동', grade: 'A+', age: 27 }

 

5. 메서드 추가

클래스 안에 기능을 구현하는 메서드를 추가할 수 있습니다.

class Student {
  // 필드
  name;
  age;
  grade;

  // 생성자
  constructor(name, grade, age) {
    this.name = name;
    this.grade = grade;
    this.age = age;
  }

  // 메서드
  study() {
    console.log("열심히 공부 함");
  }

  introduce() {
    console.log(`안녕하세요! ${this.name}입니다.`);
  }
}

let studentB = new Student("홍길동", "A+", 27);
studentB.study(); // 열심히 공부 함
studentB.introduce(); // 안녕하세요! 홍길동입니다.

 

6. this 사용

클래스 안에서 this는 현재 객체를 가리킵니다. 이를 활용해 객체의 속성에 접근하거나 메서드를 실행할 수 있습니다.

 

7. 상속

기존 클래스를 기반으로 새로운 클래스를 만들 때 상속을 사용합니다.
자식 클래스는 부모 클래스의 속성이나 메서드를 그대로 사용할 수 있습니다.

class StudentDeveloper extends Student {
  favoriteSkill;

  constructor(name, grade, age, favoriteSkill) {
    super(name, grade, age); // 부모 클래스의 생성자 호출
    this.favoriteSkill = favoriteSkill;
  }

  programming() {
    console.log(`${this.favoriteSkill}로 프로그래밍 함`);
  }
}

let dev = new StudentDeveloper("이정환", "A+", 27, "JavaScript");
dev.introduce(); // 안녕하세요! 이정환입니다.
dev.programming(); // JavaScript로 프로그래밍 함

 

이렇게 클래스는 객체를 만들 때 중복 코드를 줄여주고, 객체를 더 쉽게 관리할 수 있게 도와줍니다.



02


타입스크립트의 클래스

타입스크립트에서 클래스는 자바스크립트의 클래스와 비슷하지만,

타입을 명시적으로 지정할 수 있어 코드의 안전성을 높여줍니다.

 

이제 타입스크립트에서 클래스를 어떻게 사용하는지 간단히 살펴보겠습니다.

1. 클래스의 필드 타입 선언

타입스크립트에서는 클래스의 필드를 선언할 때 타입을 명시해야 합니다.

그렇지 않으면 암시적 any 타입으로 추론되며, 엄격한 타입 검사 모드에서는 오류가 발생합니다.

class Employee {
  // 필드
  name: string = "";
  age: number = 0;
  position: string = "";

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

 

2. 생성자에서 초기화

생성자에서 각 필드를 초기화하지 않으면, 필드 선언 시 초기값을 지정해야 합니다.

생성자에서 필드를 초기화하면 필드 선언에서 초기값을 생략할 수 있습니다.

class Employee {
  // 필드
  name: string;
  age: number;
  position: string;

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

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

 

3. 선택적 프로퍼티

어떤 프로퍼티는 선택적일 수 있습니다. 선택적 프로퍼티는 필드명 뒤에 물음표(?)를 붙여 정의할 수 있습니다.

class Employee {
  // 필드
  name: string;
  age: number;
  position?: string; // 선택적 프로퍼티

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

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

 

4. 클래스는 타입으로도 사용

타입스크립트에서 클래스는 타입으로도 사용할 수 있습니다.

클래스를 타입으로 사용하면 그 클래스가 생성하는 객체의 타입을 정의할 수 있습니다.

class Employee {
  name: string;
  age: number;
  position: string;

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

  work() {
    console.log("일함");
  }
}

const employeeC: Employee = {
  name: "",
  age: 0,
  position: "",
  work() {}
};

 

5. 상속

타입스크립트에서 클래스 상속 시, 자식 클래스에서 생성자를 정의하면 부모 클래스의 생성자를 호출해야 합니다.

이때 super()를 사용하며, 호출 위치는 생성자의 첫 번째 라인이어야 합니다.

class ExecutiveOfficer extends Employee {
  officeNumber: number;

  constructor(name: string, age: number, position: string, officeNumber: number) {
    super(name, age, position); // 부모 클래스의 생성자 호출
    this.officeNumber = officeNumber;
  }
}

 

이렇게 타입스크립트에서는 타입클래스를 잘 결합하여 코드를 더 안전하고 명확하게 만들 수 있습니다.



03


접근 제어자

타입스크립트에서는 접근 제어자를 사용해서 클래스의 필드나 메서드에 누가 접근할 수 있는지를 설정할 수 있습니다.

다음은 타입스크립트에서 사용할 수 있는 3가지 주요 접근 제어자에 대한 설명입니다.

  • public: 어디서든 접근 가능
  • private: 클래스 안에서만 접근 가능
  • protected: 클래스 안과 자식 클래스에서만 접근 가능

1. public

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, "developer");

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

 

2. private

private은 클래스 내부에서만 접근 가능하며, 외부에서 접근하려고 하면 오류가 발생합니다.

class Employee {
  // 필드
  private name: string; // private 접근 제어자 설정
  public age: number;
  public position: string;

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

  // 메서드
  work() {
    console.log(`${this.name}이 일함`); // 클래스 내부에서는 접근 가능
  }
}

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

employee.name = "홍길동"; // ❌ 오류 (외부에서 접근 불가)
employee.age = 30;       // 가능
employee.position = "디자이너"; // 가능

 

3. protected

protected은 클래스 내부와 파생 클래스에서만 접근 가능하며, 클래스 외부에서는 접근할 수 없습니다.

class Employee {
  // 필드
  private name: string; // private 접근 제어자 설정
  protected age: number; // protected 접근 제어자 설정
  public position: string;

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

  // 메서드
  work() {
    console.log(`${this.name}이 일함`); // 클래스 내부에서는 접근 가능
  }
}

class ExecutiveOfficer extends Employee {
  // 메서드
  func() {
    this.age; // ✅ 가능 (파생 클래스에서 접근 가능)
    this.name; // ❌ 오류 (private으로 접근 불가)
  }
}

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

employee.name = "홍길동"; // ❌ 오류 (외부에서 접근 불가)
employee.age = 30;       // ❌ 오류 (외부에서 접근 불가)
employee.position = "디자이너"; // 가능

 

4. 필드 생략하기

접근 제어자는 생성자의 매개변수에도 설정할 수 있습니다. 이렇게 설정하면 필드를 별도로 선언하지 않아도 됩니다.

class Employee {
  // 생성자에서 접근 제어자 설정
  constructor(
    private name: string,  // private으로 설정
    protected age: number, // protected로 설정
    public position: string // public으로 설정
  ) {}

  // 메서드
  work() {
    console.log(`${this.name}이 일함`);
  }
}

이렇게 하면 필드 선언과 생성자 코드가 간결해집니다. 생성자 매개변수에 접근 제어자를 설정하면, 자동으로 해당 필드가 생성되므로 this.name, this.age 등을 명시적으로 선언할 필요가 없습니다.



04


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

인터페이스는 클래스가 어떤 모양이어야 하는지 미리 정의해주는 역할을 합니다.

클래스를 만들 때, 인터페이스에서 요구한 대로 필드와 메서드를 정확히 구현해야 해요.

1. 인터페이스 정의

인터페이스는 클래스가 구현해야 할 프로퍼티와 메서드를 정의합니다. 

예를 들어, CharacterInterface라는 인터페이스를 정의해 보겠습니다.

interface CharacterInterface {
  name: string;
  moveSpeed: number;
  move(): void;
}

위 인터페이스는 name과 moveSpeed라는 프로퍼티를 가지고 있으며, move()라는 메서드를 반드시 포함해야 한다고 정의하고 있습니다.

 

2. 인터페이스 구현

이 인터페이스를 클래스에서 구현하려면 implements 키워드를 사용합니다.

클래스는 인터페이스에서 정의한 모든 필드와 메서드를 구현해야 합니다.

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

  move(): void {
    console.log(`${this.moveSpeed} 속도로 이동!`);
  }
}

여기서 Character 클래스는 CharacterInterface를 구현합니다.

name, moveSpeed 필드를 가지고 있으며, move() 메서드를 구현합니다.

클래스에서 implements 키워드를 사용하면 타입스크립트는 해당 클래스가 인터페이스에서 요구하는 모든 필드와 메서드를 구현했는지 확인합니다.

 

3. 인터페이스 구현 후 사용

이제 Character 클래스는 CharacterInterface를 구현하므로, 인터페이스에서 요구한 대로 객체를 생성하고 사용할 수 있습니다.

const hero = new Character("Warrior", 10, "Extra Data");
console.log(hero.name); // Warrior
console.log(hero.moveSpeed); // 10
hero.move(); // 10 속도로 이동!

 

4. 인터페이스 활용

인터페이스는 객체의 타입을 정의할 때 유용합니다.

클래스가 어떤 형태를 가져야 하는지 강제할 수 있기 때문에, 코드의 유지보수성과 가독성을 높일 수 있습니다.

function printCharacterInfo(character: CharacterInterface) {
  console.log(`이름: ${character.name}, 이동 속도: ${character.moveSpeed}`);
}

const hero = new Character("Warrior", 10, "Extra Data");
printCharacterInfo(hero); // 이름: Warrior, 이동 속도: 10

이 예제에서 printCharacterInfo 함수는 CharacterInterface 타입을 가진 객체만 받을 수 있습니다. 이 함수는 name과 moveSpeed를 출력하며, move 메서드는 호출하지 않습니다.



05


마무리

타입스크립트와 자바스크립트에서 클래스는 객체 지향 프로그래밍의 중요한 개념으로, 여러 객체를 효율적으로 관리하고 생성할 수 있게 도와줍니다.

객체를 만들 때 반복적인 코드를 줄여주는 템플릿 역할을 하며, 클래스의 설계도에 맞게 객체가 만들어지기 때문에 구조적인 코드 작성이 가능합니다.

 

 

✅ 클래스는 객체를 쉽게 만들 수 있게 도와주는 템플릿입니다.
이 템플릿을 사용해 객체의 속성기능을 정의하고 여러 객체를 쉽게 생성할 수 있습니다.

 

✅ 타입스크립트는 타입을 명시적으로 지정하여 오류를 미리 방지해 줍니다.

 

✅ 접근 제어자를 사용해 클래스 내부와 외부에서의 접근 범위를 설정함으로써,
데이터의 캡슐화와 보안성을 강화할 수 있습니다.

  • public: 모든 코드에서 접근할 수 있습니다.
  • private: 클래스 내부에서만 접근할 수 있습니다.
  • protected: 클래스 내부와 상속된 클래스에서만 접근할 수 있습니다.

✅ 인터페이스는 클래스가 반드시 따라야 할 구조를 정의하여 코드의 일관성유지보수성을 높여줍니다.

 

 

 

'DEVELOPMENT > Typescript' 카테고리의 다른 글

[TS] 타입 조작하기  (0) 2025.03.04
[TS] 제네릭 (Generics)  (1) 2025.03.03
[TS] 인터페이스 (Interface)  (0) 2025.02.28
[TS] 함수와 타입  (1) 2025.02.27
[TS] 타입 시스템  (0) 2025.02.26