JavaScript : 객체 지향 프로그래밍 (OOP)

정관우·2021년 1월 14일
0

## INTRO

객체 지향 프로그래밍 (Object-Oriented Programming, OOP)는 컴퓨터 프로그래밍을 명령어의 목록으로 보는 시각에서 벗어나, 여러 개의 독립된 단위, 즉 "객체"들의 모임으로 파악하고자 하는 컴퓨터 프로그래밍의 패러다임 중 하나이다.  -wikipedia

객체 지향 프로그래밍은 마치 현실 세계를 보는 듯 하다. 현실 그 자체가 말 그대로 독립적인 객체들의 모임이기 때문이다. 지금 이 순간도 나라는 객체는 책상이라는 객체 앞에 앉아, 노트북이라는 객체의 자판을 두드리고 있다. 우리 눈에 보이는 모든 존재들이 객체를 의미한다. 그리고 우리는 그 대상과 상호작용하며 살아가고 있다.

절차 지향 프로그래밍

앞서 INTRO에서 언급한 듯이, 초기 컴퓨터 프로그래밍의 패러다임은 프로그램을 명령어의 모음으로 인식하는 절차 지향 프로그래밍이었다. 프로그램은 단지 기능을 구현하여 결과를 내는 것이 중요하다는 생각이 지배적이었다. 이런 프로그래밍 방법론은 프로그램이 비교적 간단한 기능을 수행하던 시절에는 큰 문제가 되지 않았다. 하지만, 프로그램이 구현하는 기능들이 점점 복잡해지면서 코드는 겉잡을 수 없이 길어졌고 여러 개발자들이 코드를 유지 보수를 할 수 없을 정도로 꼬이는 현상이 발생하였다.

개발자들은 코드를 어떻게 하면 더 효율적으로 쉽게 관리할 수 있을지 고민하기 시작한다. 이때부터, 개발자들의 포커스는 기능에서 데이터로 이동한다. 데이터를 취급하는 방식을 달리하면 코드의 중복을 줄일 수 있겠다고 생각한다. 그래서 등장한 것이 객체라는 데이터 취급 방식이고 패러다임은 절차 지향 프로그래밍에서 객체 지향 프로그래밍으로 전환되었다.

객체 = 속성 + 행위

객체의 대상은 어떤 데이터 타입이든 될 수 있다. 하지만, 크게 두 가지로 구분 지으면 속성을 나타내는 데이터와 행동을 나타내는 데이터로 나눌 수 있다.

1 ) 속성

속성은 어떤 대상의 상태를 표현한다. 예를 들어, 자동차라는 객체가 있다고 가정해보자. 자동차의 색상, 속도, 주행거리 등이 자동차라는 대상의 상태를 나타낼 수 있다.

2 ) 행위

행위은 말 그대로 객체가 행할 수 있는 동작을 말한다. 자동차의 예시를 이어 나가면, 출발하기, 정지하기, 가속하기, 감속하기 등이 자동차라는 객체의 행동이라고 할 수 있다.

실제 프로그래밍에 이 개념을 대입해보면, 속성은 객체의 변수 (객체 - 프로퍼티)에 해당되고 동작은 함수(객체 - 메서드)에 해당한다고 볼 수 있다.

var car = {
  color : red;
  speed : 100;
  distance : 250; // 상태를 나타낸다. -> 프로퍼티
  start : function () {...};
  stop : function () {...};
  accel : function () {...};
  break : function () {...} ; // 행동을 나타낸다. -> 메소드
}

객체 지향 프로그래밍

앞서 말했 듯이, 객체 안의 데이터는 프로퍼티와 메서드로 존재하며 우리는 데이터들을 부품처럼 이용하며 속성과 행위(메소드)의 조합으로 프로그램의 기능들을 자유롭게 구현해낼 수 있다. 객체 지향 프로그래밍에서 모든 데이터는 어떠한 객체에 속한 형태로 존재하는데, 이를 통해 내가 이해한 바로는 프로그래밍이란 작은 객체로 더 큰 객체를 만드는 행위라는 것이다. 작은 단위의 속성 객체가 메소드를 통해 행위(기능)을 할 수 있게 되고 이러한 상호작용을 통해 하나의 프로그램이 만들어진다. 마치, 여러 객체가 합쳐져서 부품처럼 작동하게 되고 부품이 모여 하나의 완제품인 프로그램이 되는 메커니즘이다.

클래스

