[TIL] Unit 2. 객체 지향 프로그래밍

string_main·2022년 5월 25일
1

JavaScript

목록 보기
6/22
post-thumbnail

🌱 객체 지향 프로그래밍 (OOP)


  • 정의 : 하나의 모델이 되는 청사진(blueprint, class)을 만들고, 그 청사진을 바탕으로 한 객체(instance object)를 만드는 프로그래밍 패턴.

절차 지향 프로그래밍과는 다르게 데이터와 기능을 한곳에 묶어서 처리. 속성과 메서드가 하나의 "객체"라는 개념에 포함되고, 내장 타입인 object와는 다르게, 클래스(Class)라는 이름으로 부른다.

🌱 클로저 모듈 패턴


  • 단순 객체를 사용한 메서드 호출
let counter1 = {
  value: 0,
  increase: function() {
    this.value++ // 메서드 호출을 할 경우, this는 counter1을 가리킵니다
  },
  decrease: function() {
    this.value--
  },
  getValue: function() {
    return this.value
  }
}

counter1.increase()
counter1.increase()
counter1.increase()
counter1.decrease()
counter1.getValue() // 2
  • 클로저 모듈 패턴 (재사용성 증가)
function makeCounter() {
  let value = 0;
  return {
    increase: function() {
      value++;
    },
    decrease: function() {
      value--;
    },
    getValue: function() {
      return value;
    }
  }
}

let counter1 = makeCounter()
counter1.increase()
counter1.getValue() // 1

let counter2 = makeCounter()
counter2.decrease()
counter2.decrease()
counter2.getValue() // -2

🌱 클래스와 인스턴스


  • 클래스 : 하나의 모델이 되는 청사진, 틀 (ex. 붕어빵 틀)
  • 인스턴스 : 클래스를 바탕으로 생성된 객체 (ex. 붕어빵)
// ES5 클래스는 함수로 정의할 수 있다.
function Car (brand, name, color) {
	// 인스턴스 생성 시 실행 코드
}

// ES6 클래스는 class 키워드를 사용해 정의한다.
class Car {
	constructor(brand, name, color) { // 생성자 함수는 return 값 없음
		// 인스턴스 생성 시 실행 코드
	}
}

🌿 new 키워드


  • new 키워드를 통해 클래스의 인스턴스를 생성할 수 있다.
let veyron = new Car('bugatti', 'veyron', 'black')

🌿 속성과 메서드


  • 속성 : 객체 내부에 있는 값
  • 메서드 : 속성 중 자료형이 함수인 경우
  • this : 함수가 실행될 때, 해당 scope마다 생성되는 고유한 실행 문맥(context). new 키워드로 인스턴스 생성 시 해당 인스턴스가 바로 this의 값이 된다.
// ES5
function Car(brand, name, color) {
  // 속성 정의
  this.brand = brand;
  this.name = name;
  this.color = color;
}

// 메서드 정의
Car.prototype.refuel = function() { }

// ES6
class Car {
	// 속성 정의
	constructor(brand, name, color) {
		this.brand = brand;
		this.name = name;
		this.color = color;
	}

	// 메서드 정의
	refuel() { }
}

// 인스턴스에서 속성과 메서드를 사용
let mini = new Car('bmw', 'mini', 'white');
mini.brand; // 'bmw'
mini.refuel(); // mini에 연료를 공급합니다.

