백고등어 개발 블로그
객체지향 프로그래밍(OOP, Object-Oriented Programming) 개념과 프로토타입 상속 본문
객체 지향 프로그래밍(OOP) : 프로그램을 어떻게 설계해야 하는지에 대한 일종의 개념이자 방법론.
- 절차적 프로그래밍 (Procedural)
초기 프로그래밍 방식은 절차적 프로그래밍 방식이었습니다. 입력을 받아 명시된 순서대로 처리한 다음, 그 결과를 내는 것뿐이라는 생각이 지배적이었습니다. 즉, 프로그램 자체가 가지는 기능에 대해서만 신경을 썼지, 이 프로그램이 대체 어떤 데이터를 취급하는 것인가에는 그다지 관심이 없었던 것입니다.
- 절차적 프로그래밍의 문제점
조금만 복잡해져도 순서도로 나타내는 것이 거의 불가능할 정도로 꼬여서 유지보수가 어려울뿐만 아니라 다른사람이 들이 보고 이해하는 것이 불가능.
이 문제를 해결하기 위해 구조적 프로그래밍을 제안하였습니다.
프로그램을 함수단위로 나누고 함수끼리 호출하는 구조적인 방식을 제안 하면서 이러한 위기를 벗어나게 된다. 즉, 큰 문제가 있다고 가정하면 작은 문제들로 나누워서 해결하는 하향식(Top-Down) 방식이라고도 합니다.
하지만 이러한 구조적 프로그래밍에도 문제가 있었습니다.
함수는 데이터의 처리 방법을 구조화 했을뿐, 데이터 자체는 구조화 하지 못했습니다.
이를 극복하기 위해 객체 지향 프로그래밍이 등장 하였습니다.
- 객체 지향프로그래밍 등장
큰 문제를 작은것으로 나누는 것이 아니라, 작은 문제들을 해결할 수 있는 객체들을 만든 뒤, 객체들을 조합하여 큰 문제를 해결하는 상향식(Bottom-Up) 해결법을 도입한 것.
객체
객체를 지향한다는 프로그래밍이라는 뜻에 객체란 무엇일까요?
쉽게말해, 말 그대로 대상을 나타내는 단어라고 생각해봅시다.
그림과 같이 메뉴판, 손님, 바리스타, 커피들처럼 존재하거나 생각할 수 있는 것들을 객체라고 볼 수 있습니다.
이 객체들을 통하여 각 객체와그 객체들간의 관계를 설계하는 것이 객체 지향 프로그래밍입니다.
그런데 객체들 안에는 데이터(상태)와 메서드(행위)라는 것이 들어가있습니다.
예를 들어 손님이고 생각해볼때 커피를 마시고 싶은 상태이면, 커피를 주문한다라는 행위가 들어가있습니다.
클래스
클래스는 틀이라고 생각해보시면 조금 이해하기 쉬우실 겁니다.
객체는 클래스를 실체화 한 것이라고도 표현할 수 있습니다.
이제 그럼 객체를 프로그래밍으로 들여다 보겠습니다.
코드로 살펴보면 상태를 나타내는 데이터, 행위를 나타내는 메서드가 들어있습니다.
좀더 자세히 살펴볼까요??????
왼쪽은 강아지의 틀이고, 속성에는 강아지의 색, 눈의 색, 몸무게, 키 등이 있고 행동에는 앉기, 흔들기, 오기 등의 틀을 만들어봤습니다.
강아지라는 클래스를 만들어 봤습니다.
속성에는 강아지의 색, 눈의 색, 몸무게, 키 등이 있고 행동에는 앉기, 눕기, 흔들기가 있습니다.
이것을 실체화(객체화)를 시키는 코드는 이렇습니다.
boddy라는 강아지를 객체화시켜서 color는 white강아지이며 앉기를 할 수있는 강아지를 객체화 시킨것이라고 생각하면 되고, tori라는 강아지는 브라운색의 눕기를 할줄 아는 강아지입니다.
OOP의 특징
추상화, 캡슐화, 상속성, 다형성이라는 4가지의 개념이 있습니다.
- 추상화(Abstraction)
- 캡슐화(Encapsulation)
- 은닉화(Information Hiding)
- 상속성(Inheritance)
- 다형성(Polymorphism)
추상화(Abstraction)
대상의 불필요한 부분을 무시하며 복잡성을 줄이고 목적에 집중할 수 있도록 단순화 시키는 것입니다. 즉, 사물들 간의 공통점만 취하고 차이점을 버리는 일반화를 통한 단순화라고 볼 수 있습니다.
관심 영역 = 도메인 = 컨텍스트
추상화 = 모델링 = 설계
캡슐화(Encapsulation)
객체 상태를 나타내는 속성 정보를 private하게 관리 하는 것.
직접적으로 속성 정보를 변경하는것 대신에, 메세지를 같은 요청을 보내어 그 응답에 의해 객체의 상태를 변경하게 됩니다.
상속성(Inheritance)
하나의 클래스의 특징(부모 클래스)을 다른 클래스가 물려받아 그 속성과 기능을 동일하게 사용하는 것
재사용과 확장에 의미가 있습니다 (상속은 수직확장, Extension은 수평 확장)
예를 들어 자동차를 만드는 설계도가 있다고 해보겠습니다
우선 자동차 설계도라는 클래스를 통해서 만들 수 있는 것은 무엇일까요??
음... 제가 생각하기엔 이러한 멋진 차들을 만들 수 있을 것 같습니다
물론 조금 더 정확히는 우리가 자동차라고 말할 수 있는 형태만 갖춘 자동차 설계도면 이런 차들은 만들 수 없겠네요!
그렇다면 이런 멋진차를 만들기 위한 설계도를 만들 수 있지않을까요???
네! 바로 여기서 상속이라는 개념이 나옵니다!
상속에는 부모클래스와 자식클래스의 관계가 있는데 어떤게 부모 클래스이고 어떤게 자식 클래스일까요???
부모 클래스는 자동차라고 말할 수 있는 형태만 갖춘 자동차 설계도가 부모 클래스이고 BMW, 벤츠를 만들 수 있는 설계도가 자식 클래스가 됩니다!
이게 무슨말일까요???
한마디로 자식 클래스는 부모 클래스의 속성과 기능들을 모두 가지고 있고 자식 클래스만의 속성과 기능을 추가할 수 있습니다!
즉, 자동차라는 기본적인 틀을 갖춘 설계도에 BMW, 벤츠를 만들 수 있는 특징을 추가한 거라고 생각하시면 됩니다
다형성(Polymorphism)
다형성이란 쉽게, 다양한 형태로 나타날 수 있는 형태라고 볼수 있습니다.
동일한 요청에 대해 각각 다른 방식으로 응답할 수 있도록 만드는 것
이와 같은 다형성의 방식으로 오버라이딩(Overriding), 오버로딩(Overloading)을 지원합니다.
프로토타입을 이용한 상속
자바스크립트에서 프로토타입을 사용하여 상속을 구현하는 방법은 Object.create 메소드를 사용하면 간단하게 구현할 수 있습니다.
(참고 : Object.create 메소드는 IE 9 버전부터 지원됩니다.)
Object.create 를 사용하자
Object.create 매소드는 첫 번째 인자로 생성할 객체의 원본 객체가 될 객체, 두 번째 인자로 새로 생성할 객체에 추가할 프로퍼티를 객체 타입으로 받습니다.
이 메소드에서 중요한 포인트는 객체의 프로토타입 객체를 지정할 수 있다는 것이며, 이 말인 즉슨 객체의 프로토타입 체인을 내 맘대로 만져줄 수 있다는 것입니다.
그럼 이제 Object.create 메소드와 프로토타입을 사용하여 상속을 한번 구현해보도록 합시다!
우선 부모 클래스 역할을 할 SuperClass 생성자 함수를 생성하고, 이 함수의 프로토타입 객체에 say 메소드를 정의했습니다. 그럼 이제 자식 클래스 역할을 할 생성자 함수를 구현하고, 이 두 개의 함수의 상속 관계도 함께 정의해보겠습니다.
이것저것 많이 만진 것 같지만, 막상 하나하나 뜯어보면 별 거 없습니다.
SuperClass.call(this)
Function.prototype.call 메소드는 호출된 함수의 실행 컨텍스트를 첫 번째 인자로 받은 녀석으로 변경합니다. 즉, this의 타겟을 변경하는 것입니다.
즉, SuperClass.call(this, name)의 의미는 부모 생성자 함수의 생성자를 호출하되, 실행 컨덱스트를 자식 생성자 함수로 변경하라는 의미입니다.
위의 코드에센 call 메소드를 사용했지만, 뭐가 됐든 부모 생성자 함수의 실행 컨텍스트만 변경해주면 장땡이기 때문에 apply 나 bind 메소드를 사용해도 상관없습니다.
SubClass.prototype 변경 그 후
Object.create 메소드를 사용하여 SuperClass.prototype 객체를 원본 객체로 하는 새로운 객체를 생성하고, 이 객체를 SubClass의 프로토타입 객체로 할당해주었습니다.
자식 생성자 함수의 프로토타입 객체와 부모 생성자 함수의 프로토타입 객체 간의 프로토타입 체인, 쉽게 말해 부모 자식 관계를 만들어 주는 것입니다.
SubClass.prorotype.constructor 변경
우리는 부모 생성자 함수의 프로토타입 객체를 토씨 하나 안바꾸고 그대로 복제했기 때문에, 새롭게 생성한 자식 생성자 함수의 프로토타입 객체의 constructor 프로퍼티는 여전히 부모 생성자 함수인 SuperClass를 참조하고 있습니다.
하지만 자식 생성자 함수인 SubClass 를 통해 생성된 객체가 SuperClass 를 사용하여 생성된 것처럼 처리되면 안되므로, 다시 constructor 프로퍼티를 SubClass 로 변경해줘야합니다.
이런 과정들을 거치면 다음과 같은 관계가 성립됩니다.
이제 한번 SubClass 생성자 함수를 사용하여 객체를 생성해보고, 제대로 부모 생성자 함수의 속성들을 물려받았는지 확인해보겠습니다.
evan 객체는 SubClass의 프로토타입 객체를 복제해서 정상적으로 생성되었고, evan 객체의 원본 객체와 원본 객체의 원본 객체도 잘 체이닝되어있습니다!
'javascript' 카테고리의 다른 글
바닐라 Javascript import 테스트 시 발생한 에러 (2) | 2022.11.02 |
---|---|
자바스크립트 이터러블, 이터레이터, 제너레이터 (0) | 2022.10.12 |
자바스크립트 splice 메소드 사용시 주의점 (0) | 2020.10.15 |
Javascript 이벤트와 이벤트 중단 (0) | 2020.09.23 |
DOM 노드의 생성, 수정, 삭제 (0) | 2020.09.23 |