코딩을 배울테야/TIL

TIL_20210114_OOP

도도 새 2021. 1. 14. 10:58

OOP(Object-Oriented Programming) 란 객체 지향 프로그래밍을 말합니다.

여기서 말하는 객체란 무엇이고 프로그래밍은 무엇이며, 그 둘을 합한 객체 지향 프로그래밍은 무엇일까요?

OOP를 이해하기 위해서는 '컴퓨터 프로그래밍이 무엇인가' 부터 알아보아야 합니다.

 

컴퓨터 프로그래밍이란?

컴퓨터 프로그램은 알고리즘의 모음이라고 할 수 있습니다.

그렇다면 컴퓨터 프로그램을 구성하는 알고리즘은 무엇일까요?

 

알고리즘수학 컴퓨터 과학, 언어학 또는 관련 분야에서 어떠한 문제를 해결하기 위해 정해진 일련의 절차나 방법을 공식화한 형태로 표현한 것, 계산을 실행하기 위한 단계적 절차를 의미한다. 알고리즘은 연산, 데이터 마이닝(기계 학습) 또는 자동화된 추론을 수행한다.
_ 출처 : 위키백과

나의 친구 너의 친구 모두의 친구인 위키백과에서의 정의는 이렇습니다.

컴퓨터 프로그래밍 안에서의 알고리즘은 step by step 의 프로세스(과정, 공정) 의 모음이라고 이야기할 수 있겠습니다.

'어떤 문제를 해결하기 위한 과정' 들이 공통된 방향성을 가지고 모이면 하나의 컴퓨터 프로그램이 완성됩니다. 

 

하지만 컴퓨터는 인간의 언어를 그대로 받아들일 수 없기 때문에

프로그램을 개발할 수 있도록 도와주는 툴인 프로그래밍 언어를 활용해 컴퓨터에게 이야기를 하여야 합니다.

 

프로그래밍 언어의 단계

프로그래밍 언어란?

윗 문단에서 언급했듯, 쉽게 이야기하면 프로그래머가 프로그램을 개발할 수 있도록 도와주는 툴이라고 할 수 있습니다.

프로그래밍 언어는 크게 3가지 타입으로 나눌 수 있는데요,

 

Machine Languages (기계어)

Assembly Languages (어셈블리어)

High-Level Languages (고급언어)

 

이렇게 3가지입니다. (위의 High-Level이란 어려운 언어라기보다 고-저의 고 를 의미합니다)

문단 위에 따로 첨부한 이미지에 프로그래밍 언어의 단계의 도식화가 표현되어 있습니다.

Level이 low에 가까울수록 기계어에 가깝고, high에 가까울수록 인간의 언어와 가깝습니다.

 

첨언으로 제가 배우고 있는 JavaScript에 대해 설명을 한다면

  • JavaScriptHigh-Level Language 로 분류되고,
  • 실행되는 플랫폼에 따라 인터프리팅과 컴파일이 혼합되어 사용되는 특성이 있습니다.
  • 문서 전체를 보다 기계에 친화적인 언어로 컴파일(어떤 언어로 작성된 코드를 다른 언어로 바꾸는 것) 한 후 그 결과물을 인터프리트(코드를 읽어나가면서 해석하여 실행) 합니다.
    • (이 특성은 구글에서 2009년에 출시한 V8엔진으로 도입되었으며 자바스크립트의 성능을 크게 향상시켰습니다.)

 

위의 3 종류의 언어 중 객체 지향적 프로그래밍과 관련이 있는 High-Level Languages 는

절차 지향적 언어와 객체 지향적 언어로 나뉘어져 있습니다.

 

절차 지향적 언어

  • 순차적으로 특정 기능을 하는 패턴으로 구조화된 언어입니다.
  • 언어 안에서 함수와 변수 등의 상관관계(절차) 를 어떻게 짜는지에 중점이 맞춰져 있습니다.

객체 지향적 언어

 

객체 지향적 언어를 다루기 위해서는 객체(Object)가 무엇인지 알아야 합니다.

객체는 관련된 데이터와 함수(일반적으로 여러 데이터와 함수로 이루어지는데, 객체 안에 있을 때는 보통 프로퍼티와 메소드라고 부릅니다)의 집합입니다 _ 출처 : MDN

프로그래밍 과정의 모든 것을 객체(Object)로 구현할 수 있는 언어를 객체 지향적 언어라고 부릅니다.

