Javascript

[JavaScript] 자바스크립트 | 클래스와 오브젝트의 차이점(class vs object) | 객체지향 언어 | 클래스

@leem 2025. 3. 19. 14:25
이 글은 드림코딩 유튜브 강의를 보며 학습한 내용을 정리한 JavaScript 복습 노트입니다

1. 객체 지향 프로그래밍(OOP) 개념

객체 지향 프로그래밍(OOP, Object-Oriented Programming)은 코드를 객체 단위로 구성하여 재사용성과 유지보수성을 높이는 방식입니다.

객체(Object)

  • 속성(property)과 동작(method)를 가지는 데이터 구조입니다.
const car = {
  brand: 'Tesla',
  speed: 200,
  drive: function () {
    console.log('Driving fast!');
  }
};

클래스(Class)

  • 객체를 생성하기 위한 템플릿(template) 입니다.
  • JavaScript에서는 ES6(ECMAScript 2015) 에서 도입되었습니다.
  • 기존에는 프로토타입 기반의 상속을 사용했으나, 클래스를 도입하면서 가독성이 좋아졌고 문법이 간결해짐.

2. 클래스 선언(Class Declaration)

기본적인 클래스 구조

class Person {
  constructor(name, age) {
    this.name = name; // 인스턴스 필드
    this.age = age;
  }

  speak() {
    console.log(`${this.name}: hello!`);
  }
}

const ellie = new Person('ellie', 20);
console.log(ellie.name); // "ellie"
console.log(ellie.age); // 20
ellie.speak(); // "ellie: hello!"
  1. class Person { ... }
    • Person이라는 클래스를 선언 (클래스명은 대문자로 시작하는 것이 관례)
  2. constructor(name, age)
    • 생성자 메서드. new 키워드로 객체를 생성할 때 자동으로 실행됨.
    • this.name = name, this.age = age : 객체의 속성을 초기화.
  3. speak()
    • speak() 메서드는 객체의 name 속성을 이용해 메시지를 출력.
  4. new Person('ellie', 20);
    • Person 클래스의 인스턴스(객체)를 생성.

3. Getter와 Setter (게터와 세터)

class User {
  constructor(firstName, lastName, age) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age; // 내부적으로 set age(value) 호출
  }

  get age() {
    return this._age;
  }

  set age(value) {
    this._age = value < 0 ? 0 : value; // 나이가 음수면 0으로 설정
  }
}

const user1 = new User('Steve', 'Job', -1);
console.log(user1.age); // 0

get과 set 키워드

  1. Getter (get)
    • user1.age 처럼 값을 가져올 때 실행되는 함수.
    • return this._age; 로 age 값을 반환.
  2. Setter (set)
    • user1.age = -1; 같은 방식으로 값을 설정할 때 실행됨.
    • value < 0 ? 0 : value; 를 통해 음수 값 방지.
  3. _age 속성
    • JavaScript에서 get과 set을 사용할 때, 무한 루프 방지를 위해 내부적으로 _age를 사용.

4. Public(공개) & Private(비공개) 필드

class Experiment {
  publicField = 2;  // 공개 필드 (모든 곳에서 접근 가능)
  #privateField = 0; // 비공개 필드 (클래스 내부에서만 접근 가능)
}

const experiment = new Experiment();
console.log(experiment.publicField);  // 2
console.log(experiment.privateField); // undefined (외부에서 접근 불가)

 #privateField

  • # 기호를 사용하여 클래스 내부에서만 접근 가능한 비공개 필드를 만듦.
  • experiment.privateField를 출력하려고 하면 undefined가 출력됨.

5. 정적(static) 속성과 메서드

class Article {
  static publisher = 'Dream Coding';

  static printPublisher() {
    console.log(Article.publisher);
  }
}

console.log(Article.publisher); // "Dream Coding"
Article.printPublisher(); // "Dream Coding"

