-
[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를 사용하지 않고
객체 리터럴을 사용하는 것이 더 간단하고 효율적이다.
'javascript' 카테고리의 다른 글
[Javascript] 코딩 테스트에서 자주 사용되는 메소드 정리 (0) 2024.09.21 [javascript] Map VS Object_Map Object 차이점 (5) 2024.09.07 [Javascript] element.style VS getComputedStyle (0) 2024.03.04 [Javascript] insertAdjacentHTML (0) 2023.01.30 [Javascript] JSDoc (0) 2022.10.26