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 클래스는 객체의 속성에 접근할 때 실행되는 메서드를 정의할 수 있는 get
과 set
키워드를 지원합니다.
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 클래스 문법을 통해 더 효율적인 프로그래밍을 할 수 있습니다.