자바스크립트는 기능적, 객체 지향적, 명령형 프로그래밍 스타일을 모두 활용하여 코드를 작성할 수 있는 다재다능한 언어입니다. 이러한 다양한 프로그래밍 패러다임을 지원하는 것이 특징입니다.
특히 객체 지향 프로그래밍(OOP)의 핵심 요소인 클래스는 자바스크립트에서도 중요한 역할을 합니다. 본 문서에서는 자바스크립트 클래스의 개념과 사용법에 대해 자세히 알아보는 시간을 갖도록 하겠습니다.
자바스크립트 클래스란 무엇인가?
객체 지향 프로그래밍에서는 시스템을 상호 작용하는 객체들의 집합으로 모델링합니다. 객체는 고유한 속성(데이터 저장)과 메서드(작업 수행)를 가지며, 이러한 객체들의 상호작용을 통해 시스템의 기능을 구현합니다. 클래스는 바로 이러한 객체들을 생성하기 위한 일종의 설계도와 같습니다. 즉, 동일한 유형의 객체가 공유하는 속성과 메서드를 정의하는 역할을 합니다.
클래스 관련 용어 정리
클래스를 효과적으로 이해하기 위해, 본문에서 사용되는 주요 용어들을 먼저 정리해 보겠습니다. 객체 지향 프로그래밍에 익숙하신 분이라면 다음 섹션으로 바로 넘어가셔도 좋습니다.
❇️ 클래스: 객체를 생성하기 위한 템플릿입니다. 클래스를 통해 특정 유형의 객체를 만들 수 있으며, 이를 ‘인스턴스화’라고 합니다.
❇️ 클래스 멤버: 클래스에 속하는 모든 구성 요소를 통칭하며, 속성과 메서드의 두 가지 종류가 있습니다.
❇️ 속성: 클래스 내에서 데이터를 저장하는 데 사용되는 멤버입니다. 숫자, 문자열과 같은 기본 값은 물론, 복잡한 객체나 배열도 저장할 수 있습니다.
❇️ 접근 제어: 속성은 클래스 내부에서만 접근 가능한 ‘개인 속성’과 클래스 내/외부에서 모두 접근 가능한 ‘공개 속성’으로 나뉩니다.
❇️ 메서드: 클래스 내부에 정의된 함수로, 클래스에 속하며 공용 및 개인 속성에 접근할 수 있습니다. 속성과 마찬가지로 공개 메서드와 비공개 메서드로 구분됩니다.
❇️ Getter 및 Setter: 클래스 외부에서 클래스 속성에 접근하고 값을 변경할 수 있도록 인터페이스를 제공하는 특별한 메서드입니다. Getter는 속성 값을 반환하고, Setter는 속성 값을 설정합니다.
❇️ 정적 멤버: 클래스 자체에 속하며, 클래스의 인스턴스를 생성하지 않고도 클래스 이름으로 직접 접근할 수 있는 멤버입니다.
❇️ 비정적 멤버: 클래스의 인스턴스에 속하며, 클래스를 인스턴스화한 후에만 접근할 수 있는 멤버입니다.
❇️ 생성자: 클래스를 인스턴스화할 때 자동으로 호출되는 특수 메서드로, 인스턴스의 속성을 초기화하는 데 사용됩니다.
클래스 인스턴스화
자바스크립트에서 클래스를 인스턴스화하려면 ‘new’ 키워드와 클래스 이름을 함께 사용합니다. 예를 들어, Array 클래스를 인스턴스화하는 방법은 다음과 같습니다.
const myArr = new Array()
자바스크립트에서 클래스 생성하기
이제 위에서 살펴본 클래스 관련 개념들을 실제로 구현하여 클래스를 생성하는 방법에 대해 알아보겠습니다. 아래 예제들은 이전 예제들을 기반으로 점진적으로 발전하는 형태로 구성되어 있습니다. 용어 설명 섹션을 참고하시면 이해에 도움이 될 것입니다.
빈 클래스 선언
자바스크립트에서 클래스를 선언하려면 ‘class’ 키워드를 사용하고 클래스 이름을 지정합니다. 클래스 본체는 중괄호({})로 감싸며, 클래스 멤버를 정의합니다. 빈 클래스 선언은 다음과 같습니다.
class Dog { }
이 클래스를 인스턴스화하고 콘솔에 출력하면 다음과 같습니다.
const pet = new Dog; console.log(pet);
공개 속성 생성
공개 속성은 식별자와 선택적 초기값으로 정의됩니다.
class Dog { name = "Roy"; age; }
위 예제에서는 ‘name’ 속성을 문자열 값으로 초기화하고, ‘age’ 속성은 값 없이 정의했습니다.
const pet = new Dog(); console.log(pet.name); console.log(pet.age);
공개 메서드 정의
클래스 본체 내부에 메서드를 추가할 수 있습니다. 함수를 정의하는 방식과 유사하지만, ‘function’ 키워드는 생략합니다.
class Dog { name = "Roy"; age; walk () { console.log("Walking"); } }
위의 예에서는 ‘walk’ 메서드를 정의했습니다. Dog 클래스의 모든 인스턴스는 이 메서드를 가집니다.
const pet = new Dog(); pet.walk();
메서드 내부에서 속성 접근
자바스크립트에서는 객체의 속성에 접근할 때 점(.) 연산자를 사용합니다. 예를 들어 ‘person’이라는 객체의 ‘name’ 속성에 접근하려면 ‘person.name’과 같이 사용합니다. 하지만 객체 내부에서 속성에 접근할 때는 객체 이름 대신 ‘this’ 키워드를 사용합니다. ‘this.name’과 같이 사용하면 됩니다. ‘this’ 키워드는 현재 객체(인스턴스)를 참조합니다. 클래스 메서드 내부에서 클래스 속성에 접근하려면 ‘this.속성이름’ 구문을 사용해야 합니다.
개인 속성 생성
이전에 정의한 ‘name’과 ‘age’ 속성을 개인 속성으로 변경해 보겠습니다. 클래스를 다음과 같이 수정합니다.
class Dog { #name = "Roy"; #age; walk () { console.log("Walking"); } }
개인 속성은 ‘#’ 기호를 사용하여 정의합니다. 개인 속성에 직접 접근하려고 하면 오류가 발생합니다.
const dog = new Dog(); dog.#name
Getter 및 Setter 메서드 생성
이제 클래스의 ‘name’과 ‘age’ 속성은 비공개 상태입니다. 클래스 외부에서는 이 속성들에 직접 접근할 수 없으므로, 클래스 내부의 메서드를 통해서만 접근이 가능합니다. 클래스 외부에서도 이 속성들에 접근할 수 있도록 Getter와 Setter 메서드를 정의해 보겠습니다. ‘name’ 속성에 대한 Getter와 Setter 메서드는 다음과 같습니다.
class Dog { #name = "Roy"; #age; get name () { return this.#name; } set name (value) { this.#name = value; } walk () { console.log("Walking"); } }
위에서 정의된 클래스를 사용하여 ‘name’ 속성을 설정하고 출력하는 방법은 다음과 같습니다.
const pet = new Dog(); // Setting the name pet.name = "Rex"; // Getting the name console.log(pet.name);
비공개 메서드 생성
비공개 속성과 마찬가지로, 비공개 메서드도 ‘#’ 기호를 앞에 붙여 정의합니다. 비공개 메서드 선언 방법은 다음과 같습니다.
class Dog { #name = "Roy"; #age; get name () { return this.#name; } set name (value) { this.#name = value; } #increaseAge() { this.#age ++; } #decreaseAge () { this.#age --; } walk () { console.log("Walking"); } }
클래스 외부에서 비공개 메서드에 접근하려고 하면 작동하지 않습니다.
const pet = new Dog(); pet.#increaseAge();
생성자 메서드 생성
클래스에는 생성자 메서드를 정의할 수 있습니다. 생성자 메서드는 클래스의 인스턴스를 생성할 때마다 자동으로 호출됩니다. 생성자 메서드를 사용하여 클래스 속성을 초기화할 수 있습니다. 아래 예제에서는 사용자가 인스턴스화 시점에 제공하는 인수에 따라 이름과 나이를 초기화합니다.
class Dog { #name; #age; constructor (name = "Dog", age = 0) { this.#name = name; this.#age = age; } get name () { return this.#name; } set name (value) { this.#name = value; } #increaseAge() { this.#age ++; } #decreaseAge () { this.#age --; } walk () { console.log("Walking"); } }
클래스를 인스턴스화할 때 이름과 나이를 제공할 수 있습니다.
const pet = new Dog('Roy', 3); console.log(pet.name);
정적 속성 및 메서드 생성
앞서 언급했듯이, 정적 멤버는 클래스를 인스턴스화하지 않고도 클래스 이름으로 직접 접근할 수 있습니다. 다음 예제에서는 정적 속성과 메서드를 생성합니다.
class Dog { #name; #age; static genus = "Canis"; constructor (name = "Dog", age = 0) { this.#name = name; this.#age = age; } static bark() { console.log("Woof"); } get name () { return this.#name; } set name (value) { this.#name = value; } #increaseAge() { this.#age ++; } #decreaseAge () { this.#age --; } walk () { console.log("Walking"); } }
이제 인스턴스화 없이 정적 속성과 메서드에 접근할 수 있습니다.
console.log(Dog.genus); Dog.bark();
상속
클래스는 다른 클래스로부터 속성을 상속받을 수 있습니다. 다른 클래스의 멤버를 상속받는 클래스를 ‘슈퍼클래스’라고 하고, 멤버를 상속받는 클래스를 ‘서브클래스’ 또는 ‘파생 클래스’라고 합니다. 자바스크립트에서 슈퍼클래스를 생성하려면 ‘extends’ 키워드를 사용합니다. 다음은 ‘Dog’ 클래스에서 상속받은 예입니다.
class Rottweiler extends Dog { constructor (name, age) { super(name, age); this.breed = 'rottweiler'; } }
보시다시피 클래스 정의는 이전과 거의 동일하지만, 생성자 내부에서 ‘super’ 함수를 호출했습니다. ‘super’ 키워드는 기본 클래스의 생성자를 참조합니다. 슈퍼클래스 내부에서 기본 클래스의 생성자를 호출하여 이름과 나이를 전달했습니다.
const myPet = new Rottweiler(); console.log(myPet);
결론
본 문서에서는 자바스크립트 클래스에 대해 자세히 살펴보았습니다. 클래스가 무엇인지, 클래스가 가질 수 있는 멤버, 멤버에 대한 다양한 분류 등을 다루었습니다. 또한, 다양한 예제를 통해 이러한 개념들을 실제로 구현하는 방법을 설명했습니다.
다음으로는 객체 지향 프로그래밍 관련 인터뷰 질문들을 학습해 보시기 바랍니다.