자바스크립트 교재 · 18편 / 26편

클래스와 객체지향 — class·extends·this

class 문법, 상속, getter/setter, #private 까지.

중급읽는 시간 7분2026-05-17
class 가 인스턴스를 만들고 상속이 이어지는 OOP 도식

JS 의 class 는 ES2015 부터의 표준 — 사실은 프로토타입(23편) 위의 문법적 설탕이지만, 사용자 입장에선 Java·Python 같은 모양. 18편은 class 의 모든 핵심 문법을 정리합니다. TS 8편 의 비교편으로 봐도 좋아요.

기본 형태

class User {
  // 필드 선언 (ES2022+)
  active = true;

  // 생성자
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  // 메서드
  greet() {
    return `Hi, ${this.name}!`;
  }

  // 정적 메서드 (클래스 자체에 붙음)
  static fromJSON(json) {
    return new User(json.name, json.age);
  }
}

const u = new User("준성", 39);
u.greet();              // "Hi, 준성!"
User.fromJSON({...});   // 정적

getter · setter — 메서드처럼 보이는 속성

class User {
  #firstName = "";
  #lastName = "";

  constructor(first, last) {
    this.#firstName = first;
    this.#lastName = last;
  }

  get fullName() {
    return `${this.#firstName} ${this.#lastName}`;
  }

  set fullName(value) {
    [this.#firstName, this.#lastName] = value.split(" ");
  }
}

const u = new User("준성", "박");
u.fullName;             // "준성 박" (메서드 호출 () 없음)
u.fullName = "준석 박";  // setter 호출
u.fullName;             // "준석 박"

#private — 진짜 비공개 필드 (ES2022+)

class Account {
  #balance = 0;           // # 접두사 — 진짜 private
  #pin;

  constructor(pin) {
    this.#pin = pin;
  }

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

  checkBalance(pin) {
    if (pin !== this.#pin) throw new Error("PIN 틀림");
    return this.#balance;
  }
}

const a = new Account("1234");
a.deposit(1000);
a.#balance;          // ❌ SyntaxError — 클래스 밖에선 접근 불가 (TS 의 private 와 달리 런타임 강제)

TS private vs JS #private. TS 의 private 는 컴파일 시점만 — 런타임에는 일반 속성처럼 우회 가능. JS 의 #field언어 차원의 진짜 비공개. 새 코드는 #field 권장.

extends · super — 상속

class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    return `${this.name} 가 소리냄`;
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name);          // 부모 생성자 호출 (필수, this 사용 전)
    this.breed = breed;
  }

  speak() {               // 오버라이드
    return `${this.name} 짖기!`;
  }

  describe() {
    return `${super.speak()} — 종: ${this.breed}`;
    //       ^ 부모 메서드 호출
  }
}

const d = new Dog("초코", "리트리버");
d.speak();                // "초코 짖기!"
d.describe();             // "초코 가 소리냄 — 종: 리트리버"

super() 호출 순서. 자식 constructor 에서 this 사용 전 반드시 super(). 안 하면 ReferenceError. extends 가 있으면 super 가 필수.

static — 클래스 레벨

class MathUtils {
  static PI = 3.14159;            // static 필드

  static circleArea(r) {           // static 메서드
    return MathUtils.PI * r * r;
  }

  // static block (ES2022) — 클래스 초기화
  static {
    console.log("MathUtils 로드됨");
  }
}

MathUtils.PI;                     // 3.14159
MathUtils.circleArea(5);          // 78.54
// 인스턴스에서는 접근 X
new MathUtils().PI;               // undefined

this 의 함정 — 분리하면 잃음

class Counter {
  count = 0;
  increment() {
    this.count++;
  }
}

const c = new Counter();
c.increment();              // OK

const fn = c.increment;     // 메서드를 변수에
fn();                       // ❌ TypeError — this 잃음

// 해결 1: 명시적 bind
const fn = c.increment.bind(c);
fn();   // OK

// 해결 2: 화살표 함수 필드 (this 가 인스턴스에 고정)
class Counter {
  count = 0;
  increment = () => {       // 화살표 — this 가 인스턴스로 자동 캡처
    this.count++;
  };
}
const fn = new Counter().increment;
fn();   // OK

React 이벤트 핸들러·setTimeout 콜백 등에서 가장 자주 만나는 함정. 22편(this) 에서 깊이.

instanceof — 인스턴스 확인

class Cat extends Animal { }

const c = new Cat("나비");
c instanceof Cat;          // true
c instanceof Animal;       // true (상속)
c instanceof Object;       // true (모든 객체)

// 사용
function feed(x) {
  if (x instanceof Animal) x.eat();
}

믹스인 — 다중 상속의 대안

// JS 는 단일 상속만. 여러 능력 합치고 싶으면 믹스인
function Loggable(Base) {
  return class extends Base {
    log(msg) { console.log(`[${this.constructor.name}] ${msg}`); }
  };
}

function Serializable(Base) {
  return class extends Base {
    toJSON() { return JSON.stringify(this); }
  };
}

class User extends Loggable(Serializable(Object)) {
  constructor(name) { super(); this.name = name; }
}

const u = new User("준성");
u.log("hi");        // [User] hi
u.toJSON();         // '{"name":"준성"}'

클래스 vs 함수 + 객체 — 언제 클래스?

실전 가이드. 다음 중 2개 이상 해당하면 클래스, 아니면 함수 + 객체 리터럴.

① 인스턴스가 여러 개 생성됨 (User 객체 N 개).

② 상태(필드) 가 있고 메서드들이 그 상태를 다룸.

③ 상속·다형성이 자연스러움.

한 가지만 — 함수 + 클로저 또는 객체 리터럴이 더 가볍습니다. React 함수형 컴포넌트가 그 예.

한 표 — 멤버 종류

종류예시특징
인스턴스 필드x = 0;매 인스턴스
인스턴스 메서드greet() { }프로토타입에 한 번
정적 필드static C = 1;클래스 자체
정적 메서드static of() { }클래스 자체
getter/setterget x() / set x(v)속성처럼 접근
private 필드#secret = 0;진짜 비공개 (ES2022)
static blockstatic { ... }클래스 초기화 (ES2022)

19편 — 모듈 (import·export·번들러)

ESM/CJS, default vs named, 트리 셰이킹.

📚 쉽게 배우는 자바스크립트 교재
이전: 17편 fetch · 현재: 18편 (중급) · 다음 → 19편 모듈 · 진행: 18/26

© 2026 주나이테크(주) @JUNAITECH