{TIL} OOP, 객체지향프로그래밍

ytwicey·2020년 10월 28일
0

TIL

목록 보기
3/23
post-thumbnail

오늘은 주제가 객체지향프로그래밍, Object-Oriented Programming이라서
앞에 브라켓을 curly로 넣어봤다... 헷...(늘 평소와 같이 의미없는 말..)

Cominciamo

이전에 블로그에서 언급했듯이 객체라고 하면 나에겐 아직도 {}보다도, Object보다도 플라톤과 아테네학당이 먼저다. 그런데 익숙해지면 아는 것이 된다는 말, 시간이 지나면 자연스럽게 아르키메데스처럼 유레카를 외치게 된다는 말에 따라, 이제는 OOP도 시간이 지나면서 점점 익숙해지는 것 같다. 다 이해는 못했지만, 그래도 이해한대로(?) 적어보려고 한다. 틀린 게 있으면 언제든 댓글로!


1. 정의

객체지향프로그래밍, Object-Oriented Programming은 일종의 프로그래밍을 하는 방법/방법론을 의미한다.

1.1 내가 정리한 OOP에 대한 생각(?)

이 객체지향프로그래밍은 기본적으로 프로그래밍을 쉽게, 빠르게 하기 위한 방법으로 생각된다. 객체를 내가 본 강의에서는 thing이라고 생각하라고 했는데, 강아지와 시츄를 생각하면 좀 더 쉽지 않을까.

강아지는 네 다리로 걷고, 눈코입이 있고, 꼬리가 있으며, 매우 귀엽다😍. 시츄도 네 다리로 걷고, 눈코입이 있고, 꼬리가 있으며, 매우매우 귀엽다😍😍. 이러한 공통점이 있는데, 모든 강아지가 시츄가 아닌 것처럼, 시츄는 시츄만의 특징이 있다. 우선 시츄는 코가 짧고, 다리도 짧고, 털이 잘 날리지 않으며, 순둥하고, 생각보다 똑똑하다.

우리에게 시츄를 그려보세요 라고 하면 보통 강아지를 그릴 때를 기반으로 해서 그림으로 그리고, 그리고 거기에 시츄의 특징을 더한다.

이건 강아지와 시츄의 예 뿐만 아니라, 꽃을 그려도 마찬가지고, 자동차를 그려도 마찬가지다.

우리는 벤츠를 그릴 때 자동차의 기본형(바퀴가 네 개, 문이 4개, 세단형태)을 그리고 가장 중요한 걸 그린다. 그거슨 바로, 삼각별, 그리고 AMG.....(정성스러운 뻘소리)

그러니까 이 예에서 강아지가, 자동차가, 꽃이 일종의 틀이 되고, 객체라고 부를 수 있는 거다. 그러니까 자동차라는 객체로, 미니도, 비틀도, 애스턴마틴도, 벤츠 C63 amg도 만들 수 있고, 조물주가 강아지라는 틀이 있으면, 그레이하운드도, 시츄도, 포메라니안도 만들 수 있다.

이런 예처럼 OOP도 마찬가지다.
비슷한 작업을 예를 들어 1만 번 다른케이스에서 작업해야 한다면, 이를 객체로 만들어서 일을 쉽게 하는 방법론이 객체지향프로그래밍이라고 생각하면 된다.

아주 간단한 예로는, Array가 있다. 내가 프리코스때부터 엄청나게 많이 쓰던 배열. 그런데 항상 궁금한게 있었다. 왜 typeof arr === object인가.

이 질문을 이해하고 싶었다.
그런데 OOP를 보면서 아주 살짝 이해가 가기 시작했다.

다시 배열로 돌아가서 이야기하면 기본적으로 수 만 가지의 케이스에서 우리는 배열을 쓴다.
배열은 순서에 따라 인덱스에 맞춰 자료를 저장하고, 그 길이를 가진다. 그리고 그 배열의 0이라는 인덱스에 자료를 삽입하고, 삭제하고, 위치를 찾고, 배열을 자르는 등의 다양한 행위를 가한다. (왠지 이 말 때문에라도 객체 같음. 행위를 하는게 아니고 가하는 거니까... 네.. 지나가세여)

배열의 속성(property)는 길이가 있다는 것이고,
배열의 기능(function)은 삽입, 삭제 등이 있다.
이것을 배열이라는 object (?? 이렇게 표현해도 되나.)에 붕어빵 틀처럼 미리 지정을 해두는 것이다.

그래서 이미 프로토타입에 지정된 기능(=메소드)이기 때문에 그것을 받아 편하게 쓸 수 있는거다.

