아름이의 개발로그

[공부 기록] OOP(Object-Oriented Programming)

|

OOP(Object-Oriented Programming)이란?

객체를 중심으로 소프트웨어 설계를 체계화하는 프로그래밍 언어 모델이다. OOP로 프로그래밍을 짜게 되면 모든 것은 propertymethod로 이루어진 객체들로 구성되게 된다. OOP는 크게 4가지 특징으로 이루어져있는데 아래와 같다.

1. Encapsulation (캡슐화)

객체 내의 데이터들을 그 객체 안에 숨겨서 다른 객체가 접근할 수 없게 만드는 것이다. 오직 객체가 제공하는 함수를 통해서만 그 데이터에게 한정적으로 접근할 수 있게 한다. 이러한 데이터 숨김의 특성은 프로그램 보안을 강화하고 의도하지 않은 데이터 손상을 방지할 수 있다.

2. Abstraction (추상화)

여러 객체들의 공통된 propertymethod를 잘 모아서 객체를 하나 만들고 그것을 그 대상 객체들이 상속받는 것이 추상화이다. 상속하는 것을 부모, 상속 받는 쪽을 자식이라고 부르는데, 자식들은 그 객체만의 고유하고 구체적인 기능을 가진다. 이러한 과정을 통해서 자식들은 부모가 가진 공통된 것들을 다시 정의하지 않고 상속만 받아서 사용하기 때문에 코드의 재사용성이 높아진다. 그리고 코드가 복잡하기 때문에 발생할 수 있는 실수들을 줄일 수 있게 된다.

3. Inheritance (상속)

객체의 propertymethod를 사용할 수 있게 제공하는 것이다. 이를 통해서 코드를 재사용할 수 있게 하고 다형성을 가능하게 만든다.

4. Polymorphism (다형성)

객체는 문맥에 따라 둘 이상의 형태를 취할 수 있다. 같은 코드지만 객체에 따라 다른 기능을 요구하는 문맥에서, 중복된 코드를 줄이면서도 원하는 기능을 효과적으로 처리할 수 있게 한다.

JavaScript에서 Prototype은 무엇일까?

JavaScript는 객체지향 언어이지만 클래스 개념이 없다. 그래서 기존의 객체(Prototype)을 복사해서 쓰는 방식으로 클래스가 가진 기능들을 흉내내고 있다. 그렇게 만들어진 객체 또한 복사해서 사용이 가능하다. 그렇게 객체들을 확장하여 객체지향을 실현할 수 있게 해주는 것이 JavaScript의 Prototype인 것이다.
JavaScript에서 함수를 정의하면 두 가지 작업이 일어나는데, 첫 번째는 함수가 만들어지는 것이고 두 번째는 프로토타입 객체가 만들어지는 것이다. 함수에는 prototype이라는 변수가 자동으로 생기는데 이 prototype은 함께 생성되었던 프로토타입 객체를 가리키게 된다. 함수에서 프로토타입 객체에 접근이 가능하게 되는 것이다. 그리고 프로토타입 객체에서도 constructor라는 변수가 자동으로 생기는데 이것은 함께 생성되었던 함수를 가리킨다. 이를 그림으로 표시하면 아래와 같다.
function_and_prototype_object
new키워드를 써서 객체를 생성하면 생성된 모든 객체는 프로토타입 객체를 가리키게 된다. 프로토타입 객체는 생성된 인스턴스의 원형이 되는 객체가 되는 것이다.
all_obj_indicate_prototype_object

프르토타입 객체란?

인스턴스들의 원형이 되는 객체이다. 모든 객체는 __proto__를 통해서 프로토타입 객체에 접근할 수 있다. 프로토타입 객체는 런타임에 동적으로 메소드를 추가할 수 있다. 그리고 프로토타입 객체를 원형으로 만들어진 인스턴스들은 동적으로 생성된 메소드를 사용할 수 있다.

function Person(){}

var joon = new Person();  
var jisoo = new Person();

Person.prototype.getType = function (){  
    return "인간"; 
};

console.log(joon.getType());   // 인간  
console.log(jisoo.getType());  // 인간 

all_obj_indicate_prototype_object2

프로토타입 객체에 메소드를 추가하거나 삭제할 때는 함수prototype을 통해서 접근해야 하지만 프로토타입 객체의 값을 읽어올 때에는 함수안의 prototype 혹은 객체 이름으로 접근하면 된다.

joon.getType = function (){  
    return "사람"; 
};

console.log(joon.getType());   // 사람  
console.log(jisoo.getType());  // 인간

jisoo.age = 25;

console.log(joon.age);   // undefined  
console.log(jisoo.age);  // 25  

all_obj_indicate_prototype_object3 png

이렇게 joon객체에 메소드를 추가한 경우처럼 인스턴스에 속성이나 메소드를 추가한 경우에는 프로토타입 객체에 같은 이름의 속성이나 메소드가 있다고 하더라도 인스턴스의 속성이나 메소드를 읽어오게 된다. 인스턴스에 속성이나 메소드가 없는 경우는 그 객체의 원형인 프로토타입 객체에 올라가서 속성이나 메소드를 찾게 된다. 여기서 상위의 프로토타입 객체에 올라가서 해당하는 속성이나 메소드를 찾는 것을 prototype link라고 한다.

정리하면

JavaScript에서는 기본형을 제외한 모든 것이 객체인데, 이 객체를 만들기 위해서는 원형이 필요하다. 프로토타입은 객체를 만들기 위한 원형의 역할을 하는 것이다. 만들어진 객체(인스턴스)에는 __proto__라는 속성이 그 객체의 원형을 가리키는 숨겨진 링크를 참조하고 있다. 이 숨겨진 링크를 프로토타입이라고 정의한다.

JavaScript에서 Object를 생성하는 4가지 방법들

1. Functional Instantiation

let Car = function() {
    let someInstance = {};
    someInstance.position = 0;
    
    someInstance.move = function() {
        position += 1;
    }
    return someInstance;
};

let car1 = Car();
let car2 = Car();
car1.move();

2. Functional Shared Instantiation

let extend = function(to, from) {
    for (let key in from) {
        to[key] = from[key];
    }
};

let someMethods = {};
someMethods.move = function() {
    this.position += 1;
};

let Car = function(position) {
    let someInstance = {
        position: position,
    };
    extend(someInstance, someMethods);
    return someInstance;
};

let car1 = Car(5);
let car2 = Car(10);
car1.move();

Functional Instantiation 방식은 인스턴스를 생성할 때마다 모든 메소드를 someInstance에게 할당하므로, 각각의 인스턴스들이 메소드의 수 만큼의 메모리를 더 차지하지만 Functional Shared Instantiation 방식은 someMethods의 메모리 주소만을 참조하기 때문에 메모리 효율이 좋아집니다.

3. Prototypal Instantiation

let someMethods = {};
someMethods.move = function() {
    this.position += 1;  
};

let Car = function(position) {
    let someInstance = Object.create(someMethods);
    someInstance.position = position;
    return someInstance;
};

let car1 = Car(5);
let car2 = Car(10);
car1.move();

object.create() : 특정 객체를 프로토타입으로 하는 객체를 생성해주는 함수.

4. Pseudoclassical Instantiation

let Car = function(position) {
    this.position = position;
};

Car.prototype.move = function() {
    this.position += 1;  
};

let car1 = new Car(5);
let car2 = new Car(10);
car1.move();

현재 가장 많이 쓰는 방법입니다.

출처
Codestates Immersive Course
https://searchapparchitecture.techtarget.com/definition/object-oriented-programming-OOP
http://www.nextree.co.kr/p7323/

Comments