OOP, Class/Instance, Prototype 정리

김대연·2019년 12월 26일
0

Javascript concepts

목록 보기
3/9

1. OOP(Object Oriented Programming) 란?

객체 지향 프로그래밍으로 프로그램을 디자인하는 개념 중 하나이다.
이 방식은 단순히 거대한 하나의 프로그램부터 시작하여 작게 쪼개지는 방식이 아니라, 반대로 먼저 작은 파트들을 만들어 그것을 조합하여 하나의 프로그램을 구현하는 방식이다. 이 때 작은 파트들의 역할을 맡게 되는 것이 객체가 된다. (여기서 조금 더 쉽게 표현하기 위해 ‘파트’라고 하였는데, 이것을 ‘객체’로 생각하면 되겠다.)

이런 방식으로 프로그램이 만들어지면 여러 장점이 생기는데 첫번째는 중복성이다. 프로그램에 필요한 작은 파트들을 먼저 디자인을 하면서 중복적인 부분을 줄일 수 있게 된다.

두번째로는 파트들의 독립성이다. 파트의 독립성이 강해져서 문제가 생겼을 경우 그 문제가 야기하는 임팩트를 줄일 수 있다. 즉, 각 문제를 분산시켜 해결하기 용이하게 만든다는 것이다.

1-1. 객체

먼저 객체 지향 프로그래밍을 설명하려면 여기서 지향하는 이 “객체”란 무엇인가를 빼놓을 수 없다. 영어로는 Object 라는 이 것을 추상적인 개념으로 번역하려고 하다 보니 혼란스러웠다.

단순하게 표현하자면 객체는 변수(Property/Attribute) 혹은 함수(Methods/Behaviour)를 지닌 하나의 대상이다. 이 때 변수는 표현하고자 하는 상태를 나타내고 함수는 표현을 하는 행위가 되겠다.

실생활의 예시를 들어본다면, 자동차가 가장 유명한 예시이다.
자동차라는 하나의 객체는 여러 가지를 내포하고 있다.

예를 들어, 자동차의 Property는 모델, 가격, 색상, 연비 등이 될 수 있고, 자동차의 Methods는 가속, 감속, 정지, 라이트 등이 될 수 있다.
이런 객체의 기본이 되는 정형화된 모델을 class 라고 부르는데, 자동차 예시를 이어 설명하자면 공장에서의 도면을 class라고 생각할 수 있다. 그러면 이 도면을 따라 같은 속성을 지닌 여러 자동차들이 생산이 되는 것이다.

출처: https://intellipaat.com/blog/tutorial/python-tutorial/python-classes-and-objects/

그리고 위의 그림처럼 Class 기반으로 만들어진 각 자동차가 객체가 되는 것이고, 이러한 객체를 classinstance 라고 칭한다.
그리고 객체가 생성될 때 classconstructor 라는 “생성자” 메서드는 instance 를 생성하고 instance 의 Property에 접근할 수 있다.

1-2. 객체 지향 프로그래밍의 특징

객체 지향 프로그래밍의 특징은 대표적으로 4가지가 있다.

  1. Encapsulation(캡슐화)
  • Object 에 속한 Property 와 Methods 들을 은닉화시켜 외부에서 접근하지 못하게 할 수 있어서 정보 보호를 할 때 유용하다.
  • 같은 객체를 재사용할 수 있어 유용하다.
  1. Inheritance(상속)
  • 부모(class)의 속성을 물려받으면서 중복성을 줄일 수 있다.
  • 또한 부모클래스에서 수정이 일어나도 자식클래스는 속성을 물려받기에 수정에 따른 여파가 적다.
  1. Abstraction(추상화)
  • 추상화를 통해 공통적인 Property와 Methods 를 정리할 수 있다.
  1. Polymorphism(다형성)
  • 여러 다른 자식클래스에서 따로 메서드들을 선언하지 않고, 부모클래스에서 메서드를 선언하여 놓으면 각 자식클래스에서 상속받아 원하는 기능을 자식클래스에 맞게 구현할 수 있다.

아래 그림을 예시로 들자면, 먼저 각 도형 객체들의 부모가 되는 클래스 Figure가 있다.
Figure에 메서드 Draw()를 선언하였고, 아래 3개의 객체가 Draw()를 상속받았다.
하지만 Draw()의 기능은 각 도형의 Property에 맞게 변경을 할 수 있다.

출처: https://debugdaldal.tistory.com/152

