onebite TS - 6강. 클래스

박하늘·2025년 10월 21일

자바스크립트의 클래스 소개

let studentA = {
  name: "이정환",
  grade: "A+",
  age: 27,
  study() {
    console.log("열심히 공부 함");
  },
  introduce() {
    console.log("안녕하세요!");
  },
};

// 만약 이때 한명의 학생이 더 필요하다면 다음과 같이 새로운 변수를 만들어야 합니다.

let studentB = {
  name: "홍길동",
  grade: "A+",
  age: 27,
  study() {
    console.log("열심히 공부 함");
  },
  introduce() {
    console.log("안녕하세요!");
  },
};
  • 붕어빵이 객체라면 붕어빵 기계는 클래스
  • 두 학생 모두 필드가 동일함

✴︎ 클래스 선언

  • 클래스를 선언했다면 다음으로는 필드를 선언
  • 필드란 이 클래스가 생성할 객체가 갖는 프로퍼티를 의미
  • 학생 객체는 name, age, grade 프로퍼티를 갖기 때문에 다음과 같이 필드를 선언
class Student {
  // 필드
  name;
  age;
  grade;

  // 생성자 - 특수한 메서드로 실질적으로 객체를 생성하는 함수입니다. 
  constructor(name, grade, age) {
    this.name = name;
    this.grade = grade;
    this.age = age;
    // 이때 this는 객체이며 현재 만들고 있는 객체를 의미
  }
}

// ⭐️ 클래스를 이용해서 만든 객체 -> 인스턴스

// 즉, studentB 는 스튜던트 인스턴스
const studentB = new Student("홍길동", "A+", 27);
// 이렇게 생성할 수 있음 인수 순서 맞춰서

✴︎ 메서드도 클래스에 포함

  • 쉼표 사용하면 안 됨
class Student1 {
  // [필드]
  name;
  grade;
  age;

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

  // [메서드] - 아래처럼 메서드 추가 해주면 됨
  study() {
    console.log("열심히 공부 함");
  }

  introduce() {
    console.log(`안녕하세요!`);
  }
}

let studentBb = new Student1("홍길동", "A+", 27);

studentBb.study(); // console - 열심히 공부 함
studentBb.introduce(); // console - 안녕하세요!

✴︎ this 사용

class Student12 {
  // [필드]
  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 studentBb1 = new Student12("홍길동", "A+", 27);
studentB.introduce(); // console - 안녕하세요 홍길동 입니다!

✴︎ 클래스의 상속

class StudentDeveloper extends Student {
  // [필드]
    name;
    age;
    grade;
    favoriteSkill;

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

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

  introduce() {
    console.log(`안녕하세요!`);
  }

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

⚠️ 위처럼 학생의개발 직군으로 또 만들면 기존 학생 클래스와 겹치는 필드와 메서드 존재

class StudentDeveloper extends Student {
  // [필드]
  favoriteSkill;
  // StudentDeveloper 에 추가시킬 필드만 입력

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

  // 메서드
  programming() {
    console.log(`${this.favoriteSkill}로 프로그래밍 함`);
  }
}
  • constructor(name, grade, age, favoriteSkill) : StudentDeveloper 클래스에서 Student 클래스의 생성자를 함께 호출. 그렇지 않으면 생성되는 객체의 name, grade, age 값이 제대로 설정되지 않음
  • super(name, grade, age); : super를 호출하고 인수로 name, grade, age를 전달하면 슈퍼 클래스(확장 대상 클래스)의 생성자를 호출

2️⃣ 타입스크립트의 클래스

▪️ 클래스 선언 방식의 예

✴︎ 타입스크립트의 클래스 에러 (1)

class Employee {
  // [필드]
  name;
  age;
  position;

  // [메서드]
  work() {
    console.log("일함");
  }
}
  • 위처럼 선언 시 추론 불가한 타입으로 자동 any 타입으로 타입 추론이 되므로 에러 발생
  • 이때 any 타입 도 허용하고 싶을 경우 - tsconfig.json 파일에 noImpliciANY: false 로 하면 허용 됨

✴︎ 타입스크립트의 클래스 에러 (2)

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