🌱 절차 지향 프로그래밍 vs 객체 지향 프로그래밍


  • 절차 지향 프로그래밍 : 순차적인 명령들의 조합으로, 기껏해야 함수로 이동하는 것이 전부였다. (ex. C, 포트란 등)

  • 객체 지향 프로그래밍 : 별개의 변수와 함수로 순차적으로 작동하는 것을 넘어, 데이터의 접근과, 데이터의 처리 과정에 대한 모형을 만들어 내는 방식이다. 데이터와 기능이 별개로 취급되지 않고, 한 번에 묶여서 처리할 수 있게 되었다. (ex. Java, C++, C# 등)

JavaScript는 엄밀해 말해 객체 지향 언어는 아니지만, 객체 지향 패턴으로 작성할 수 있다.

🌱 객체 지향 프로그래밍(OOP)의 주요 개념

  • 객체로 그룹화 된다.

  • 데이터와 기능이 함께 있다는 원칙에 따라 메서드와 속성이 존재한다.

  • 클래스는 일종의 원형(original form)으로, 객체를 생성하기 위한 아이디어나 청사진이다.

  • 인스턴스는 클래스의 사례이다.

  • 클래스는 객체를 만들기 위한 생성자 함수를 포함한다. 생성자를 통해 클래스에 세부 사항(속성)을 주입한다.

  • OOP의 4가지 특징 (OOP Basic Concepts)

    1. 캡슐화(Encapsulation) : 데이터와 기능을 하나의 단위로 묶는 것으로, 구현은 숨기고 동작은 노출시키는 은닉화와 언제든 구현을 수정할 수 있는 느슨한 결합에 유리한 특징이 있다.
    • 은닉화(hiding) : 내부 데이터나 내부 구현이 외부로 노출되지 않도록 만드는 것
    • 느슨한 결합(Loose Coupling) : 코드 실행 순서에 따라 절차적으로 코드를 작성하는 것이 아니라, 코드가 상징하는 실제 모습과 닮게 코드를 모아 결합하는 것
    1. 상속(Inheritance) : 부모 클래스의 특징을 자식 클래스가 물려받는 것. (기본 클래스(base class)의 특징을 파생 클래스(derived class)가 상속받는다는 표현이 적합하나, 부모/자식을 많이 사용함)
    2. 추상화(Abstraction) : 내부 구현은 복잡한데 실제 노출되는 부분은 단순하게 만든다는 개념으로, 인터페이스(interface)를 단순화할 수 있다. 캡슐화는 은닉에 포커스가 있다면, 추상화는 필요치 않은 메서드 등의 노출을 줄이고 단순화 하는 것에 포커스가 있다.
    3. 다형성(Polymorphism) : 다양한 형태를 가질 수 있는 특성. 똑같은 메서드라 하더라도 다른 방식으로 구현될 수 있다. (ex. HTMLElement)

    ➡️ 복잡성을 줄이고, 재사용성을 높인다. 변화에 대한 영향을 최소화 한다. 객체의 특성에 맞게 작성할 수 있다는 장점!

🌱 TypeScript


  • MS에서 구현한 JavaScript의 슈퍼셋 프로그래밍 언어로 엄격한 문법을 지원한다. (JavaScript의 한계를 보완)

  • private 키워드(은닉화) 제공 (JavaScript에서는 ES2019부터 #이라는 키워드가 도입. 지원하는 브라우저가 적어 널리 쓰이지 않음)

class Animal {
  private name: string;

  constructor(theName: string) {
    this.name = theName;
  }
}

new Animal("Cat").name; // 사용 불가
// Property 'name' is private and only accessible within class 'Animal'. 
  • interface 키워드(추상화) 제공 (JavaScript에서는 존재하지 않는 기능)
interface ClockInterface {
  currentTime: Date;
  setTime(d: Date): void;
}

class Clock implements ClockInterface {
  currentTime: Date = new Date();
  setTime(d: Date) {
    this.currentTime = d;
  }
  constructor(h: number, m: number) {}
}

🌱 프로토타입(Prototype)


Prototypes are the mechanism by which JavaScript objects inherit features from one another

프로토타입은 자바스크립트 객체를 다른 하나로부터 특성을 상속받기 위한 매커니즘이다.

  • 프로토타입은 object 자료형임.

  • JavaScript에서는 객체를 상속하기 위하여 프로토타입이라는 방식을 사용함. (흔히 프로토타입 기반 언어(prototype-based language)라 불린다.)

  • 프로토타입에 속성을 추가하면 부모만 가지게 되는데, 자식이 해당 속성을 가지고 있지 않으면 부모 속성을 찾아 대체하기 때문에 부모 속성을 사용할 수 있다. 부모가 없다면 부모의 부모..계속 타고 올라감. (prototype chain)

그래서 프로토타입이 뭔데..?
➡️ 부모 객체의 유전자라고 생각하면 이해하기 쉽다.

class Human {
  constructor(name, age) { // 생성자에 작성한 속성은 자식이 직접 가짐
    this.name = name;
    this.age = age;
  }

  sleep() {
    console.log(`${this.name}은 잠에 들었습니다`);
  }
}

let kimcoding = new Human('김코딩', 30);

Human.prototype.constructor === Human; // true
// Human 클래스 원형의 생성자 함수는 Human을 가리킨다.

Human.prototype === kimcoding.__proto__; // true
// __proto__는 kimcoding이라는 객체를 생성한 Human 객체의 prototype 객체를 가리킨다.

Human.prototype.sleep === kimcoding.sleep; // true
// Human 클래스의 sleep 메서드는 프로토타입에 있으며, Human 클래스의 인스턴스인 kimcoding에서 kimcoding.sleep으로 사용할 수 있음

Human.prototype.height = 155; // 프로토타입에 속성을 추가하면 부모만 속성을 가짐
  • array 자료에 .sort()등의 메서드를 붙일 수 있었던 이유는? ➡️ 부모 유전자에 기록 되어있기 때문!!
let array = [4, 2, 1]; // 사실은 let array = new Array(4, 2, 1); 와 같은 표현이었다.

Array.prototype // 찍어보면 별의별거 다 나옴

🌱 .prototype vs .__proto__


  • 한 클래스 객체 생성 시 객체만 생성되는 것이 아니라 prototype 객체(원형)도 함께 생성됨.
  • 새로운 객체를 생성할 때 객체의 프로퍼티와 함께 __proto__ 프로퍼티가 함께 생성됨.
Human.prototype.constructor === Human; // true
// Human 클래스 원형의 생성자 함수는 Human을 가리킨다.

Human.prototype === kimcoding.__proto__; // true
// __proto__는 kimcoding이라는 객체를 생성한 Human 객체의 prototype 객체를 가리킨다. 

홍삼 게임도 아니고 아~싸 너너 하면서 서로를 지목하는 프로토타입………어질어질 ^^;
그림으로 이해하는게 확실히 편했다.

🌱 프로토타입 체인


  • 객체 지향 프로그래밍의 특성 중 상속을 JavaScript에서 구현할 때에는 프로토타입 체인을 사용함

  • 특정 객체의 프로퍼티나 메소드에 접근시 proto가 가리키는 링크를 따라서 자신의 부모 역할을 하는 프로토타입 객체의 프로퍼티나 메소드를 접근할 수 있음.

  • 모든 프로토타입 체이닝의 종점은 Object.prototype이다.

let div = document.createElement('div');

div.__proto__ // HTMLDivElement
div.__proto__.__proto__ // HTMLElement
div.__proto__.__proto__.__proto__ // Element
div.__proto__.__proto__.__proto__.__proto__ // Node
div.__proto__.__proto__.__proto__.__proto__.__proto__ // EventTarget
div.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__ // Object
div.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__ // null

🌱 알게된 점 & 느낀 점


  • 프로토타입 기반 OOP는 class 기반의 OOP 와 완전히 상반되는 방식이다.

  • 프로토타입 기반 OOP에서 객체 생성은 일반적으로 복사를 통해 이루어진다.

  • 프로토타입은 개별 객체 수준에서 객체를 수정하고 발전시키는 능력은 선험적 분류의 필요성을 줄이고 반복적인 프로그래밍 및 디자인 스타일을 장려한다.

  • 프로토타입 프로그래밍은 일반적으로 분류하지 않고 유사성을 활용하도록 선택한다.

  • JS 공부는 아무래도 철학 공부같다.....

🌱 추가 학습


  • 프로토타입
  • this
  • super
  • extends
  • 인터페이스
  • #으로 은닉화 구현해보기
  • getter, setter 구현하기

| 참고자료 |

잘못된 설명은 댓글로 피드백 주시면 저의 성장에 도움이 됩니다! 감사합니다 :)

profile
FE developer

0개의 댓글