가치투자자

[JS/기술면접] 객체지향 프로그래밍 및 프로토타입(prototype) 본문

Programming/JavaScript

[JS/기술면접] 객체지향 프로그래밍 및 프로토타입(prototype)

미주민 2023. 4. 3. 16:26
728x90
반응형

 객체지향 프로그래밍 

지금 자바스크립트를 공부하고 있거나, 혹은 자바스크립트를 공부할까 고민하고 있지만,

과연 자바스크립트가 어떤 특징의 언어인지 제대로 알고 있을까?

 

 자바스크립트(JavaScript) 는 명령형, 함수형, 프로토타입 기반 객체지향 프로그래밍을 지원하는 프로그래밍 언어이다.

하지만 객체지향이 무엇인지, 프로토타입은 또 무엇인지 제대로 알지 못하고 공부를 시작하는 사람이 많다.

 

* 기술면접 질문은 맨 아래에 적혀 있습니다

 

728x90

1. 객체지향 프로그래밍

프로그램을 명령어 또는 함수의 목록으로 보는 전통적인 명령형 프로그래밍의 절차지향적 관점에서 벗어나 여러 개의 독립적 단위, 즉 객체의 집합으로 프로그램을 표현하는 프로그래밍을 말한다.

 

좀 더 쉽게 설명하자면, 하나의 상자가 있다. 그리고 그 상자는 가로, 세로, 높이, 색깔 등 다양한 속성(attributes, properties)을 가지고 있다.  또, 이러한 속성의 값들을 가지고 상자의 부피를 구할 수도 있을 것이다.

여기서 속성의 값들은 객체의 상태(state)를 나타내는 데이터들이며, 그 상태 데이터들을 가지고 부피를 구하는 공식이 동작(behavior)이다. 여기서 상태 데이터들은 프로퍼티(property), 동작을 메서드(method)라고 부른다.

따라서 프로퍼티와와 메서드의 세트가 객체(Object)이며, 이러한 독립적인 객체의 집합으로 프로그램을 구성하는 언어가 자바스크립트이다.

const box = {
  width: 3,    // 가로
  length: 2,   // 세로
  height: 5,   // 높이
  color: 'blue',
  weight: 5,   // 무게
  
  // 부피 구하기
  getVolume() {
    return this.width * this.length * this.height;
  }
};

console.log(box.getVolume());

🎯  this

위 코드에서 this가 무엇인지 생소할 수 있다.

간단하게 말하자면, this는 실행한(호출한) 놈(객체)을 말한다. 여기서는 객체 box가 this이다.

 

 


2. 객체지향 프로그래밍의 특징

이러한 객체지향 프로그래밍은 다음과 같은 특징을 가지고 있다.

1) 추상화 (Abstraction)

앞서 살펴봤듯이 상자는 가로, 세로, 높이, 색깔, 무게 등 다양한 속성들을 가지고 있다. 이 중 필요한 속성만 간추내는 것을 추상화라고 한다.

 

예를 들어, 상자도 종류가 워낙 많고, 다양한 무늬의 상자들이 있을 것이다. 그러나 상자의 크기를 구하기 위해선 가로, 세로, 높이만 필요하기에 그 속성들만 추출해 객체를 만드는 것이 추상화다.

 

https://viktor-kukurba.medium.com/object-oriented-programming-in-javascript-1-abstraction-c47307c469d1

 


2) 캡슐화 (Encapsulation)

캡슐화는 객체의 상태(state)를 나타내는 속성(프로퍼티)과 그 속성을 기반으로 동작하는 메소드를 하나로 묶는 것을 말한다.

또한, 이렇게 캡슐화를 통해 외부에서 데이터에 함부로 접근할 수 없도록 '은닉(hiding)'할 수도 있다. 대표적인 예에는 클로저(Closure)가 있다. 은닉을 통해 접근을 차단하지만, 동작은 작동하도록 할 수 있다.

 

https://viktor-kukurba.medium.com/object-oriented-programming-in-javascript-4-encapsulation-4f9165cd26f9

 


3) 상속 (Inheritance)

상속은 어떤 객체의 프로퍼티나 메소드를 다른 객체가 상속받아 사용할 수 있는 것을 말한다.

