JavaScript

[JavaScript] OOP in JavaScript - 자바스크립트의 객체 지향 프로그래밍

Gray Park 2020. 9. 9. 14:00
728x90
반응형

OOP ( 객체 지향 프로그래밍 ) 은 말 그대로 객체 단위로 쪼개서 프로그래밍을 하자는 것이다. 어떤 이는 이 개념이 단순히 프로그램을 잘게 쪼개는 걸로 오해하여 너무 많은 클래스를 만들어서 협업하는 동료를 힘들게 하기도 한다고 한다.

 

자바스크립트에서는 너무나 많은 객체가 있다. 그래서 조금 다르게 표현하면 OOP를 이해하기 편할 거다.

 

OOP in JavaScript ( 자바스크립트의 추상화 프로그래밍 )

객체 지향 프로그래밍 이라는 말 자체가 Object Oriented Programming 을 직역한 거다. 좀 더 쉽게 이해하자면 그냥 현실 세계의 무언가를 추상화하여 부품단위로 쪼개 넣어준 뒤 하나로 합치듯 구성하는 것이다.

 

스마트폰을 예 들어 보자. 스마트폰을 구성하고 있는 보편적인, 공통적인 것들이 있다. 스마트폰을 만들기 위해서는 아래의 것이 기본적으로 포함되어야 한다.

  • 정전식 터치 디스플레이
  • 내장 스피커
  • 내장 마이크
  • 충전단자
  • 볼륨조절 버튼
  • 전원버튼
  • ...etc

어차피 모두에게 공통되는 건데 각자 만들게 되면 아래와 같다.

하나의 스마트폰을 만들 때마다 새로운 디스플레이, 스피커, 마이크, 파워버튼 등을 만들어 추가한다. 심지어 같은 사양의 같은 이름의 같은 폰이라도 하나하나 새로 만들어 줘야하는 고강도 수작업이 될 것이다!

 

그런데 우리 모두가 알다시피, 스마트폰의 제조공정은 기계가 열일한다. 기계가 공통된 디스플레이, 스피커, 마이크, 파워버튼을 이미 만들어 두었다. 우리는 이걸 다시 합쳐서 하나의 기계로 조립해주는 또 다른 기계에게 명령만 하면 된다.

 

이게 바로 상속이다.

// 스마트폰 공장을 class로 선언
class SmartPhone{
  constructor(name) {
    this.name = name;
  }
}

// 스마트폰 공장에, iPhone을 만들라고 명령
const iPhone = new SmartPhone('iPhone');
// iPhone 확인
console.log(iPhone.name);
// "iPhone"

 

마찬가지로 다른 모든 기능을 Method의 형태로 구현하여 새롭게 생성되는 모든 스마트폰에서 동일한 기능을 하도록 만들어줄 수 있다.

// 스마트폰 공장을 class로 선언
class SmartPhone{
  constructor(name) {
    this.name = name;
  }
  
  printName() {
    console.log(this.name);
  }
}

// 스마트폰 공장에, iPhone을 만들라고 명령
const iPhone = new SmartPhone('iPhone');

// iPhone 확인
console.log(iPhone.name); // "iPhone"

// SmartPhone의 메소드 사용
iPhone.printName();
// "iPhone"

 

Object.create(proto)

 

 

이 친구는 좀 다르다. 클래스의 개념으로 접근하면 이해가 안되는 친구다. 첫 시작부터가 Object이니 당연히 그럴 수 밖에...

// 스마트폰 공장을 class로 선언
class SmartPhone{
  constructor(name) {
    this.name = name;
  }
  
  printName(){
    console.log(this.name);
  }
}

// 스마트폰 공장에, iPhone을 만들라고 명령
const iPhone = Object.create(SmartPhone);
iPhone.name = "iPhone";
iPhone.printName();
// iPhone.printName is not a function

그럼 Object.create은 어떻게 사용하는 걸까?

 

이름처럼 Object로 접근해보자.

const person = {
  isHuman: false,
  printIntroduction: function() {
    console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
  }
};

const me = Object.create(person);

me.name = 'Matthew'; // "name" is a property set on "me", but not on "person"
me.isHuman = true; // inherited properties can be overwritten

me.printIntroduction();
// expected output: "My name is Matthew. Am I human? true"

person 이라는 객체에는 isHuman과 printIntroduction 이라는 key가 있고, 각각 boolean과 함수를 value로 가지고 있다.

 

이 때 새로운 변수 me 에 person이라는 객체를 인스턴스"처럼" 할당한다.

이 때 me를 열어보면 아래와 같다.

person이라는 객체를 __proto__에 담아 가지고 있다. 아래는 person 객체이다.

이제 뒷부분을 마저 해주자.

me.name 에는 'Mattew'를 할당해 주었고, me.isHuman 에는 true를 할당해주었다.

그리고 여전히 __proto__ 로 person 객체를 가지고 있다.

 

Object.create()는 기존 객체를 건들지 않으면서 몇 가지 변화할 때에 사용하는 메소드가 되겠다.

 

그렇다면 어떤 때에 Object.create()을 사용해줄 수 있을까?

내가 생각한 예는 회원정보를 관리할 때이다. 아래에서는 userDefault 라는 객체를 선언하여 이름, 나이, 성인여부, 음주가불을 프린트하는 함수를 담고 있다.

const userDefault = {
  name: "didn't have name",
  age: 0,
  isAdult: function () {return this.age > 19},
  printInfo: function () {
    console.log(`${this.name} ${this.isAdult ? "can" : "can't"} drink a soju`);
  }
}
const me = Object.create(userDefault);
me.name = 'gray';
me.age = 28;
me.isAdult = me.isAdult();
me.printInfo();

const you = Object.create(userDefault);
you.name = 'elen';
you.age = 17;
you.isAdult = you.isAdult();
you.printInfo();

보다시피 me라는 새로운 객체는 userDefault를 기반으로 만들어진 새로운 객체이며, 새로 할당되어도 기존의 객체에는 영향을 주지 않는 모습을 볼 수 있다.

 

이것은 자바스크립트에서 사용하는 객체도 OOP의 취지에 부합하게끔 작성될 수 있음을 보여준다.

 

 

Super

super syntax는 클래스와 객체를 상속받는 자식 클래스를 생성할 때 사용하는 문법으로, 키워드 하나로 constructor 혹은 method를 가져올 수 있다.

위의 사진에서 Square 클래스는 Rectangle 클래스를 상속받으며, constructor에 super 문법을 사용하는 것으로 height와 width을 한 번에 받는 걸 보여준다.

상위 클래스를 상속받은 자식 클래스답게 부모 클래스에서 정의해준 area도 잘 가져온다.

 

객체 또한 마찬가지로 상속이 가능하다.

아래의 코드에서 super 문법과 Object.setPrototypeOf 메소드를 이용해 obj2가 obj1의 method1을 상속받는 모습이다.

let obj1 = {
  method1() {
    console.log('method 1');
  }
}

let obj2 = {
  method2() {
    super.method1();
  }
}

Object.setPrototypeOf(obj2, obj1);
obj2.method2(); // logs "method 1"

 

OOP를 한 번에 이해하는 건 결코 쉽지않다. 상속의 개념과 그 안에서 사용해야하는 다양한 문법이 존재한다.

그러나 한 번 확실하게 해두면, 추상화가 사용되는 수많은 곳에서 응용할 수 있으리라.

 

자주 사용해보면서 체득할 수 있길....

728x90
반응형