Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript 클래스 완벽 가이드: 기초 개념부터 상속까지

JavaScript는 프로토타입(prototype) 기반 언어입니다. 객체를 선언할 때마다 해당 객체에 연결된 속성과 메서드를 확장하는 프로토타입 속성이 자동으로 생성됩니다.

지난 몇 년간 많은 JavaScript 개발자들이 자신의 코드에 객체 지향 설계를 도입하는 방법을 모색해 왔습니다. 그 결과 프로토타입을 확장하는 새로운 유형의 객체인 '클래스(class)'가 등장하게 되었습니다.

이 가이드에서는 클래스가 무엇인지, 왜 사용되는지, 그리고 여러분의 코드에서 클래스를 어떻게 구현할 수 있는지 살펴보겠습니다. 실제 예제를 통해 클래스를 시작하는 방법도 함께 알아봅니다.

JavaScript 클래스란?

클래스는 객체의 템플릿을 선언하는 방식입니다.

객체 지향 프로그래밍 언어에 익숙하다면 이러한 언어들이 클래스와 객체에 크게 의존한다는 점을 알고 있을 것입니다. 클래스는 일종의 데이터 청사진(blueprint)과 같아서, 어떤 데이터를 저장할 수 있는지 그리고 어떤 메서드에 접근할 수 있는지 정의합니다. 객체는 그 클래스의 인스턴스(instance)입니다.

예를 들어 Book이라는 클래스가 있다고 가정해 봅시다. 이 클래스에는 책에 저장할 수 있는 정보와 그 데이터를 변경하는 방법에 대한 청사진이 담겨 있습니다. 그리고 '욕망이라는 이름의 전차(A Streetcar Named Desire)'라는 객체는 개별적인 한 권의 책이 되는 것이죠.

JavaScript에서 클래스는 소위 '문법 설탕(syntactic sugar)'이라고 불립니다. 클래스 문법은 매우 편리하지만, 반드시 새로운 기능을 추가하는 것은 아닙니다.

클래스는 React나 Next.js 같은 현대적인 JavaScript 프레임워크에서 널리 사용되고 있습니다.

클래스 vs 함수

이 글에서 딱 한 가지만 기억한다면 다음 사항을 기억하세요. 바로 클래스는 평범한 함수라는 점입니다.

클래스와 함수 표현식의 유일한 차이점은 선언 방식입니다. 함수는 function 키워드를 사용하고, 클래스는 class 키워드를 사용합니다. 기술적으로는 class 키워드 없이도 클래스를 선언할 수 있습니다.

두 개의 함수를 만들고 프로토타입을 출력해 보면 두 가지가 동일하다는 것을 확인할 수 있습니다:

const PlayerFunction = function() {}
const PlayerClass = class {}

console.log(Object.getPrototypeOf(PlayerFunction));
console.log(Object.getPrototypeOf(PlayerClass));

클래스 표현식과 함수는 다음과 같은 결과를 반환합니다:

function ()
function ()

함수와 클래스 모두 동일한 프로토타입 기반 아키텍처를 사용합니다.

클래스 정의하는 방법

그렇다면 클래스는 어떻게 정의할까요?

class 키워드를 사용하여 클래스를 정의할 수 있습니다. 클래스를 정의한 후에는 constructor() 함수를 사용해 기본값으로 초기화할 수 있습니다.

JavaScript 콘솔을 열고 다음 코드를 붙여넣어 보세요:

class Book {
  constructor(title, author) {
    this.title = title;
    this.author = author;
  }
}

위 코드는 Book이라는 클래스를 생성합니다. 이 클래스는 생성자(constructor) 메서드에서 정의한 title과 author 두 값을 저장할 수 있습니다. 이 클래스의 객체를 만들려면 다음 코드를 사용하면 됩니다:

var streetcar = new Book("A Streetcar Named Desire", "Tennessee Williams");

일반 객체에서 값을 가져오듯이 클래스에서도 값을 조회할 수 있습니다:

console.log(streetcar.title);

코드 실행 결과: A Streetcar Named Desire

클래스 메서드 정의하기

프로토타입 대신 클래스를 사용할 때의 장점 중 하나는 클래스 내부에 메서드를 선언할 수 있다는 점입니다. 즉, 기존 함수에 새로운 메서드를 추가하기 위해 prototype 문법을 사용할 필요가 없습니다.

