Object Oriented Programming (OOP) & Prototype in JavaScript

Gahee Kim
7 min readFeb 26, 2021

--

객체 지향 언어 (OOP)란?

‘객체 지향’이라는 말에서도 알 수 있듯이, OOP는 모든 것을 ‘객체’로 그룹화한다는 특징이 있다. 구체적으로는, ‘클래스’라는 데이터 모델의 청사진을 이용한 코드 구현 방식이다. 현대의 언어들에서 자주 찾아볼 수 있는 방식인데, Javascript도 객체 지향으로 작성할 수 있다.

객체 지향 프로그래밍이 등장하면서, 단순히 절차적으로 별개의 변수와 함수를 처리하던 것을 넘어서 데이터와 기능을 한번에 묶어서 처리함으로써 데이터의 접근과 처리 과정에 있어 훨씬 수월해졌다.

데이터와 기능이 함께 있다는 말의 뜻은 객체 내에 즉 속성과 메소드가 존재한다는 말이기도 하다. 예를 들어, 모든 자동차는 공통적인 기능 (가속을 한다, 주유를 한다 등)을 공유하고, 고유의 속성 (크기, 색상, 최고 속력 등)을 가진다. 클래스를 통해 새로운 인스턴스 (찍어낸 객체)를 만들 때, 이런식으로 다양한 고유의 속성 값을 집어넣을 수 있다.

이제 세부 속성을 넣어줘야 하는데, 이 때 생성자 (constructor)가 등장한다. 클래스에 생성자 함수를 포함해서, 생성자를 통해 세부적인 속성을 함수에 인자를 넣어주듯 넣을 수 있다.

학생이라는 클래스를 가진 예시 코드를 한 번 살펴보자.

class Student {
constructor(name, age, grade){
this.name = name;
this.age = age;
this.grade = grade;
}
learn() {
console.log(this.name + '가 공부를 시작합니다');
}
graded() {
console.log(`${this.name}의 성적은 ${grade}입니다`);
}
}
let lana = new Student('Lana', 24, 'A+');lana.age; // 24
lana.graded(); // 'Lana의 성적은 A+입니다'

constructor 함수의 파라미터로 들어간 친구들이 세부 속성들의 이름이다.

그 아래에 있는 함수들이 바로 공통적인 기능을 담당하는 메소드들이다.

OOP Basic Concepts

  • Encapsulation (캡슐화)
  • Inheritance (상속)
  • Abstraction (추상화)
  • Polymorphism (다형성)

Encapsulation (캡슐화)

캡슐화란 앞서 보았던 것처럼 속성과 메소드를 따로 외부에서 지정하는 것이 아닌, 하나의 객체 안에 넣어서 묶는 것을 말한다. 캡슐화는 내부 데이터나 구현은 외부에 노출되지 않고, 동작만 노출시키는 ‘은닉’의 특성을 지닌다.

캡슐화의 장점은 느슨한 결합 (Loose Coupling)을 돕는다는 것이다. 즉, 언제든 구현을 수정할 수 있다. 절차적 코드에서는 데이터의 형태가 바뀌면 전체적인 코드 흐름에 영향을 미쳐 문제가 발생할 수도 있지만, 객체 지향 코드에서는 객체 내의 은닉된 메소드 구현만 수정하고, 노출된 코드의 흐름은 영향을 받지 않게 할 수 있다.

Abstraction (추상화)

추상화란 실제 노출시키는 부분을 단순하게 포장해서 보여주는 것을 말한다. 자동차의 구조를 한 번 생각해보자. 자동차의 보닛만 열어봐도, 내부의 구조가 얼마나 복잡한지 알 수 있다. 하지만 실제로 우리는 차를 탈 때 내부적인 구조와 작동 원리를 생각하면서 운전하지 않는다. 우리는 단순히 핸들, 액셀, 브레이크, 그리고 기어를 이용해 자동차를 움직이게 할 뿐이다. 이렇게 단순한 인터페이스로만 노출시키는 것을 추상화라고 한다.

추상화를 통해 수많은 내부 기능을 굳이 노출시키지 않음으로써 예기치 못한 변수들을 막을 수 있게 된다. 캡슐화와 비슷해보이지만, 캡슐화는 데이터와 기능이 은닉되어 있다면, 추상화는 사용자가 필요하지 않은 메소드들을 노출시키지 않고, 단순한 인터페이스 혹은 명칭으로만 노출시키는 것을 강조한다.

Inheritance (상속)