  // [메서드]
  work() {
    console.log("일함");
  }
}
  • 위 예시도 초기값도 없고 생성자 할당도 안 되어 있으면 안 되어서 에러 발생

✴︎ 올바른 TS 클래스 선언

[1] 초기값 설정

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

  // [메서드]
  work() {
    console.log("일함");
  }
}
  • 이렇게 필드에 초기값 설정 해주면 에러 안 남

[2] 생성자 설정

class Employee1 {
  // [필드]
  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 employeeB = new Employee1("박하늘", 25, "개발자")
  • 이렇게 사용할 경우 employeeB에 커서를 올리면 타입이 Employee1 인 걸로 나옴

▪️ 클래스의 확장

class Employee1 {
  (...)
}

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

// Employee1 보다 확장
class ExecutiveOfficer extends Employee1 {
  officeNumber: number;

  constructor(
    name: string,
    age: number,
    position: string,
    officeNumber: number
  ) {
    super(name, age, position);
    this.officeNumber = officeNumber;
  }
}
  • super(name, age, position); : js 에서는 super 없어도 가능하지만 TS 에서는 불가 에러 발생

3️⃣ 접근 제어자

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

- public : 모든 범위에서 접근 가능
- private : 클래스 내부에서만 접근 가능
- proteced : 클래스 내부 또는 파생 클래스 내부에서만 접근 가능

▪️ public

  • 기본값 - 객체이기도 하고 각각 필드에 자동으로 접근제어자인 public 이 걸려있음
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 employee = new Employee('박하늘', 25, "developer")
employee.age = 30
employee.name = "바가늘"
// 이런식으로 클래스 외부에서도 프로퍼티에 접근하여 재선언(수정) 가능

▪️ private

  • 클래스 자신 + 자식 클래스에서 접근 가능

✴︎ 클래스 외부 사용 불가

class Employee1 {
  private name: string ;
  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("일함");
  }
}


const employee1 = new Employee1('박하늘', 25, "developer")
employee1.age = 30
employee1.name = "바가늘" // ❌ - private 을 걸어주면 클래스 외부에서 접근 불가 


// 메서드에 (클래스 내부) 사용시에는 this 로 사용(접근) 가능

work() {
    console.log(`${this.name}일함`);
  }

✴︎ 상속 받는 클래스도 사용 불가

class ExecutiveOfficer extends Employee1 {
  officeNumber: number;

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

  func () {
    this.name
  }
}
  • Employee1 클래스를 상속받는 ExecutiveOfficer 클래스에서 Employee1 클래스에 선언된 필드인 name 도 사용 불가능

▪️ proteced

  • 클래스 외부에서 사용 불가
  • 파생 클래스 내부에서는 사용 가능
class User {
  protected age: number;

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

class Developer extends User {
  introduce() {
    console.log(`저는 ${this.age}살 개발자입니다.`); // ✅ 가능 (자식 클래스)
  }
}

const dev = new Developer(25);
// console.log(dev.age); // ❌ 외부 접근 불가

▪️ 필드 생략하기

❌ - 아래처럼 작성하면 필드랑 생성자랑 중복된다고 인식. 즉, 필드 생략 가능

class Employee11 {
  // 필드
  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} 일함`);
  }
}

⭕️ - 아래처럼 생락하여 사용 가능

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

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

4️⃣ 인터페이스와 클래스

  • interface 는 접근제어자 중 무조건 public 필드만 정의 가능
interface CharacterInterface {
  name: string;
  moveSpeed: number;
  move(): void;
}

// Character 는 CharacterInterface 인터페이스를 구현한다 라는 뜻
// CharacterInterface 를 필드로 사용하면 되는 느낌

class Character implements CharacterInterface {
  constructor(
    public name: string,
    public moveSpeed: number,
    private extra: string
    // ⚠️ 이거처럼 클래스에 따로 정의 하면 private 사용 가능
  ) {}

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

0개의 댓글