Java, C++, Python 등을 모두 객체 지향적 언어라고 이야기할 수 있습니다.

JavaScript는 처음에는 객체 지향적 언어의 범주에 들어가지 않았지만 시간이 갈수록 객체 지향적 성격을 띄어 가고 있습니다.

그렇기 때문에 JavaScript로도 충분히 객체 지향적 프로그래밍(OOP) 이 가능합니다.

 

 

그래서 OOP(Object Oriented Programming)가 무엇?

어떠한 라이브러리나 특정 언어를 지칭하는 것이 아닌

프로그래밍 세계에서 통용되는 '객체 지향 프로그래밍'이라는 철학을 의미하는 단어입니다.

객체 지향 프로그래밍이란

우리가 실제 세계에서 사물을 인지하는 방법을 객체를 통해 프로그래밍에 접목시키려는 시도입니다.

단순한 명령어의 집합과 그 목록일 뿐인 절차 지향 프로그래밍과 달리

객체들에게 각각의 특성을 쥐어주고, 객체들 사이에서의 소통을 기반으로 프로그래밍 합니다.

때문에 절차 지향 프로그래밍보다 유연하고, 유지 보수가 용이합니다.

절차 지향 프로그래밍으로 수정을 하려면 해당 코드를 찾아 일일히 바꿔 주어야 하지만

객체 지향 프로그래밍에서는 수정할 데이터가 담겨 있는 객체의 값만 바꿔 주면

그 객체의 데이터를 응용하는 다른 객체들이 값을 도출하기 때문입니다.

 

OOP는 4가지 속성을 지니고 있습니다.

이 속성들을 그냥 설명하기보다 OOP를 실행하기 위한 객체를 만드는 방법을 설명하고, 그 과정에 이 속성들이 어떻게 적용되는지를이야기하는 것이 이해하기 더 쉬울 것 같습니다.

 

지금의 자바스크립트는 ES6문법(자바스크립트의 표준 규격을 정하는 ECMA Script의 최신 버전입니다)을 사용합니다.

ES6 문법에서는 Class가 도입되었는데요, Class의 정의는 객체(인스턴스)를 생성하기 위한 템플릿입니다.

쉽게는 틀이라고 말할 수 있겠습니다.

 

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

위의 코드는 각기 다른 Rectangle 들을 찍어내기 위한 기본적인 틀이 되는 Rectangle 클래스입니다.

Class를 가지고 세부사항을 기입하면 Object(객체)를 만들 수 있습니다.

세부사항은 Class가 가지고 있는 constructor에 정의하여 줍니다.

 

 

위의 Rectangle Class와 기타 예시를 참고하면서 OOP의 4가지 속성을 설명하겠습니다.

 

1. 캡슐화 (Encapsulation)

외부에서 클래스에 주어지는 속성들을 모아놓습니다_캡슐화 합니다.

데이터 구조와 데이터를 다루는 방법들을 묶어놓는다고 설명할 수 있습니다.

클래스의 청사진에 맞지 않는 정보들을 클래스의 입력 조건에 맞게 정리하여 하나의 Object에 담아줍니다.

또한 캡슐화에 성공하면 자연스럽게 은닉화도 진행됩니다.

은닉화는 의도하지 않은 / 고의적인 정보의 수정을 막아줍니다. 위의 Rectangle Class 를 예로 들면

Rectangle Class 내부의 constructor를 거쳐야만 this에 해당하는 객체 내부의 height값과 width값을 핸들링할 수 있습니다.

 

 

2. 상속 (Inheritance)

상위 개념의 특징을 하위 개념이 물려받는 것입니다.

상속성은 객체 지향 프로그래밍과 절차 지향 프로그래밍을 나누는 중요한 분기입니다.

핸드폰이라는 부모 Class가 있고 Class 핸드폰은 USB-C 타입을 사용하는 속성이 있다고 할 때

이어폰 구멍을 없앤 핸드폰-Z라는 하위 개념을 만들면 부모 개념인 핸드폰의 속성 - USB-C - 을 무조건 가진 상태에서 이어폰 구멍을 없앤 속성이 추가된 상태로 생겨나게 됩니다.

 

 

3. 추상화 (Abstraction)

공통의 속성이나 기능을 묶어 이름붙이는 것을 의미합니다.

상속성에서 이야기한 핸드폰을 예로 든다면,