부모(상위) 객체 Vehicle(탈 것)이 '전진()'과 '후진()'이라는 메서드를 가지고 있다고 하자.

자식(하위) 객체 자동차와 오토바이를 만든다고 했을 때, 서로 공통적인 기능인 '전진()'과 '후진()' 메서드를 부모 객체 Vehicle에서 상속받아오고, 각 객체의 다른 메서드를 추가하면 하위 객체가 완성된다.

각각의 객체를 만들고, 거기에 동일한 메서드를 적어주는 것보다 상위 객체에서 상속을 받아와 쓰는 것이 더 효율적이며, 상속을 통해 코드의 재사용성을 높일 수 있다.

 

https://viktor-kukurba.medium.com/object-oriented-programming-in-javascript-2-inheritance-447368f57a26

 


4) 다형성 (Polymorphism, 多形性)

다형성이란 어떤 객체의 프로퍼티나 메서드를 각각의 맥락에 따라 다른 역할을 할 수 있도록 하는 특성을 의미한다.

예를 들어, 동물이라는 부모 객체에 speak()라는 메서드가 있다고 하자. 자식 객체 고양이와 강아지에 speak() 메서드를 가져와 사용하지만, 고양이는 '야옹'이라고 말하고, 강아지는 '멍멍'이라 말한다.

즉, 부모 객체에서 물려받은 프로퍼티나 메서드를 자식 객체의 특성에 맞게 사용하는 것이 다형성이다.

 

https://viktor-kukurba.medium.com/object-oriented-programming-in-javascript-3-polymorphism-fb564c9f1ce8

 


3. 상속과 프로토타입

위와 같은 4가지 객체지향 프로그래밍의 특성 중 상속에 대해 자세히 알 필요가 있다.

예시를 통해 살펴보자.

 

아래를 살펴보면, width와 height라는 프로퍼티와 getArea라는 메서드를 가진 함수 Box가 있다.

이 함수을 복사해와 파란색 사각형과 초록색 사각형 객체(인스턴스)를 만들어보았다.

 

하지만 각 상자의 메서드가 동일한지 콘솔창에 찍어봤는데 false라는 결과가 나왔다. 동일한 함수를 복사해왔지만, 각 객체는 서로 다른 것이므로 false로 인식한다.

 

게다가 제일 큰 문제는 여러 인스턴스에 동일한 메서드를 각각 주면 메모리가 불필요하게 더 많이 낭비되며, 속도도 느려질 수 있다.

function Box(width, height) {
  this.width = width;    // 가로
  this.height = height;  // 세로

  this.getArea = function() {  // 사각형 넓이 공식
    return this.width * this.height;
  };
}

// 파란색 사각형 (인스턴스 생성)
const blueBox = new Box(1, 2);
console.log(blueBox.getArea());  // 2

// 초록색 사각형 (인스턴스 생성)
const greenBox = new Box(3, 2);
console.log(blueBox.getArea());  // 6

// 프로퍼티와 메서드를 모두 복사해오기에 메모리를 불필요하게 사용하게 된다
console.log(bluBox);    // Box { width: 1, height: 2, getArea: [Function (anonymous)] }
console.log(greenBox);  // Box { width: 1, height: 2, getArea: [Function (anonymous)] }

// 두 사각형의 메서드는 동일할까?
console.log(blueBox.getArea === greenBox.getArea);  // false

 

따라서 자바스크립트에선 상속을 통해 메서드의 불필요한 중복 사용을 막으며, 프로토타입을 기반으로 상속을 구현한다.

 


3-1. 프로토타입 객체

 프로토타입(prototype)  또는 프로토타입 객체는 상위(부모) 객체의 역할을 하는 객체로서, 다른 객체에 공유 프로퍼티(메서드 포함)을 제공한다. 필요한 프로퍼티와 메서드를 프로토타입에 추가하고, 하위(자식) 객체가 프로토타입을 상속받는다면 자신의 프로퍼티처럼 사용할 수 있다.

 

좀 더 쉽게 설명하자면, 프로토타입은 일종의 "유전자"다.

