Javascript 객체 지향 프로그래밍 (Object Oriented Programming, OOP)

설강·2020년 9월 9일
4

javascript

목록 보기
7/8
post-thumbnail

1. 객체 지향 프로그래밍이란?

Object Oriented Programming (객체 지향 프로그래밍) 는 프로그램 설계 방법론의 일종이다.

프로그래밍 할 때 프로그램을 단순히 데이터와 처리 방법으로 나누는 것이 아닌
객체 라는 단위로 나누고 이를 서로 상호작용할 수 있게 만들어 역할을 수행 할 수 있게 만든다.

그래서 이를 사용하기 위해 다른 언어에서는 Class 라는 문법을 제공하고 있는데
물론 Class 가 없다고 객체가 아닌 것은 아니다.

Javascript 에서는 Prototype을 사용하여 객체를 표현하고
C Language 와 Golang 에서는 struct(구조체) 를 사용해서 객체를 표현한다.

그리고 이러한 객체 지향 프로그래밍에서 4가지의 특징이 있다.

  1. 캡슐화 (Encapsulation)
    변수와 함수를 하나로 묶고 필요에 따라 접근 권한을 나누어 외부에서 함부러 접근하지 못하게 제한을 두어 객체의 손상을 방지한다.
    이에 따라 내부 구현 내용을 감추어 외부에서 확인 할 수 없도록 정보 은닉 도 포함되게 된다.

  2. 추상화 (Abstraction)
    객체들이 사용하는 공통적인 변수와 함수들을 따로 묶는 것 을 말한다.
    예를 들어 말, 강아지, 고양이가 존재한다고 치면
    이 3가지의 동물들이 공통적으로 수행하는 행동 중 숨쉬기, 걷기, 달리기 등등이 있을 것이고
    다리 개수, 성별 등 공통 적으로 가지고 있는 특징들도 있다.
    이렇게 공통적인 행동과 특징들을 가지고 하나의 객체를 정의 하는 과정 을 추상화로 볼 수 있다.

  3. 상속 (Inheritance)
    자식 객체가 부모 객체의 변수와 함수를 그대로 물려 받을 수 있는 것을 뜻한다.
    예를 들어 동물이라는 객체에 달리기, 숨쉬기 함수가 있다면
    강아지, 고양이 객체를 만들 때 동물 객체를 상속 받아
    강아지, 고양이 객체에서는 달리기, 숨쉬기 함수를 따로 구현하지 않고
    동물 객체의 달리기, 숨쉬기 함수를 쓸 수 있다.

  4. 다형성 (Polymorphism)
    같은 객체임에도 상황에 따라 다르게 동작 할 수 있는 것을 뜻한다.
    오버로딩 (Overloading) 이나 오버라이딩 (Overriding) 같은 것을 사용하여 객체를 상황에 따라 다르게 사용 할 수가 있는 것이다.

  • 오버로딩 (Overloading) : 같은 이름의 함수명을 가지면서 매개 변수의 유형과 개수를 다르게 만들어 쓸 수 있다. (Javascript에서는 변수 타입이 자유롭기 때문에 사실상 없는 개념)
int sum(int n1, int n2) {
  return n1 + n2;
}

int sum(int n1, int n2, int n3) {
  return n1 + n2 + n3;
}
  • 오버라이딩 (Overriding) : 부모 객체가 가지고 있는 함수를 자식 객체가 해당 함수를 재정의해서 사용할 수 있다.
class Person {
  eat() {
    console.log("밥 먹을거야");
  }
}

class Kim extends Person {
  eat() {
    console.log("난 밥 싫어 라면 먹을거야");
  }
}

let kim = new Kim();
kim.eat(); // 난 밥 싫어 라면 먹을거야

2. Javascript에서 객체 생성 방법

2-1. Functional

사실상 함수 내부에서 오브젝트에 값을 다 담아서 반환해주는 것과 같다

let Person = function(name, age) {
  let obj = {};
  obj.name = name
  obj.age = age
  obj.print = function() { console.log(this.name + " " + this.age); }
  return obj;
}
var lee = Person("Lee", 24);
lee.print(); // Lee 24

2-2. Functional Shared

객체 메소드를 하나만 생성해주고 생성되는 객체에서는 생성된 객체 메소드를 참조하여
메모리 사용 효율을 높인다.

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

let method = {};
method.eat = function() {
  console.log(`${this.myfood}를 먹을거야`);
}

let Person = function(food) {
  let obj = { myfood: food };
  extend(obj, method);
  return obj;
}

let my = Person("Apple");
my.eat(); // 난 Apple를 먹을거야

2-3. Prototypal

Object.create 를 사용하면 특정 객체를 프로토타입으로 하는 객체를 생성 할 수 있다.

let method = {};
method.eat = function() {
  console.log(`${this.myfood}를 먹을거야`);
}

let Person = function(food) {
  let obj = Object.create(method);
  obj.myfood = food;
  return obj;
}

let my = Person("Apple");
my.eat(); // 난 Apple를 먹을거야

2-4. Pseudoclassical

아마 이 방법이 일반적으로 많이 사용하는 Class를 생성하는 방법일 것이다.
다만 위와 방법과 다른 점은 new 키워드를 사용해서 객체를 생성해야 한다.

let Person = function(food) {
  this.myfood = food;
}

