1. 클래스란 무엇인가
클래스(Class)는 객체를 만들기 위한 청사진(템플릿) 이다.
다른 언어(Java, C++)에서는 원래부터 존재하던 개념이지만,
자바스크립트는 2015년(ES6) 이후에 문법적으로 추가되었다.
class User {
constructor(name) {
this.name = name;
}
sayHi() {
console.log(`안녕, 나는 ${this.name}`);
}
}
const kb = new User("기범");
kb.sayHi(); // 안녕, 나는 기범
✅ constructor는 객체가 생성될 때 자동 실행되는 생성자 함수
✅ 클래스 내부 메서드는 User.prototype에 저장된다
✅ 즉, 클래스는 “보기 좋은 프로토타입 문법”이다
2. 클래스와 프로토타입의 관계
위 코드는 내부적으로 다음과 동일하게 동작한다 👇
function User(name) {
this.name = name;
}
User.prototype.sayHi = function () {
console.log(`안녕, 나는 ${this.name}`);
};
즉, 클래스는 사실상 다음 구조를 자동으로 만들어준다.
구성요소 실제 역할
| constructor | 생성자 함수 |
| 메서드 | prototype에 저장됨 |
| new 호출 | 인스턴스 생성 + 프로토타입 연결 |
이 때문에 클래스 문법을 이해하려면 프로토타입 체인을 먼저 알아야 하는 것이다.
3. 클래스의 주요 특징
✅ 클래스는 호이스팅되지 않는다
const user = new User(); // ❌ ReferenceError
class User {}
클래스 선언은 TDZ(Temporal Dead Zone) 내에 있기 때문에
함수처럼 위에서 호출할 수 없다.
✅ strict mode가 자동 적용
클래스 내부의 모든 코드는 자동으로 'use strict' 모드에서 실행된다.
즉, this가 undefined로 처리되는 등 보다 안전한 실행 환경을 가진다.
4. 클래스의 상속 (extends)
클래스의 진정한 힘은 상속 구조에 있다.
class Animal {
constructor(name) {
this.name = name;
}
move() {
console.log(`${this.name}이(가) 움직인다`);
}
}
class Dog extends Animal {
bark() {
console.log(`${this.name}이(가) 멍멍 짖는다`);
}
}
const choco = new Dog("초코");
choco.move(); // 초코이(가) 움직인다
choco.bark(); // 초코이(가) 멍멍 짖는다
✅ extends는 내부적으로 Dog.prototype.__proto__ = Animal.prototype
✅ 즉, 프로토타입 상속을 자동으로 구성해준다
5. super() — 부모 클래스 생성자 호출
super()는 상속 관계에서 부모 클래스의 생성자(constructor) 를 호출한다.
class Animal {
constructor(name) {
this.name = name;
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // 부모 생성자 호출
this.breed = breed;
}
}
const max = new Dog("맥스", "리트리버");
console.log(max.name, max.breed); // 맥스 리트리버
✅ super()는 this보다 먼저 호출해야 한다
✅ 부모 클래스의 속성을 자식이 안전하게 상속받는 구조
6. 메서드 오버라이딩
자식 클래스에서 부모의 메서드를 재정의할 수 있다.
class Animal {
speak() {
console.log("소리를 낸다");
}
}
class Cat extends Animal {
speak() {
super.speak();
console.log("야옹!");
}
}
const kitty = new Cat();
kitty.speak();
// 소리를 낸다
// 야옹!
✅ super.speak()로 부모 메서드 실행 후 확장 가능
✅ “확장 가능한 상속 구조” 구현 가능
7. 정적 메서드 (static)
클래스의 인스턴스가 아닌 클래스 자체에 직접 연결되는 메서드를 만들 수 있다.
class MathUtil {
static add(a, b) {
return a + b;
}
}
console.log(MathUtil.add(5, 3)); // 8
✅ 인스턴스 없이 호출 가능
✅ 보통 유틸리티, 헬퍼, 팩토리 함수 등에 사용
8. 필드(Field) 선언과 초기화
ES2022 이후로, 클래스 내부에서 바로 속성을 정의할 수 있다.
class Counter {
count = 0; // 클래스 필드
increase() {
this.count++;
console.log(this.count);
}
}
const c = new Counter();
c.increase(); // 1
✅ 생성자 없이도 필드 정의 가능
✅ React, Vue 등에서 클래스형 컴포넌트의 기본 구조로 자주 쓰임
9. private 필드 (#)
ES2022부터 클래스에는 진짜 비공개 변수(private field) 를 지원한다.
class BankAccount {
#balance = 0;
deposit(amount) {
this.#balance += amount;
console.log(`입금 완료: 현재 잔액은 ${this.#balance}원`);
}
getBalance() {
return this.#balance;
}
}
const account = new BankAccount();
account.deposit(10000);
console.log(account.getBalance()); // 10000
console.log(account.#balance); // ❌ SyntaxError
✅ #으로 선언된 변수는 외부 접근 불가
✅ 진정한 의미의 캡슐화(Encapsulation) 구현 가능
10. Getter / Setter
Getter와 Setter를 사용하면
속성 접근처럼 보이지만, 실제로는 함수 로직을 실행시킬 수 있다.
class Product {
constructor(name, price) {
this.name = name;
this._price = price;
}
get price() {
return this._price + "원";
}
set price(value) {
if (value < 0) throw new Error("가격은 0 이상이어야 합니다.");
this._price = value;
}
}
const item = new Product("커피", 3000);
console.log(item.price); // 3000원
item.price = 5000;
console.log(item.price); // 5000원
✅ 내부 로직을 속성 접근처럼 처리할 수 있어 직관적
✅ 데이터 유효성 검사 및 포맷팅에 자주 사용
11. 클래스와 화살표 함수의 조합
클래스 내부에서 화살표 함수를 쓰면
자동으로 this가 인스턴스에 바인딩된다.
class Button {
constructor(label) {
this.label = label;
}
handleClick = () => {
console.log(`${this.label} 버튼 클릭됨`);
};
}
const btn = new Button("확인");
document.body.addEventListener("click", btn.handleClick);
✅ bind() 없이도 this가 유지
✅ React 클래스형 컴포넌트에서 매우 자주 사용되는 패턴
12. 클래스 vs 함수 생성자 비교
구분 클래스 생성자 함수
| 문법 | class 키워드 | function 키워드 |
| 상속 | extends, super() | Object.create(), call() |
| 캡슐화 | private field 지원 | 불가능 |
| this 바인딩 | 명확함 | 함수 컨텍스트에 따라 다름 |
| 호이스팅 | 불가능 | 가능 |
| 코드 가독성 | 높음 | 낮음 |
13. 실무 예제 — 사용자 인증 시스템
class User {
constructor(name, role = "guest") {
this.name = name;
this.role = role;
}
login() {
console.log(`${this.name}님이 로그인했습니다.`);
}
}
class Admin extends User {
constructor(name) {
super(name, "admin");
}
deleteUser(user) {
console.log(`${user.name}님이 삭제되었습니다.`);
}
}
const kb = new Admin("기범");
const user1 = new User("민수");
kb.login(); // 기범님이 로그인했습니다.
kb.deleteUser(user1); // 민수님이 삭제되었습니다.
✅ 클래스 상속을 이용해 역할(Role)별 로직을 구조화
✅ 실제 백엔드 사용자 모델에서도 거의 동일한 방식으로 사용
14. 정리
개념 설명
| 클래스(Class) | 객체 생성 템플릿, 프로토타입 기반 문법 |
| constructor | 인스턴스 초기화 메서드 |
| extends / super | 상속 및 부모 호출 |
| static | 클래스 단위 메서드 |
| private field | 정보 은닉 (#field) |
| getter/setter | 속성 접근 인터페이스 |
| this | 자동 바인딩(화살표 함수와 조합 시 유용) |
15. 마무리
클래스는 단순한 문법 편의가 아니라,
자바스크립트를 진짜 객체지향 언어로 확장시킨 도구다.
프로토타입의 복잡한 구조를 단순화하면서,
캡슐화·상속·다형성의 3대 원리를 완벽히 구현할 수 있게 되었지.
“프로토타입은 자바스크립트의 유전자이고,
클래스는 그 유전자가 만들어낸 생명체다.”
'frontend > javascript' 카테고리의 다른 글
| 🟨 2-22. 이벤트 루프와 비동기 흐름의 시각적 이해 — 브라우저의 내부 작동 구조 (0) | 2025.11.07 |
|---|---|
| 🟨 2-21. 비동기 프로그래밍 완전정복 — Promise, async/await, 그리고 이벤트 루프의 협업 구조 (0) | 2025.11.07 |
| 🟨 2-19. 프로토타입(Prototype) 완벽 가이드 — 자바스크립트 객체지향의 뼈대 구조 이해하기 (0) | 2025.11.07 |
| 🟨 2-18. 클로저(Closure) 완전 정복 — 함수형 자바스크립트의 핵심 개념과 실무 응용 (0) | 2025.11.07 |
| 🟨 2-17. this 완전 정복 — 함수, 객체, 클래스에서의 this 바인딩 규칙과 혼동 포인트 (0) | 2025.11.07 |