아래 예시를 보면, 원래라면 Box라는 함수에는 width와 height라는 프로퍼티만 있다.

근데 Box 함수(부모)의 유전자(프로토타입)에 사각형 넓이 공식을 넣어주면, 자식 객체인 blueBox와 greenBox도 가져다 쓸 수 있는 것이다.

게다가 두 자식 모두 동일한 부모에게서 같은 유전자를 물려받았기에 두 사각형의 메서드 getArea(사각형 넓이 공식)는 동일한 것이다.

 

function Box(width, height) {
  this.width = width;    // 가로
  this.height = height;  // 세로
}

// Box 함수의 프로토타입에 getArea 메서드를 추가해 모든 인스턴스가 상속받아 사용할 수 있도록 한다
Box.prototype.getArea = function() {
  return this.width * this.height;
};


// 파란색 사각형 (인스턴스 생성)
const blueBox = new Box(1, 2);
console.log(blueBox.getArea());  // 2

// 초록색 사각형 (인스턴스 생성)
const greenBox = new Box(3, 2);
console.log(blueBox.getArea());  // 6

// 부모 객체 프로토타입으로부터 상속받았기에 두 사각형의 메서드는 동일하다
console.log(blueBox.getArea === greenBox.getArea);  // true

 

여기서 좀 더 신기한 점을 살펴보자

자식이 어떻게 생겼는지 콘솔창으로 찍어봤지만, getArea 메서드는 나오지 않는다.

즉, 자식에 하나하나 메서드를 적진 않았지만, 프로토타입은 유전자이기에 자식이 필요하다면 상속받아 쓸 수 있는 것이다.

 

게다가 getArea라는 메서드를 복사해오지 않아 메모리 소모도 줄일 수 있다.

function Box(width, height) {
  this.width = width;    // 가로
  this.height = height;  // 세로
}

// 프로토타입으로 getArea 메서드 상속
Box.prototype.getArea = function() {
  return this.width * this.height;
};


// 인스턴스 생성
const blueBox = new Box(1, 2);
const greenBox = new Box(3, 2);

console.log(blueBox);   // Box { width: 1, height: 2 }
console.log(greenBox);  // Box { width: 3, height: 2 }

 


3-2-1. 프로토타입 체인

만약 현재 객체에 어떤 프로퍼티나 메서드가 없으면 어떻게 할까?

위에 살펴본 것처럼, 상위 프로토타입(부모 객체)에 가서 상속을 받아온다.

즉,  프로토타입 체인 은 하위 객체(자식)에 없는 프로퍼티나 메서드를 상위 객체(부모)에 가서 검색하고 상속받아오는 메커니즘을 말한다

 

3-2-2. 프로토타입 체인의 종점

프로토타입 체인의 종점은 Object.prototype 객체다.

Object.prototype의 프로토타입은 null이다. 그 이유는 무한루프에 빠지지 않기 위해서다.


3-3. 왜 프로토타입을 쓸까?

코드를 짤 때, sort() 메서드로 배열을 정렬해주고, length 프로퍼티로 배열의 길이를 출력해본 적이 있을 것이다.

근데 왜 이것이 가능한지 알고 써본 적은 없을 것이다.

 

이처럼 프로퍼티와 메서드를 자유롭게 사용 가능한 이유는 무엇일까?

그건 바로 배열이라는 부모 객체에 저 메서드들이 들어있고, 그것을 상속받아왔기에 사용가능한 것이다.

const arr = [3, 2, 5, 4];

console.log(arr.sort());   // [ 2, 3, 4, 5 ]
console.log(arr.length);   // 4

 

아래는 sort() 메서드에 대한 설명이 적힌 공식문서이다.

sort()라는 메서드는 Array라는 배열(객체)의 프로토타입에 등록된 함수(메서드)며, 그렇기에 우리가 새로운 배열을 만들었을 때 프로퍼티와 메서드를 상속받아 쓸 수 있는 것이다.

만약 프로퍼티와 메서드를 상속받지 못한다면, 객체를 만들 때마다 매번 수많은 프로퍼티와 메서드를 다 적어줘야 할 것이다.

 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

 

 