다음 예제를 살펴보세요:

class Book {
  constructor(title, author) {
    this.title = title;
    this.author = author;
  }

  getDetails() {
    console.log(`${this.title} is a book written by ${this.author}.`);
  }
}

클래스 내부에 존재하는 getDetails()라는 메서드를 선언했습니다. 모든 코드가 한곳에 모여 있기 때문에 코드 관리가 훨씬 수월합니다. 이제 getDetails() 함수를 호출해 보겠습니다:

var streetcar = new Book("A Streetcar Named Desire", "Tennessee Williams");
streetcar.getDetails();

코드 실행 결과:

A Streetcar Named Desire is a book written by Tennessee Williams.

클래스 상속

다른 객체 지향 구조와 마찬가지로 클래스도 다른 클래스로부터 속성을 상속받을 수 있습니다.

상속(inheritance)이란 자식 클래스가 부모 클래스의 메서드와 데이터에 접근할 수 있는 과정을 말합니다. 클래스를 상속받으려면 extends 키워드를 사용하면 됩니다. JavaScript 파일을 만들거나 콘솔을 열어 다음 코드를 입력해 보세요:

class Fiction extends Book {
  constructor(title, author, fiction) {
    super(title, author);

    this.fiction = true;
  }
}

앞서 선언한 Book 클래스를 청사진으로 사용하는 Fiction 클래스를 만들었습니다. 코드에서 super() 키워드를 사용하여 부모 클래스인 Book으로부터 title과 author 값을 상속받았습니다. 그런 다음 기본값이 true로 설정되는 새로운 속성 fiction을 정의했습니다.

새로운 Fiction 클래스의 객체를 만들어 보겠습니다:

var gatsby = new Fiction("The Great Gatsby", "F. Scott Fitzgerald");
console.log(gatsby.fiction);

코드 실행 결과: true. Fiction 클래스는 기본적으로 true인 fiction 항목을 저장합니다. 만약 Book 클래스의 인스턴스에서 이 값에 접근하려고 하면 아무것도 반환되지 않습니다. 'fiction'은 오직 Fiction 클래스에서만 접근 가능하기 때문입니다.

게터(Getter)와 세터(Setter)

클래스를 다룰 때는 게터(getter)와 세터(setter) 함수를 활용하는 것이 좋습니다.

게터 함수는 클래스의 값을 조회할 수 있게 해주고, 세터 함수는 클래스 내 특정 항목의 값을 변경할 수 있게 해줍니다. 각각 getset 키워드로 표시됩니다.

다음 코드를 살펴보세요:

class Book {
  constructor(title, author) {
    this.title = title;
    this.author = author;
  }

  get author() {
    return this.author;
  }

  set author(author) {
    this.author = author;
  }
}

이 예제에서는 author라는 두 개의 메서드를 선언했습니다. 하나는 author 값을 조회하는 게터 메서드이고, 다른 하나는 author 값을 변경하는 세터 메서드입니다.

다음 코드로 직접 확인해 볼 수 있습니다:

var streetcar = new Book("A Streetcar Named Desire", "");
streetcar.author = "Tennessee Williams";
console.log(streetcar.author);

코드 실행 결과: Tennessee Williams

streetcar라는 객체를 초기화하고 제목을 'A Streetcar Named Desire'로 지정했습니다. 그다음 코드에서 정의한 세터를 사용해 author 값을 'Tennessee Williams'로 설정했습니다. 마지막으로 게터 메서드를 통해 author 값을 콘솔에 출력했습니다.

마무리

클래스는 JavaScript에 새로운 기능을 추가하지는 않지만, 객체 지향 프로그래밍에 익숙한 개발자에게는 함수를 더 이해하기 쉽게 작성할 수 있도록 도와줍니다.

클래스는 JavaScript의 프로토타입 기반 설계를 추상화하여 더 객체 지향적으로 보이게 만듭니다. 여기서 '보이게'라는 단어가 중요합니다. 클래스는 결국 함수이며, 문법 설탕 이상도 이하도 아니기 때문입니다.

이제 여러분도 JavaScript 전문가처럼 클래스를 활용할 준비가 되었습니다!