const arr = [1,2,3,4,5]
arr.length
arr.push(7)
arr.pop()
arr.shift()
arr.slice()

2. 표현 & 방법

이 OOP를 만드는 방식에는 여러가지 방법이 있다. (자바스크립트 기준)
물론 지금은 ES6에서 Class를 이용한 방법으로 생각보다 심플하게 쓸 수 있지만 이전에는 다음에 소개할 방법으로 작성했다고 한다.

2-1. 표현 (내가 이해한...)

  • class : 아파트를 예로 들면 어떻게 만들겠다는 설계도면 정도로 이해하면 된다.
    그러니까 만약에 Car라는 클래스가 있으면 이 Car의 속성과 기능에 대한 패키지를 부르는 명칭이다. 이 안에는 색깔, 사이즈, 스피드, 운전하기, 속도 높이기, 연료넣기 등의 속성과 기능이 패키지로 만들어져서 들어가 있고, 나중에 인스턴스를 만들때 똑같이 적용된다. 설계도면!

  • instance : 클래스를 통해 만들어진 철수네! 정도로 생각하면 된다. 강아지로는 시츄, 꽃은 장미, 차로는 미니! 실제로 클래스를 통해 만들어진 객체!
    - instantiation : 인스턴스를 만드는 과정!

  • prototype : 자신을 통해 만들어질 객체의 원형이다. 그래서 모델하우스 정도로 이해하면 되지 않을까. 모델하우스에서 화장실도 써보고, 방에 들어가서 티비도 켜보고, 세탁기는 어디에 넣을지 고민도 해보고...

    Array.prototype.push()를 예를 들면, 배열의 뒤에 값을 삽입하는 함수(메소드)인데, Array.prototype이라는 모델하우스에서도 쓸 수 있고, 이 후에 철수네인 arr=['a', b']에서도 똑같이 쓸 수 있다.

  • constructor : 생성자라고 하는데, 아파트 공사장 인부쯤... 생각하면 될거 같다. 실제로 인스턴스를 만들 때, 이 컨스트럭터 생성자 함수에 의해서 만들어지는데, 설계도면 보고 아파트 짓는 건 공사장 인부들이니까.

  • ._proto__ (prototype link라고도 하나보다!)
    (원래 앞의 언더바가 2개여야 하는데, 벨로그에서 그렇게 쓰면 사라짐...🤬)
    : 프로토타입 체인이라고 한단다. 상위 객체(상위 프로토타입)로 연결 해주는 것 같음...

2-2. 형태

0. ES6 Class 이용

우리가 자료구조 스프린트때 쓴 방식이 이런 방법!
<아래와 예시가 다름. 이건 그냥 내가 막 쓴거...>

1. functional

let car = function(){
  let someInstance = {}; 
    someInstance.postion = 0
    someInstance.forward = function(){
    someInstance.postion += 1;
    }
    return someInstance
    }

이렇게 함수로 선언해서 인스턴스를 생성하는 방법이 있었다.(그냥 있었구나, 정도만 알아두면 될듯한데...)

2. functional shared

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

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

let car = function(postion){
  let someInstance = {
      postion: postion
  };
  extend(someInstance, someMethods);
  return someInstance
}

위 두 방식의 차이점은 메모리를 어떻게 쓰냐가 다르다.

왼쪽이 functional인데 총 3개의 인스턴스가 6개의 메모리를 쓰고, 오른쪽은 functional shared이고, 4개의 인스턴스가 5칸의 메모리를 쓴다. 그러니까 functional shared는 someMethods의 메모리 주소만을 참조한다. 효율이 좋아짐!(이렇게 쓸 수 있나? 돈 대비 작업이 많아지는 거니까... 효율적인 것 같음)

3. Prototypal (발음하기 디따어렵네.. 프로토티팔...😳)

let someMethode ={};
  someMethode.move = function(){
  this.postion += 1
};

let car = function(position){
  let someInstance = Object.create(someMethode);
  someInstance.postion = position
  return someInstance
}

위 2개의 방법보다 간단해졌는데, Object.create()를 썼음. Object.create는 특정 객체를 프로토타입으로 하는 객체를 생성하는 함수.

첫번째 인자로 들어가는 프로토타입 객체를 가지고 프로토타입을 생성한다.

그냥 특정 객체를 카피&페이스트 한다고 생각해도 좋다고 그랬음... 그러나 0번 방법으로 하는 것이 요즘 대세라고 했음 (난 몰라.. 그랬다 누가... 누군지 궁금하면 오백원..)

4. Pseudoclassical

var car = function(position){
this.position = position
}

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

이렇게 하면 앞선 3가지의 방식보다도 훨씬 코드가 짧고 간결해지는데, 이렇게 쓸때는 꼭 앞에 new 키워드를 사용해 줘야하고(0번 방법과 공통점!), ES6에서 쓰는 방식과 내부적으로 동일한 원리도 작동한다.


3. OOP의 특징

객체지향프로그래밍이 가지는 4가지 특성이 있다. 4가지 특성은 영어로는 대따 어려운데, 모쉬오빠의 설명 듣고가자(feat.영어) 다음과 같다.

  • Encapsulation : 단어를 이해하면 된다. En(안에)/Capsul(캡슐)/ation(명사), 캡슐 안에 넣는 것. 캡슐은 타임캡슐 할 때..😅 아니면... 내복약도 캡슐이니까...😅 그런 것처럼 안에 다 때려 넣어서 작업을 쉽게 할 수 있게 만든다는 것

  • Abstraction : 추상화라는 뜻인데, 사실 추상화, 그림 이야기 같고 넘 어렵지 않나... 그냥 동의어를 찾아보면, notional, conceptual 이라고 뜬다. 다시 배열로 돌아가보자. 배열로 돌아가서 생각해보면 혹시 배열에 자료를 삽입 할 때마다 push를 구현해서 쓰는 사람이 있나? 그 코드를 난 다 외우고 있다 손! ✋🏻🤚🏻(그렇다면 박수를 드립니다. 👏🏻). 여튼 그런 복잡한 건 뒤로 하고 쓴다는 뜻이다.

  • Inheritance : 부모로부터 자녀가 일부 특징을 상속받는 것을 의미한다. 혹은 다른 프로토타입으로부터 또 다른 프로토타입이 속성이나 메소드를 상속 받을 수도 있음. 추후 기술 하겠음.

  • PolyMorphism : Poly는 많다는 뜻이고, Morph는 형태라고 해석해서 다형성이라고 이야기 하고, 그래서 OOP가 다양한 케이스들을 한번에(?) 처리 할 수 있다고 간단하게 이야기 한다.
    그런데 사실 Morph는 언어의 원형을 따지자면, Morph는 나비의 날개의 색이 빛의 각도에 따라가 조금씩 변하는 것을 이야기 한다. 그래서 점진적으로 달라지는 형태를 말하는데, 예를 들어 개와 고양이와 말과 오리에게 짖으라고 하면 각각 다른 소리를 내는 걸, class && extends && super를 통해 심플하게 처리 할 수 있다는 것.

4. Subclassing & Prototype Chain

OOP의 특징 중에서 가장 큰 이점은 상속이 가능하다는 거다. 부모에서 자식으로 상속이 가능하다.
그런데 강의를 보니까 Human과 Student의 클래스를 만들어서 Human의 서브 클래스로 Student을 지정하는 걸 보니, 내 생각에는 계층이 없는 두 개의 클래스를 가지고 서브로 넣어서 부모-자식 관계를 만든다음 필요한 부분을 상속해서 쓸 수도 있는 것 같다. 그래서 이름을 subclassing 이라고 하는 것 같고..

아래의 예는 human과 student 클래스를 각각 만들어둔 것이고, 이에 따른 메소드 설정까지 해서 잘 되는 걸 확인 했다.

그리고 나서 이렇게 extends와 super를 사용해서 상속할 수 있음.
상속을 하게 되면 Human 이라는 클래스를 가지고 Student로 클래스를 확장시켜 메소드를 사용할 수 있게된다.

이렇게 Extends로 상속을 하고 나서, 위의 예시를 기준으로 아래와 같이 표기 된다.

 h instanceof Human //True
 h instanceof Student // true 

Human과 Student의 인스턴스는 맞지만, Human.prototype만 따르고 있는 것을 볼 수 있다.

이런 특징으로 객체지향의 가장 큰 장점인 polymorphism과 inheritance를 알아 볼 수 있는데, 그 예는 아래 링크 중 엘리의 OOP를 참고하면 좋겠다.


Finiamo

객체지향프로그래밍... 이해하고 싶었지만 아직 제대로 이해 안 된 부분도 (엄청) 많고, 여전히 어렵다. 어떻게 쓰는 것 같다 정도의 느낌만 남았다. 하루종일 강의를 얼마나 돌려봤는지 모른다. 블로그를 쓰는 내내 약간 무지개칼라똥을 넷상에 투척하는 느낌이었고, 시간이 지나서 이불킥을 할 내가 너무 부끄러웠다. 부끄럽지 않는 글을 쓰는 날이 왔으면 좋겠다.


# 참고자료

엘리의 OOP
Prototype Object && Prototype Link 관련 블로그

profile
always 2B#

0개의 댓글