또한, 우리는 아래처럼 배열로 arr를 선언해주었지만, 컴퓨터는 이를 생성자 함수로 인식하여 그 생성자 함수에 맞는 프로토타입을 상속해준다.

// 원래 식 : const arr = [3, 2, 5, 4];
// 컴퓨터가 받아들이는 식
const arr = new Array(3, 2, 5, 4);

console.log(arr.sort());   // [ 2, 3, 4, 5 ]
console.log(arr.length);   // 4

 


3-4. 원시타입(Primitive data type)의 확장

이처럼 프로토타입을 통해 다양한 프로퍼티와 메서드를 쓸 수 있다는 것을 알 수 있었다.

그런데 여기서 또 의문이 드는 점이 있다.

바로 객체가 아닌데도 메서드를 쓸 수 있는 원시타입이 있다는 것이다.

 

우리가 문자열로 타입을 바꾸기 위해 자주 쓰는 toString()은 원시타입에서 작동한다.

let num = 1;
console.log(typeof num.toString());  // string

 

MDN을 살펴봐도 String의 프로토타입 내에 메서드가 있는 것을 알 수 있다.

원시타입은 객체가 아닌데 어떻게 프로퍼티와 메서드를 사용할 수 있으며, 어떻게 프로토타입이 있을 수 있을까?

 

그 이유는 바로

원시타입으로 프로퍼티나 메서드를 호출할 때, 원시 타입과 연관된 객체로 일시적으로 변환되어 프로토타입 객체를 공유했기 때문이다.

이와 관련된 부분은 내장객체(Built-in object)에서 자세히 다룰 것이다.

 

 

반응형

 


🌟 자바스크립트 기술면접 질문

1. 객체지향 프로그래밍은 무엇을 의미하나요? 🔥

 

  • 기존의 절차지향적 관점에서 벗어나, 프로퍼티와 메서드를 가진 독립적인 객체들의 집합으로 프로그램을 표현하는 방식

 

2. 객체지향 프로그래밍의 특징에 대해 말해볼 수 있나요? 🔥

 

  1. 추상화
    - 객체를 구성하는 다양한 속성 중에 필요한 속성만 간추려내는 작업
  2. 캡슐화
    - 객체의 상태(state)를 나타내는 속성(프로퍼티)과 그 속성을 기반으로 동작하는 메소드를 하나로 묶는 것
  3. 상속
    - 상위 객체의 프로퍼티나 메소드를 하위 객체가 상속받아 사용할 수 있는 것
  4. 다형성
    - 어떤 상위 객체의 프로퍼티나 메서드를 하위 객체 각각의 상황에 맞게 사용하는 것

 

3. 자바스크립트는 객체지향 프로그래밍 언어인가요?

 

  • 자바스크립트는 프로토타입 기반의 객체지향 언어다

 

4. 프로토타입이 무엇인가요?

 

  • 어떤 객체의 상위 객체 역할을 하는 객체로서, 하위 객체에 공유 프로퍼티를 제공해 하위 객체가 상위 객체의 프로퍼티를 자유롭게 사용할 수 있도록 한다.

    - 예를 들어, 어떤 Array 생성자 함수를 만들었을 때, 그 함수 내에 length 같은 프로퍼티나 각종 메서드를 작성해주지 않아도 프로토
    타입에 의해 상속받아 사용할 수 있다

 

5. 프로토타입 체인이 무엇인가요?

 

  • 하위 객체(자식)에 없는 프로퍼티나 메서드를 상위 객체(부모)에 가서 검색하고 상속받아오는 메커니즘을 말하며, 프로토타입의 종점은 Object.prototype 객체이며, Object.prototype의 프로토타입은 null이다.

 

6. 원시타입은 객체가 아닌데 어떻게 프로퍼티나 메서드 사용이 가능할까요?

 

  • 원시타입으로 프로퍼티나 메서드를 호출할 때, 원시타입과 연관된 객체로 일시적으로 변환되어 프로토타입 객체를 공유했기 때문이다.

 


</> 끊임없이 성장하기 위해 공부한 내용을 글로 작성하고 있습니다. 틀린 부분이나 추가해야 할 부분이 있다면 언제든 댓글로 남겨주세요❗️

 


References

 

728x90
반응형