frontend/javascript

🟨 1-13. ES6 클래스(Class)와 프로토타입(Prototype) — 객체지향 자바스크립트의 핵심 구조

mirabo01 2025. 11. 6. 22:11

1. 객체지향 프로그래밍이란?

프로그래밍 언어에는 여러 패러다임이 있다.
그중 하나가 객체지향 프로그래밍(OOP, Object-Oriented Programming).

핵심 개념은 단순하다.

“데이터와 기능을 하나의 객체로 묶어서 관리하자.”

예를 들어, 단순히 사용자 이름과 인사 기능을 따로 두는 대신,
그 둘을 하나의 객체로 묶어두는 것이다.

const user = {
  name: "기범",
  greet() {
    console.log(`안녕하세요, ${this.name}입니다.`);
  },
};

user.greet(); // 안녕하세요, 기범입니다.

이런 객체가 여러 개 필요할 때,
하나씩 수동으로 만드는 대신 템플릿(설계도) 로 찍어내는 게 바로 클래스의 역할이다.


2. 클래스(Class)의 기본 구조

ES6 이전에는 클래스를 직접 지원하지 않았다.
그 대신 함수(Function)프로토타입(Prototype) 으로 비슷한 기능을 구현했다.

하지만 ES6 이후부터는 공식적으로 class 문법이 추가되어 훨씬 직관적으로 작성할 수 있다.

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  greet() {
    console.log(`안녕하세요, ${this.name} (${this.age}세)입니다.`);
  }
}

const me = new Person("기범", 27);
me.greet(); // 안녕하세요, 기범 (27세)입니다.

여기서 중요한 포인트는 다음 세 가지다.

  1. constructor()는 객체가 생성될 때 자동 실행되는 초기화 메서드
  2. this는 생성된 인스턴스(instance) 자신을 가리킨다
  3. 클래스 내부의 메서드는 자동으로 프로토타입 메서드로 등록된다

3. 인스턴스(Instance)란 무엇인가

class는 단순히 설계도일 뿐이다.
실제 메모리에 존재하는 것은 인스턴스다.

const a = new Person("민수", 30);
const b = new Person("지현", 25);

console.log(a.name); // 민수
console.log(b.name); // 지현

즉, new 키워드를 사용해야 실제 객체가 만들어진다.
각 인스턴스는 고유한 속성을 가지며, 클래스에 정의된 메서드를 공유한다.


