JavaScript ES6 Class

ECMAScript 6(ES6)에서 도입된 클래스는 자바스크립트의 객체 지향 프로그래밍(OOP)을 보다 직관적이고 간결하게 작성할 수 있게 해줍니다. 기존의 프로토타입 기반 상속 방식을 추상화하여, 더 익숙한 문법으로 객체를 정의하고 상속할 수 있습니다. ES6 클래스는 자바스크립트의 프로토타입 기반 상속을 문법적으로 감싸는 것일 뿐, 근본적인 동작 방식은 기존의 프로토타입 기반 상속과 동일합니다.

1. 클래스 정의

ES6에서 클래스를 정의하는 방법은 다음과 같습니다.

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

  greet() {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  }
}

const john = new Person('John', 30);
john.greet(); // Hello, my name is John and I am 30 years old.
  • class 키워드를 사용하여 클래스를 정의합니다.
  • constructor 메서드는 인스턴스를 초기화하는 특별한 메서드로, 인스턴스가 생성될 때 자동으로 호출됩니다.
  • 클래스 내부에 정의된 메서드는 모두 프로토타입 메서드로 정의됩니다.

2. 클래스 상속

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

class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a sound.`);
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name); // 부모 클래스의 constructor 호출
    this.breed = breed;
  }

  bark() {
    console.log(`${this.name} barks.`);
  }
}

const rex = new Dog('Rex', 'German Shepherd');
rex.speak(); // Rex makes a sound.
rex.bark();  // Rex barks.
  • extends 키워드를 사용하여 상속을 구현합니다.
  • 자식 클래스의 생성자에서 super 키워드를 사용하여 부모 클래스의 생성자를 호출해야 합니다.

3. 정적 메서드와 정적 속성

클래스 자체에 속하는 정적 메서드와 정적 속성을 정의할 수 있습니다. 정적 메서드와 속성은 인스턴스가 아니라 클래스 자체에서 호출됩니다.

class MathUtil {
  static add(a, b) {
    return a + b;
  }

  static get PI() {
    return 3.141592653589793;
  }
}

console.log(MathUtil.add(2, 3)); // 5
console.log(MathUtil.PI);        // 3.141592653589793
  • static 키워드를 사용하여 정적 메서드와 속성을 정의합니다.
  • 정적 메서드와 속성은 클래스 이름으로 호출합니다.

4. 클래스 필드

ES6 이후, 클래스 필드를 정의할 수 있는 문법이 추가되었습니다. 이는 클래스 내부에서 속성을 정의할 수 있게 해줍니다.

class Car {
  brand = 'Toyota';

  constructor(model) {
    this.model = model;
  }

  displayInfo() {
    console.log(`This car is a ${this.brand} ${this.model}.`);
  }
}

const myCar = new Car('Corolla');
myCar.displayInfo(); // This car is a Toyota Corolla.
  • 클래스 필드는 constructor 외부에 정의됩니다.
  • 초기값을 설정할 수 있으며, 모든 인스턴스가 해당 초기값을 가집니다.

5. Private 필드

ES2021에서 도입된 Private 필드는 클래스 외부에서 접근할 수 없으며, 클래스 내부에서만 접근 가능합니다. Private 필드는 # 기호로 정의됩니다.

class Person {
  #ssn;

  constructor(name, ssn) {
    this.name = name;
    this.#ssn = ssn;
  }

  getSSN() {
    return this.#ssn;
  }
}

const john = new Person('John', '123-45-6789');
console.log(john.name);   // John
console.log(john.getSSN()); // 123-45-6789
console.log(john.#ssn);   // SyntaxError: Private field '#ssn' must be declared in an enclosing class
  • # 기호를 사용하여 Private 필드를 정의합니다.
  • Private 필드는 클래스 내부에서만 접근 가능하며, 외부에서 직접 접근할 수 없습니다.

6. Getter와 Setter

ES6 클래스는 객체의 속성에 접근할 때 실행되는 메서드를 정의할 수 있는 getset 키워드를 지원합니다.

class Rectangle {
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  get area() {
    return this.width * this.height;
  }

  set area(value) {
    console.log('Cannot set area directly. Please set width and height instead.');
  }
}

const rect = new Rectangle(10, 5);
console.log(rect.area); // 50
rect.area = 60;         // Cannot set area directly. Please set width and height instead.
  • get 키워드를 사용하여 속성 접근자 메서드를 정의합니다.
  • set 키워드를 사용하여 속성 설정자 메서드를 정의합니다.
  • get 메서드는 속성에 접근할 때 실행되며, set 메서드는 속성에 값을 할당할 때 실행됩니다.

7. 클래스 표현식

클래스는 선언식 외에도 표현식으로 정의할 수 있습니다.

const Person = class {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

const alice = new Person('Alice');
alice.greet(); // Hello, my name is Alice
  • 클래스 표현식은 변수에 할당되거나 즉시 사용될 수 있습니다.

8. 추상 클래스 및 메서드

자바스크립트에는 추상 클래스와 추상 메서드를 지원하는 직접적인 문법은 없지만, 추상 클래스처럼 동작하도록 구현할 수 있습니다. 이는 주로 상속받은 클래스가 특정 메서드를 반드시 구현하도록 강제할 때 사용됩니다.

class Animal {
  constructor(name) {
    if (new.target === Animal) {
      throw new TypeError('Cannot construct Animal instances directly');
    }
    this.name = name;
  }

  speak() {
    throw new Error('Method "speak" must be implemented');
  }
}

class Dog extends Animal {
  speak() {
    console.log(`${this.name} barks.`);
  }
}

const dog = new Dog('Rex');
dog.speak(); // Rex barks.

const animal = new Animal('Unknown'); // Error: Cannot construct Animal instances directly
  • new.target을 사용하여 특정 클래스의 인스턴스를 직접 생성하는 것을 방지할 수 있습니다.
  • 메서드 내부에서 throw new Error를 사용하여 추상 메서드처럼 동작하게 할 수 있습니다.

9. 클래스 믹스인(Mixin)

클래스 믹스인은 여러 클래스로부터 기능을 합성할 수 있는 패턴입니다.

const CanEat = {
  eat() {
    console.log('Eating');
  }
};

const CanWalk = {
  walk() {
    console.log('Walking');
  }
};

class Person {
  constructor(name) {
    this.name = name;
  }
}

// 믹스인 함수
function applyMixins(target, mixins) {
  mixins.forEach(mixin => {
    Object.assign(target.prototype, mixin);
  });
}

applyMixins(Person, [CanEat, CanWalk]);

const person = new Person('John');
person.eat(); // Eating
person.walk(); // Walking
  • Object.assign을 사용하여 믹스인 객체의 메서드를 클래스 프로토타입에 복사합니다.

결론

ES6 클래스는 자바스크립트에서 객체 지향 프로그래밍을 구현하는 데 있어 강력하고 직관적인 문법을 제공합니다. 클래스를 사용하여 객체를 정의하고 상속을 구현함으로써 코드의 재사용성을 높이고 유지보수를 용이하게 할 수 있습니다. 프로토타입 기반의 기존 자바스크립트 상속 방식을 더 읽기 쉽고 사용하기 편리하게 만들어 주는 ES6 클래스 문법을 통해 더 효율적인 프로그래밍을 할 수 있습니다.

Leave a Reply

Your email address will not be published. Required fields are marked *