Person.prototype.eat = function() {
  console.log(`오늘은 ${this.myfood}으로 먹어볼까?`);
}

let my = new Person("볶음밥");
my.eat() // 오늘은 볶음밥으로 먹어볼까?

3. 프로토타입

3-1. 프로토타입이란?

Javascript에서의 프로토타입은 무엇일까?
뜻을 찾아 보게 되면 일반적인 의미로 원형 이라는 뜻을 가지고 있다.
이것을 객체에 의미를 부여해보면 객체의 원형자신을 만들어낸 객체의 원형을 뜻한다.
또한 자신을 만들어낸 객체의 원형이 있다면 객체의 원형에서 만들어질 객체도 있지 않은가?
그래서 객체의 원형에서 만들어질 객체자신을 통해서 만들어질 객체의 원형의 뜻도 지닌다.

그리고 Javascript에서는 이러한 프로토타입을 표현하는 용어가 있다.

  • Prototype Link : 자신을 만들어낸 객체의 원형
  • Prototype Object : 자신을 통해서 만들어질 객체의 원형

이러한 용어를 이해하기 위한 예를 보자

function Person() {}
console.dir(Person);


그리고 여기서 prototype 속성과 __proto__ 속성을 확인 할 수가 있다.
해당 속성에 내용은 직접 확인해 보도록 하고 이들의 관계에 대해서 알아보자.

이들의 관계에 대해서 표로 표시하자면 아래 이미지와 같다.

[출처 : https://mygumi.tistory.com/312]

표에 나온 용어들이 무엇을 나타내는지 정리 해보자.

  • __proto__ : 자신을 만들어낸 객체의 원형
  • constructor : 생성자를 뜻하며 자신을 만들어낸 객체
  • prototype : 자신을 원형으로 만들어진 새로운 객체

__proto__ 속성은 Prototype Link로 연결되어 자신을 만들어낸 객체를 연결 시키고
constructor 속성은 Prototype Object로 연결되어 자신을 만들어낸 객체에 연결 시키고
prptotype 속성은 Prototype Object로 연결되어 자신이 만들어 낸 새로운 객체에 연결 시킨다.

그리고 Prototype Object 는 생성 당시에 객체가 가진 정보를 토대로 새로운 객체를 생성한다.

예를 들면

let My = function(name) {
  this.name = name;
  this.show = function() { console.log("First " + this.name); }
}

My.show = function() { console.log("Second " + this.name); }

let my = new My("Lee");
my.show() // "First Lee"

해당 코드처럼 중간에 Second로 변경 해주었지만 그대로 First로 나오는 것을 확인 할 수 있다.

이는 My 객체의 Prototype Object가 My 객체 생성 당시의 정보인 show를 복제 하기때문에
My 객체를 이용해서 새로 만든 객체의 경우 First를 출력하는 show 메소드가 그대로 복제 된것이다.

3-2. 프로토타입 사용 이유

Javascript는 Class 라는 개념이 존재 하지 않는다.
물론 최근에는 Class 라는 키워드가 추가되어 클래스처럼 표현 할 수 있지만
이는 문법만 매핑 해준 것이고 동작 방법은 프로토타입을 활용하여 객체를 생성하는 것과 같다.

따라서 결과적으로 프로토타입의 사용 이유는
Javascript는 Class라는 개념이 존재 하지 않기 때문에 프로토타입 이라는 객체를 활용하여
이를 Class 처럼 표현하기 위해 사용한다고 볼 수 있다.

4. ES6 Class 맛보기

Javascript에서는 함수를 이용해서 클래스를 구현했었지만
ES6에서 Class 키워드를 지원해서 해당 문법을 이용해서 클래스같은 클래스를 만들 수 있다.

let Person = function(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.show = function() {
  console.log(`Hello My name is ${this.name}, My age is ${this.age}`);
}

let person = new Person("Lee", 24);
person.show(); // Hello My name is Lee, My age is 24

//////////////////////////////////////////////////////////////////////
// TO CLASS

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  show() {
    console.log(`Hello My name is ${this.name}, My age is ${this.age}`);
  }
}

let person = new Person("Lee", 24);
person.show(); // Hello My name is Lee, My age is 24

이렇게 Person Class를 만들 수 있으며
constructor는 생성자 함수로서 객체의 변수를 초기화 하는 함수이다.
그외에 코드에서 볼 수 있는 것은 함수를 작성 할 때 따로 function 키워드를 작성하지 않아도 된다.

그다음엔 상속을 해보자.

class Animal {
  constructor(name) {
    this.name = name;
  }
  
  whois() {
    console.log(`My name is ${this.name}.`);
  }
}

class Cat extends Animal {
  constructor(name) {
    super(name);
  }
}

let myCat = new Cat("Bab");
myCat.whois(); // My name is Bab.

Class 키워드를 사용하여 상속을 할 때에는 extends 키워드를 쓴 다음 상속할 클래스 이름을 적는다.
그리고 자식 클래스의 생성자에서 super 키워드를 써서 부모 클래스 호출한다.
이러한 과정을 거쳐 부모 클래스의 내용을 자식 클래스가 상속받아 사용 할 수 있다.

profile
Be a Full Stack Developer

1개의 댓글

comment-user-thumbnail
2020년 9월 9일

이 글이 올라오기만을 기다렸습니다... 지식도둑질 해야지

답글 달기