static 키워드

  • 클래스 자체에 속하는 변수나 메서드.
  • 인스턴스가 아닌 클래스명 자체로 접근해야 함 (Article.publisher).

6. 상속(Inheritance)

class Shape {
  constructor(width, height, color) {
    this.width = width;
    this.height = height;
    this.color = color;
  }

  draw() {
    console.log(`drawing ${this.color} color!`);
  }

  getArea() {
    return this.width * this.height;
  }
}

class Triangle extends Shape {
  draw() {
    super.draw(); // 부모 클래스의 draw() 호출
    console.log('🔺');
  }

  getArea() {
    return (this.width * this.height) / 2; // 삼각형 면적 공식
  }

  toString() {
    return `Triangle: color: ${this.color}`;
  }
}

const triangle = new Triangle(20, 20, 'red');
triangle.draw(); // "drawing red color!" 🔺 출력
console.log(triangle.getArea()); // 200

extends 키워드

  • class Triangle extends Shape
    → Shape 클래스를 상속하여 Triangle 클래스 생성.

super 키워드

  • 부모 클래스의 메서드를 호출할 때 사용 (super.draw();).

7. instanceof 연산자

console.log(triangle instanceof Triangle); // true
console.log(triangle instanceof Shape); // true
console.log(triangle instanceof Object); // true (모든 객체는 Object의 인스턴스)
  • instanceof 는 특정 객체가 해당 클래스를 기반으로 만들어졌는지 확인하는 연산자.

8. 객체 값 변경 확인 (참조형 데이터)

let obj = { value: 5 };
function change(value) {
  value.value = 7;
}
change(obj);
console.log(obj); // { value: 7 }
  • 객체는 참조(reference)로 전달되므로 함수 내부에서도 값이 변경됨.

🔍 추가 설명

1) Getter와 Setter 내부 _age 속성의 의미

get age() {
  return this._age;
}

set age(value) {
  this._age = value < 0 ? 0 : value;
}
  • this.age = value; 할 때, 내부적으로 set age(value) 가 실행됨.
  • 무한 재귀 호출을 방지하기 위해 this._age 라는 별도의 변수 사용.
  • 만약 this.age = value; 를 그대로 할 경우, set age() 가 계속 호출되며 스택 오버플로우 오류(Stack Overflow) 발생.

2) Private 필드(#privateField)의 실제 동작 방식

class Experiment {
  #privateField = 0;
}

const experiment = new Experiment();
console.log(experiment.privateField); // undefined
  • JavaScript에서는 # 키워드를 붙여야만 해당 필드를 외부에서 직접 접근하지 못하게 보호 가능.
  • experiment.#privateField 로 접근하려고 하면 SyntaxError 발생.

3) super.draw(); 가 호출되는 이유

class Triangle extends Shape {
  draw() {
    super.draw(); // 부모 클래스의 draw() 실행
    console.log('🔺');
  }
}
  • super.draw(); 는 부모 클래스의 draw() 메서드를 호출.
  • Shape 클래스를 상속했으므로, 기본적인 색상 출력 후 추가적인 동작을 수행할 수 있도록 확장.

4) 객체가 instanceof Object 가 되는 이유

console.log(triangle instanceof Object); // true
  • JavaScript에서 모든 객체는 Object 를 상속 받음.
  • Object는 JavaScript에서 모든 객체의 최상위 부모 클래스이므로, 어떤 객체든 instanceof Object 를 실행하면 true.

5) static 속성이 this 로 접근되지 않는 이유

class Article {
  static publisher = 'Dream Coding';

  static printPublisher() {
    console.log(this.publisher); // 가능 (클래스에서 호출할 때)
  }
}

const article1 = new Article();
console.log(article1.publisher); // undefined
  • static 속성은 클래스 자체에 귀속 되기 때문에, article1.publisher 로 접근할 수 없음.
  • 반드시 Article.publisher 처럼 클래스명으로 접근해야 함.