ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Javascript] Class란?
    javascript 2024. 12. 7. 19:34

     


    1. Class란?

    Javascript의 Class객체지향 프로그래밍을 지원하기 위해 도입된 문법으로, ES6에서 처음 도입됐으며 기존의 프로토타입 기반 상속을 더 직관적으로 사용할 수 있게 해 준다.

     

    우리는 객체를 직접 작성하여 생성할 수 있지만 Class라는 틀을 만들어줌으로써 다양항 데이터를 비슷한 모양의 객체 만들어줄 수 있다.

     

    (1) 프로토타입 기반 상속이란?

    프로토타입 기반 상속은 Javascript가 객체 간 상속을 처리하는 방식이다.

    Javascript는 Class 기반의 언어가 아닌, 객체를 기반으로 하는 프로토타입 체인을 통해 상속을 구현한다.

     

    프로토타입은 다른 객체로부터 상속받을 수 있는 속성과 메서드를 포함하는 객체이며,

    모든 Javascript 객체는 __proto__ 또는 [[Prototype]]이라는 숨겨진 속성을 통해 프로토타입에 접근할 수 있다.

    const person = {
      greet: function() {
        console.log('Hello!');
      }
    };
    
    const student = {
      study: function() {
        console.log('Studying...');
      }
    };
    
    // student가 person을 상속받도록 설정
    student.__proto__ = person;
    
    student.greet(); // Hello! (person의 메서드를 상속받아 사용)
    student.study(); // Studying...

     

    person의 메서드를 상속받는 것과 같이 객체의 프로토타입에 접근하고 상속받는 구조를 프로토타입 체인이라고 한다.

    또한 객체의 속성이나 메서드를 찾을 때 해당 객체에서 먼저 찾고 없으면 프로토타입 체인을 따라가면서 상위 프로토타입에서 찾는다.

     

    이런 기존 프로토타입 기반 상속을 더 직관적으로 사용할 수 있도록 도입된 게 Class다.

     

    2. 기본 문법

    class Person {
      constructor(name, age) {
        this.name = name;
        this.age = age;
      }
    
      greet() {
        console.log(`안녕하세요, 저는 ${this.name}이고, 나이는 ${this.age}살입니다.`);
      }
    }
    
    const person1 = new Person('KimBoolean', 23);
    person1.greet(); // 안녕하세요, 저는 KimBoolean이고, 나이는 23살입니다.

     

    (1) Class 선언

    Class 키워드를 사용하여 클래스를 선언한다.

    class MyClass {
      // 클래스 내용
    }

     

    (2) 생성자(Constructor)

    Constructor 메서드는 클래스의 인스턴스(객체)를 생성하고 초기화할 때 호출되며 this를 사용하여 인스턴스의 속성을 정의한다.

    class Car {
      constructor(brand) {
        this.brand = brand;
      }
    }
    
    const myCar = new Car('Hyundai');
    console.log(myCar.brand); // Hyundai

     

    (3) 메서드

    클래스 내에서 함수를 메서드로 정의하며, 클래스의 메서드는 자동으로 prototype에 추가된다.

    class Dog {
      bark() {
        console.log('멍멍!');
      }
    }
    
    const dog = new Dog();
    dog.bark(); // 멍멍!

     

    (4) 상속(inheritance)

    extends 키워드를 사용하여 다른 클래스를 상속받을 수 있다.

    class Animal {
      constructor(name) {
        this.name = name;
      }
    
      speak() {
        console.log(`${this.name}이(가) 소리를 냅니다.`);
      }
    }
    
    class Cat extends Animal {
      speak() {
        console.log(`${this.name}이(가) 야옹!`);
      }
    }
    
    const kitty = new Cat('나비');
    kitty.speak(); // 나비이(가) 야옹!

     

    super를 호출하면 부모 클래스의 constructor 또는 메서드를 호출할 수 있다.

    class Animal {
      constructor(name) {
        this.name = name;
      }
    
      speak() {
        console.log(`${this.name}이(가) 소리를 냅니다.`);
      }
    }
    
    class Dog extends Animal {
      constructor(name, breed) {
        super(name); // 부모 클래스의 생성자 호출
        this.breed = breed;
      }
    
      bark() {
        console.log(`${this.name} (${this.breed})이(가) 멍멍!`);
      }
    }
    
    const myDog = new Dog('바둑이', '진돗개');
    myDog.speak(); // 바둑이이(가) 소리를 냅니다.
    myDog.bark();  // 바둑이 (진돗개)이(가) 멍멍!

     

    위 코드에서 Dog 클래스는 Animal 클래스를 상속받고 super(name)은 Animal 클래스의 생성자를 호출하여 this.name를 초기화한다.

     

    (5) 정적 메서드(Stattic Method)

    static 키워드를 사용하여 클래스 자체에 속한 메서드를 정의할 수 있다.

    인스턴스(객체)가 아니라 클래스에서 직접 호출한다.

    class MathUtil {
      // 정적 메서드
      static add(a, b) {
        return a + b;
      }
    
      // 일반 메서드
      subtract(a, b) {
        return a - b;
      }
    }
    
    // 정적 메서드 호출 (클래스를 통해 직접 호출)
    console.log(MathUtil.add(5, 3)); // 8
    
    // 인스턴스 생성
    const mathInstance = new MathUtil();
    
    // 일반 메서드 호출 (인스턴스를 통해 호출)
    console.log(mathInstance.subtract(5, 3)); // 2
    
    // 정적 메서드는 인스턴스를 통해 호출할 수 없음
    // console.log(mathInstance.add(5, 3)); // Error: mathInstance.add is not a function

     

    (6) Getter와 Setter

    클래스 속성에 대한 접근 및 설정을 제어할 수 있다.

    class Rectangle {
      constructor(width, height) {
        this.width = width;
        this.height = height;
      }
    
      get area() {
        return this.width * this.height;
      }
    
      set dimensions({ width, height }) {
        this.width = width;
        this.height = height;
      }
    }
    
    const rect = new Rectangle(10, 20);
    console.log(rect.area); // 200
    
    rect.dimensions = { width: 5, height: 10 };
    console.log(rect.area); // 50

     

    • get: 속성 값을 반환하는 메서드를 정의한다.
    • set: 속성 값을 설정하는 메서드를 정의한다.

     

    3. Class의 특징

    (1) 호이스팅(Hoisting)

    클래스 선언은 호이스팅되지만 초기화되지 않으며, 클래스 선언 전에 접근하면 ReferenceError가 발생한다.

    const p = new Person(); // ReferenceError: Cannot access 'Person' before initialization
    
    class Person {}

     

    (2) 엄격 모드(Strict Mode)

    클래스 본문은 자동으로 엄격모드('use strict')로 실행된다.

     

    (3) 프로토타입 기반

    클래스는 내부적으로 프로토타입 기반 상속을 사용하며 이를 더 직관적으로 사용할 수 있게 해준다.

     

    4. Class는 언제 사용할까?

    Class는 보통 재사용성, 유지보수성, 코드의 모듈화를 높여야 하는 경우 유용하다.

     

    (1) 유사한 객체를 여러개 만들어야 할 때

    같은 구조와 동작을 가진 객체를 반복해서 생성할 때 사용한다.

    class User {
      constructor(name, age) {
        this.name = name;
        this.age = age;
      }
    
      greet() {
        console.log(`안녕하세요, ${this.name}입니다.`);
      }
    }
    
    const user1 = new User('Gdragon', 37);
    const user2 = new User('Taeyang', 37);
    
    user1.greet(); // 안녕하세요, Gdragon입니다.
    user2.greet(); // 안녕하세요, Taeyang입니다.

     

    (2) 코드를 모듈화하고 구조화할 때

    관련된 데이터와 동작을 묶어서 관리하고 싶을 때 사용하며, 복잡한 기능을 여러 클래스로 나누어 설계하면 유지보수에 용이하다.

     

    (3) 상속(inheritance)이 필요한 경우

    부모 클래스의 속성과 메서드를 자식 클래스가 상속받아 확장할 때 유용하다.

    class Animal {
      constructor(name) {
        this.name = name;
      }
    
      speak() {
        console.log(`${this.name}이(가) 소리를 냅니다.`);
      }
    
    
    class Dog extends Animal {
      speak() {
        console.log(`${this.name}이(가) 멍멍!`);
      }
    }
    
    const dog = new Dog('뽀삐');
    dog.speak(); // 뽀삐이(가) 멍멍!

     

    (4) 캡슐화(Encapsulation)가 필요할 때

    클래스 내부의 속성과 메서드를 외부에서 접근하지 못하게 하여 데이터를 보호할 때도 사용한다고 한다.

    보통 프라이빗 필드(#)와 프라이빗 메서드를 사용한다.

    class BankAccount {
      #balance = 0;
    
      deposit(amount) {
        this.#balance += amount;
      }
    
      getBalance() {
        return this.#balance;
      }
    }
    
    const account = new BankAccount();
    account.deposit(1000);
    console.log(account.getBalance()); // 1000

     

    (5) 객체 간의 관계를 명확하게 표현할 때

    예를 들어 자동차와 엔진, 학교와 학생처럼 서로 연결된 개념을 표현할 때 직관적으로 알 수 있다.

     

    (6) 복잡한 상태 관리와 로직이 필요할 때

    상태(state)를 여러 속성으로 관리하고 상태를 변경하는 메서드를 정의할 때 Class를 사용하기 좋다.

     


     

    이렇게 클래스에 대해 간단히 알아보았는데 간단한 데이터 구조나 한 번만 사용할 객체를 생성할 때는 굳이 Class를 사용하지 않고

    객체 리터럴을 사용하는 것이 더 간단하고 효율적이다.

Designed by Tistory.