객체 지향 프로그래밍에서 특정 객체를 생성하기 위한 변수와 메소드를 정의하는 틀로, 객체를 정의하기 위한 상태 (멤버 변수)와 메서드 (함수)로 구성된다.  -wikipedia

위의 정의를 조금 쉽게 풀어쓰자면, 클래스는 특정한 객체를 쉽게 생성하기 위해 만들어 놓은 일종의 메뉴얼이라고 보면 될 것 같다. 앞서 예시로 들은 자동차에서는 속성으로 색상, 속도, 주행거리 등이 있었다. 예시에서는 자동차가 빨간색이었고, 속력은 100km/h, 주행거리는 250km/h였다. 하지만, 어떤 자동차인지에 따라 색상이 노란색일 수도 있고 파란색일 수도 있다. 이처럼, 자동차라는 객체는 색상이라는 값이 여러가지일 수도 있지만, 색상이라는 속성은 모든 자동차가 가지고 있다. 프로그래밍의 관점에서 보자면, 클래스의 변수에 특정한 값을 할당하면 다른 객체와 구분되는 고유한 객체를 만들어 낼 수 있다.

Instantiation (객체를 생성하는 방법)

그렇다면, 이제 객체를 생성하는 방법에 대해 알아보자. JavaScript에 클래스가 나오기 전 4가지 클래스 선언 방식이 있었다. 앞서 말한대로, 클래스는 객체를 생성하기 위한 틀같은 역할을 한다. 이 틀을 통해 만들어진 복제품과 같은 객체를 인스턴스라고 한다.

예를 들어, 앞선 예시인 Car라는 객체를 여러 개 만드는 상황을 가정해보자. Car라는 객체는 편의를 위해 각각 1가지 속성과 메서드를 갖고 있다고 하자. 여기서, 일일이 Car1, Car2 ... 라는 변수를 선언하여 할당하면 매우 번거로울 것이다. 여기서, 필요한게 Instantiation이다. Car이라는 모델을 만드는 공장을 만들면, 비슷한 객체를 쉽게 생성할 수 있을 것이다.

1 ) Functional

: 함수를 이용하는 방식이다.

var car = function () { 
  var instance = {};			// 결과를 담을 객체를 만들어준다.
  instance.position = 0;		// position 속성을 할당.
  instance.move = function () {		// move 메서드 할당.
    this.position += 1;			// move가 실행되면 position이 1 상승한다.
  }
  return someInstance;			// 만들어진 객체를 리턴한다.
}

var car1 = Car (5);
var car2 = Car (4);

2 ) Functional Shared

: 마찬가지로 함수를 이용하는 방식이나, 속성이나 메서드를 객체에 합쳐주는 함수를 추가하였다. 위의 방식과 다른 점은 1번은 인스턴스에 동일한 메서드가 할당되면서 불필요한 중복이 생겨 메모리를 낭비시킨다. 이와 달리, 2번은 인스턴스에 필요한 속성만 부여하고 메서드가 호출될 때 필요한 속성의 주소만 참조하기 때문에 메모리가 더 효율적으로 사용된다.

var extend = function (to, from) { 	// 3-1. instance와 methods 객체를 합치는 extend 함수를 만든다.
  for (var key in from) {
    to[key] = from[key];
  }
};

var methods = {};			// 2. 메소드를 담을 빈 객체를 생성한다. 예제에선 메소드가 하나이지만 여러 메소드를 담을 수도 있다.
methods.move = function () {
  this.position += 1;
};

var Car = function (position) {		// 1. Car 함수를 선언한다. 이번엔 instance 객체에 position 속성을 담아 선언했다.
  var instance = {
    position : position,
  };
  extend(instance, methods); 		// 3-2. Car 함수 내부에서 두 객체를 합쳐준다.
  return instance; 			// 4. 만들어진 객체를 리턴한다.
};

var car1 = Car (5);
var car2 = Car (4);

3 ) Prototypal

: 2번 방식과 코드가 거의 비슷하지만, Object.Create() 함수를 사용하여 extend 함수 없이 바로 객체를 완성시켰다. 프로토 타입 객체는 잠시 후에 알아보자.

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

var Car = function (position) {		
  var instance = Object.create(methods);
  instance.position = position;
  return instance; 	
};

var car1 = Car (5);
var car2 = Car (4);

4 ) Pseudoclassical

:

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

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

var car1 = new Car (5);
var car2 = new Car (4);
profile
작지만 꾸준하게 성장하는 개발자🌳

0개의 댓글