상속이란 기본 클래스 (base class)의 특징을 파생 클래스 (derive class)에 고스란히 물려주는 것을 말한다 (부모 — 자식 관계로 주로 설명한다).

예를 들어, 사람 (Human)이라는 클래스가 있다고 가정할 때, 공통적인 속성과 메소드로는 각각 이름, 성별, 나이, 그리고 먹다, 자다 등이 있을 것이다.

거기에 추가로 학생 (Student)라는 클래스를 생성한다고 가정해보자. 학생은 결국 사람의 속성을 가지고 있으므로, 새롭게 사람이 가진 모든 속성을 다시 작성하는 것은 매우 비효율적일 것이다. 따라서, 상속을 이용해 사람 클래스의 속성과 메소드를 상속받고, 학생의 특정 속성인 ‘학습 목표’와 특정 메소드인 ‘공부하다’를 추가하면 된다.

Polymorphism (다형성)

다형성이란 자동차들마다 각기 다른 디자인의 모델이 출시되는 것처럼, 객체에서 같은 메소드일 때에도 여러다양한 방식으로 구현될 수 있음을 의미한다.

예를 들어, HTML Element 중에는 아주 다양한 형태의 Element들이 존재한다. Checkbox, radio, inputbox, textarea 등등 이 모든 요소를 전부 Element라고 부른다. 이 요소들을 직접 구현한다고 할 때, 다른 것들과 마찬가지로 속성과 메소드가 필요하다. 보편적으로는 화면에 보여주는 기능을 하는 render 메소드를 공통적으로 가지고 있을 것이다.

위 element들은 모두 HTML Element라는 부모 클래스에서 render메소드를 상속받을 수 있다. 그런데, 각 element들마다 render하는 방식이 다를 수 밖에 없다. checkbox는 눌렀을 때 체크표시가 보여져야 하고, textarea는 긴 네모 상자 위에 텍스트를 입력할 수 있도록 보여져야 한다. 이렇게 같은 메소드로 다양한 동작을 보여주는 것을 다형성이라 한다.

만약 다형성의 개념이 없다면?

if (type === 'checkbox') {
renderCheckbox()
}
else if (type === 'text') {
renderText()
}
else if (type === 'input') {
renderInput()
}
//...

위 코드처럼 부모 클래스에서 상속받을 메소드를 분기시켜 모두 다르게 생성해야 할 것이다.

정리하자면,

  1. 캡슐화 — 복잡성은 줄이고, 재사용성은 높인다.
  2. 추상화 — 복잡성은 줄이고, 예상 못한 변수로 인한 문제의 가능성을 줄인다.
  3. 상속 — 불필요한 코드를 없애 의미없는 반복을 줄인다 ( = 재사용성 높임).
  4. 다형성 — 같은 메소드를 사용할 때에도 객체의 특성에 따라 고유하게 작성할 수 있다.

Javascript Prototype

자바스크립트는 프로토타입 기반 언어로 잘 알려져있다. 자바스크립트는 다른 객체 지향 언어와는 다르게 클래스라는 개념이 없었다. 최신 자바스크립트에는 Class 문법이 추가되긴 했지만, 자바스크립트는 여전히 프로토타입 기반 언어이고, 이 프로토타입을 이용해 메소드를 상속받는 형태를 빌려와서 쓴 것이라고도 할 수 있다.

프로토타입이란?

그렇다면 프로토타입이 대체 무엇인가? 프로토타입은 쉽게 말해 다른 객체의 원형 (original form)이 되는 객체이다. 모든 객체는 프로토타입에 접근이 가능하다. 예시와 함께 살펴보자.

function Student() {}Student.prototype.isHuman = true;
Student.prototype.hoursOfSleep = 7;
let lana = new Student();
let kim = new Student():
console.log(kim.isHuman); // true
console.log(lana.hoursofSleep); // 7

위 예시에서는 프로토타입이라는 객체가 어딘가에 존재하고, 생성된 객체 lana와 kim은 어딘가에 존재하는 프로토타입 객체에 담긴 모든 값을 가져다 쓸 수 있게 된다. 예시를 보면, isHuman과 hoursOfSleep을 프로토타입 객체에 집어넣고, 외부에서 kim과 lana가 그 프로토타입에 접근해서 값을 공유해서 사용하고 있는 것을 확인할 수 있다.

다음 포스트에서 프로토타입 체인에 대해서 조금 더 깊게 알아보자!

--

--

No responses yet