4. 클래스의 상속(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(); // 해피가 멍멍 짖습니다.

자식 클래스는 extends 키워드로 부모를 상속받는다.
super()를 사용하면 부모의 생성자나 메서드에 접근할 수 있다.

class Cat extends Animal {
  constructor(name, color) {
    super(name);
    this.color = color;
  }
  info() {
    console.log(`${this.color} 고양이 ${this.name}`);
  }
}

상속은 중복 코드를 줄이고,
공통 기능을 상위 클래스에서 한 번만 정의할 수 있게 해준다.


5. 프로토타입(Prototype)의 개념

자바스크립트의 클래스는 사실 프로토타입 기반(prototype-based) 문법의 문법적 설탕(syntax sugar)이다.

즉, class 문법은 내부적으로 다음과 같은 코드로 동작한다.

function Person(name) {
  this.name = name;
}
Person.prototype.greet = function() {
  console.log(`안녕하세요, ${this.name}입니다.`);
};

const me = new Person("기범");
me.greet();

여기서 Person.prototype이 바로 프로토타입 객체다.
모든 인스턴스는 이 객체를 참조하고, 메서드를 공유한다.

즉, me는 실제로 me.__proto__ → Person.prototype을 참조한다.
이런 구조를 프로토타입 체인(prototype chain) 이라고 부른다.


6. 프로토타입 체인 (Prototype Chain)

프로토타입 체인은 객체의 상속 관계를 결정하는 메커니즘이다.
자바스크립트에서 어떤 속성이나 메서드를 찾을 때의 순서는 다음과 같다.

  1. 인스턴스 자신에게 존재하는가?
  2. 없다면 __proto__ (즉, prototype)에 존재하는가?
  3. 거기에도 없으면 Object.prototype까지 탐색
const arr = [1, 2, 3];
console.log(arr.toString()); // "1,2,3"

// 실제 동작 구조
// arr.__proto__ → Array.prototype
// Array.prototype.__proto__ → Object.prototype

이런 연결 덕분에 모든 객체가 toString(), hasOwnProperty() 같은 공통 메서드를 쓸 수 있다.


7. 정적 메서드 (Static Method)

클래스에 따라서는 인스턴스가 아니라
클래스 자체에서만 사용하는 메서드가 필요할 때가 있다.

그럴 때 static 키워드를 사용한다.

class Calculator {
  static add(a, b) {
    return a + b;
  }
}

console.log(Calculator.add(3, 5)); // 8

이런 메서드는 new로 생성한 객체에서는 접근할 수 없다.


8. private / public 필드

ES2022부터는 클래스 필드에 접근 제한자를 사용할 수 있다.
#으로 시작하는 속성은 외부에서 접근할 수 없는 비공개(private) 필드다.

class Account {
  #balance = 0;

  deposit(amount) {
    this.#balance += amount;
  }

  getBalance() {
    return this.#balance;
  }
}

const myAcc = new Account();
myAcc.deposit(1000);
console.log(myAcc.getBalance()); // 1000
console.log(myAcc.#balance); // ❌ SyntaxError

이 기능은 객체지향의 핵심 원칙인 캡슐화(encapsulation) 를 언어 차원에서 지원한다.


9. 클래스와 프로토타입의 관계 시각화

[Person 클래스]
   │
   ▼
[Person.prototype]  ← 클래스의 메서드가 여기에 저장
   │
   ▼
[me 인스턴스]  ← __proto__로 연결됨
   │
   ▼
[Object.prototype]

즉, class는 함수와 프로토타입을 자동으로 연결해주는 편의 문법일 뿐,
자바스크립트의 본질은 여전히 “프로토타입 기반 상속”이다.


10. 실무 예시 — 컴포넌트 클래스

클래스는 단순한 문법이 아니라,
React, Vue, 게임 엔진, Node.js 서버 구조 등에서 핵심적인 추상화 도구로 쓰인다.

예를 들어 간단한 UI 컴포넌트를 클래스로 표현할 수 있다.

class Button {
  constructor(label) {
    this.label = label;
  }

  render() {
    const el = document.createElement("button");
    el.textContent = this.label;
    document.body.appendChild(el);
  }
}

const loginBtn = new Button("로그인");
loginBtn.render();

이런 방식은 React의 “class component”와 거의 동일한 개념이다.


11. 클래스 vs 프로토타입 직접 비교

구분 클래스(Class) 프로토타입(Prototype)

문법 ES6 표준 문법 기존 자바스크립트 방식
사용성 직관적, 선언적 함수와 객체로 구현
상속 extends로 지원 Object.create()로 구현
접근 제어 private/public 필드 가능 직접 제어 어려움
내부 구조 결국 프로토타입 기반 클래스 문법의 근간

즉, class는 “더 읽기 좋은 프로토타입”이다.


12. 마무리

자바스크립트는 자바나 C++처럼 전통적인 객체지향 언어가 아니다.
그러나 프로토타입 기반의 유연한 상속 구조 덕분에
필요한 만큼 객체지향 패턴을 구현할 수 있다.

  • 클래스는 설계도, 인스턴스는 그 결과물
  • 프로토타입은 연결고리, 클래스는 그 위의 문법적 설탕
  • 상속, 캡슐화, 재사용성 모두 클래스 문법으로 구현 가능

자바스크립트의 클래스는 문법이 아니라 ‘개념의 가시화’다.
보이지 않던 프로토타입 체인을 읽기 쉽게 만들어 준 것이다.


다음 편에서는
1-14. 비공개 데이터, 캡슐화, 상속 구조 설계 — 객체지향을 실무적으로 적용하는 법
을 통해 실제 코드 설계 단계에서 클래스와 상속을 어떻게 안전하게 관리하는지,
그리고 private 필드, getter/setter, 추상화 패턴을 조합해보자.