1-3. JavaScript에서 Object를 생성하는 여러가지 방법들

  1. Functional
  • 함수를 이용하여 Instance를 생성
var Point = function() {
  var point = {};
  point.num = 0;
  point.add = function() {
    point.num++;
  }
  return point;
};
var number1 = Point();
number1.add(); //number1.num === 1;
  1. Functional Shared
  • Functional Instantiation 은 각 인스턴스가 메서드를 할당받아 메모리를 더 차지하게 되지만, 이 경우는 인스턴스가 메서드의 주소만 참조하며 메모리 상 효율이 좋습니다.
var extend = function(to, from) {
  for (var key in from) {
    to[key] = from[key];
  }
};
var Point = function(num) {
  var point = {
    num : num,
  };
  extend(point, someMethod);
  return point;
};
var someMethod = {};
someMethod.add = function() {
  this.num++;
};
var number1 = Point(0);
number1.add();//number1.num === 1;
  1. Prototypal Instantiation
  • Functional Shared 와 비슷하지만 point를 선언할 때 Object.create 을 이용하여 프로토타입이어야 할 객체를 지정합니다.
var someMethod = {};
  someMethod.add = function() {
  this.num += 1;
}
var Point = function(num) {
  var point = Object.create(someMethod); // 프로토타입이어야 할 객체를 지정
  point.num = num;
  return point;
};
var number1 = Point(0);
var number1.add() //number1.num === 1
  1. Pseudoclassical Instantiation
  • 메소드를 Class의 프로토타입에 추가하고, 새 객체를 선언할 때 “new” 를 사용합니다.
var Point = function(num) {
  this.num = num;
}
Point.prototype.add = function() {
  this.num += 1;
}
var number1 = new Point();
number.add(); //

2. Prototype

사실 javascript 에는 class 가 존재하지 않는다. 위에 예시로 적힌 코드들을 다시 본다면 class 라는 단어 대신 function 으로 선언되어 있다.
일단 예시로 사용할 간단한 코드이다.

function Foo() {};
var foo = new Foo();

constructor 에는 prototype 이라는 property가 있는데 이것은 자기 자신을 통해 만들어질 새로운 객체의 원형이 될 프로토타입(객체)을 가리킨다. 즉 자신의 분신이 되는 이 것을 “Prototype Object” 라고 한다.

function Foo()prototype 을 확인해보자.
그렇다면 자신의 원형이 되는 객체는 어떻게 찾을 수 있을까?

자신의 원형이 되는 프로토타입을 지칭하는 말은 “Prototype Link”라고 부른다. 위의 예시에서 __proto__: f() 라인에서 속성값은 function Prototype 임을 확인할 수 있다.
그리고 constructor인 “Prototype Object”의 원형이 되는 것을 __proto__ 로 따라가보면 Object, 즉 Object Prototype Object를 향하는 것을 확인할 수 있다. 그러므로 “Prototype Link”는 상위에서 물려받는 객체의 프로토타입에 관한 정보라는 것이 된다.

2-2. Prototype Chain

“Prototype Object”를 다시 정리해보자. 자신의 분신, 즉, 자신을 원형으로 하는 (새롭게 만들어질) 객체의 프로토타입을 “Prototype Object”라고 한다.
“Prototype Link”는 자신의 원형이 되는 프로토타입 객체를 향한다.

출처: http://insanehong.kr/post/javascript-prototype/

위의 그림처럼 __proto__, 즉 Prototype Link 가 자신의 상위 객체의 프로토타입과 연결되어 있는 관계를 “Prototype Chain” 이라고 한다.

추가로 아래의 예시를 보면,

A에 직접 상속된 값과 A의 Prototype Object에 상속된 값은 다르다는 것을 알 수 있다.

그래서 이것이 왜 사용되는가?

이제 우리는 function 객체가 생성될 때 prototype 이란 것이 생성되는 것을 알았고, 이 prototype 을 이용하여 자식에게 속성을 상속할 수 있다는 것도 알게 되었다. 그런데 이것이 왜 필요한가? 자식에게 자신의 속성을 상속을 하게 되면서 자식은 각자 속성을 선언하며 메모리를 낭비할 필요가 없어진다. 대신 prototype 에 이미 존재하는 속성을 이용하여 훨씬 효율적으로 메모리 관리를 할 수 있게 된다.

참고 자료 :

http://insanehong.kr/post/javascript-prototype/
https://medium.com/@bluesh55/javascript-prototype-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-f8e67c286b67

0개의 댓글