핸드폰을 전자기기, 전화기 등 더 큰 개념으로 묶는 것을 추상화한다고 할 수 있습니다.

 

 

4. 다형성 (Polymorphism)

다형성은 상속을 통해 기능을 확장하거나 변경하는 것을 가능하게 해 줍니다. 이를 통해 코드의 재사용, 코드길이 감소가 되어 유지보수가 용이하도록 도와주는 개념입니다.

같은 동작이지만 다른 결과물이 나오는 것이 다형성입니다.

자바스크립트에서 나타나는 다형성의 특징으로는 오버라이딩이 있습니다.

오버라이딩은 상위클래스에서 상속받은 클래스가 상위클래스에서 만들어진 메서드를 자신의 입맛대로 다시 재창조해서 사용하는 것으로, 서로 다른 객체가 같은 행위를 하지만 용도와 목적에 부합하여 다양한 기능수행과 처리, 결과를 낳을 수 있습니다.

 

 

 

ES6 문법에서 Class가 도입되면서 객체 지향 프로그래밍에 사용되는 '정형화된 모델' 을 만들기가 더 용이해졌지만, ES6 문법을 쓰기 전에도 JavaScript에서 객체 지향 프로그래밍을 하기 위한 시도가 있었습니다. Class의 기능을 하는 Object를 만들려면 어떻게 해야 할까요?

 

 

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

1. Functional _ 함수를 이용해서 찍어내기

var Car = function() {
  var someInstance = {};
  someInstance.position = 0;
    // Car 함수가 실행되어 나온 인스턴스의 position 초기값은 항상 0
  someInstance.move = function() {
    this.position += 1;
  }
  /* 여기서의 this는 메소드에 쓰였기 때문에 온점 왼쪽의 someInstance가 this이고
     someInstance.move의 실행 결과는 someInstance.position 값 + 1이다. */
  return someInstance;
}


var car1 = Car();
var car2 = Car();
car1.move();
// 이렇게 car1, car2를 Car 함수를 이용해 찍어낼 수 있다.
// car1.move() 가 한번 실행되었기 때문에 console.log(car1.position) === 1 이다

 

2. Functional Shared_

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

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

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

 

Functional 방식에서는 인스턴스를 생성할 때마다 모든 메소드를 각각의 인스턴스들에게 할당하므로 메모리를 많이 잡아먹지만 Functional Shared 방법에서는 메소드를 담아줄 객체의 주소만 참조해서 사용하기 때문에 메모리 효율이 좋아집니다.

 

3. Prototypal

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

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

var car1 = Car(5)
var car2 = Car(10)

Object.create 함수를 사용합니다.

Object.create는 특정 객체를 프로토타입으로 하는 객체를 생성해주는 함수입니다.

 

4. Pseudoclassical

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

Car.prototype.move = function() {
  this.position += 1;
};
// 작성 끝. 찍어낼 때 new 생성자만 붙여주면 된다
var car1 = new Car(5);
var car2 = new Car(10);

new 생성자를 사용한다는 점을 유의해야 합니다. 제일 많이 쓰이는 방법입니다.

 

 

JavaScript에서 Prototype은 무엇이고 왜 사용해야 하는지?

ES6 등장 이전의 자바스크립트는 객체 지향 언어이지만 객체 지향 프로그래밍의 주체가 되는 Class 가 없는 대신 프로토타입이라는 것이 존재했습니다. ES6에서 Class 문법이 추가되긴 했지만 문법이 추가되었을 뿐이지, 자바스크립트가 Class 기반으로 바뀌지는 않았습니다. 때문에 자바스크립트를 객체 지향 언어이자 프로토타입 기반 언어라고 합니다.

클래스가 없으니 기본적으로 상속 기능도 존재하지 않습니다. 대신 프로토타입 기반으로 상속 기능을 흉내내도록 구현해 사용하였습니다. 

 

프로토타입은 생성자 함수의 prototype을 생성된 객체 모두 똑같이 가지는 숨겨진 프로퍼티입니다.

기본적으로 프로토타입 생성을 위한 함수를 통해 생성된 인스턴스(객체) 에서 어떤 값을 탐색하면 먼저 인스턴스(객체) 내부에서 탐색한 뒤, 그 곳에 찾는 값이 없다면 자동으로 부모라 할 수 있는 prototype의 오브젝트 (__proto__)를 탐색해 값을 찾아옵니다.