본문으로 바로가기

자바스크립트 객체지향 프로그래밍




클래스(생성자) 기반의 객체지향 기법


프로그램을 작성하는 방법론 관점에서 보면 자바스크립트는 함수(function)을 위주로 프로그래밍을 해나가는 절차적 프로그래밍(procedural programing)과 함수를 비롯해 모든 것을 객체로 간주해서 객체를 중심으로 프로그래밍을 해 나가는 객체지향 프로그래밍(object-oriented-proraming) 방법을 모두 지원하는 언어이다.


객체지향 프로그래밍 언어도 다시 클래스 기반의 프로그래밍과 프로토타입 기반의 프로그래밍으로 나뉘는데. 자바스크립트는 프로토타입 기반의 객체지향 프로그래밍을 지원한다. 


클래스 기반 언어에서는 클래스를 이용해 객체를 만들고 클래스를 기반으로 해서 상속을 지원하지만 프로토타입 언어에서는 객체의 원형인 프로토타입을 이용해 객체를 만들고 상속도 프로토타입을 기반으로 한다.


일반적으로 객체지향이라고 하면 클래스 기반의 객체지향을 의미한다.


잠시 클래스 기반의 객체지향의 특성을 정리해 본다. 흔히 클래스 기반의 객체지향 언어라면 다음과 같은 특징이 있어야 한다.객체, 메소드, 속성(Object, method, property)


   - 클래스(Class)

   - 캡슐화(Encapsulation)

   - 집합(Aggregation)

   - 상속성(Inheritance)

   - 다형성(Polymorphism)


이러한 객체지향적인 특징을 자바스크립트로는 어떻게 구현하는지에 초점을 두면서 자바스크립트를 공부 할 필요성이 있다.


위 개념들에 대해 간단히 알아보자.




객체

객체지향이라는 이름이 암시하듯이 객체는 매우 중요하다.

세상에 존재하는 모든 것은 객체라고 할 수 있다. 객체는 실제로 존재하는 것일 수도 있고 난해한 개념적인 것일 수도 있다. 

세상은 수많은 객체로 구성돼 있고(사람, 나무 객체, 돌 객체, 물 객체, 동물 객체) 그것들이 상호작용하면서 세상이 돌아간다. 


프로그래밍 세계도 이러한 일반 세계의 객체와 같은 개념을 채용한 것이다.

그래서 객체지향 언어는 이러한 객체를 표현할 수 있고 세계의 구성요소인 객체를 '현재 상태(state)'와 '행동(behavior)'으로 정의하여 프로그래밍을 표현했다.


예를 들어, 고양이(동물 객체)는 다리가 네 개있고(state), 털이 있고(state), 야옹야옹(behavior)거리고, 높이 점프(behavior)를 할 수 있는 객체인 것이다. 


객체지향에서는 상태(state)를 속성(property)이라하고 행동(behavior)을 메소드(method)라고 한다. 

즉, 모든 객체는 속성과 메소드로 구성된다.

객체 지향에서는 속성과 메소드를 모두 객체의 멤버(member)라고 한다.




클래스(Class)

현실 세계에서는 유사한 객체들끼리 어떤 기준을 근거로 그룹핑될 수 있다. 참새와 독수리는 모두 새다. 

따라서 두 종류의 새는 모두 Bird라는 클래스에 속한다고 할 수 있으며, 실제 참새와 독수리는 각가 Bird의 특별한 객체에 해당한다.


객체지향 프로그래밍에서 클래스란 객체를 만들어 내는 청사진 또는 프레임 또는 객체를 만들어내는 레시피라고 할 수 있으며, 동일한 클래스를 사용해 다른 객체를 만들어 낼 수 있다.




캡슐화

캡슐화는 객체지향 프로그래밍과 관련된 또 다른 개념으로서 객체지향 언어는 하나의 객체는 관련 속성과 메소드를 하나의 객체로 묶어 포함(캡슐화)할 수 있음을 나타낸다.


캡슐화와 함께 나오는 개념으로 정보 은닉이 있다. 

가스렌지를 예로 든다면 가스렌지의 사용자에게는 몇 가지의 버튼이 제공된다. 버튼을 누르면 불이 켜진다.
그러나 우리는 내부에서 어떤 일이 일어나고 있는지는 모른다. 다시 말하면 가스렌지가 어떻게 구현되는지 사용자에게 숨겨진다. 

외부에 노출된 메소드 또는 속성을 코드에서 사용할 때 똑같은 일이 일어난다. 외부의 사용 코드에서는 개발자가 직접 코딩을 해서 구현했는지, 아니면 서드파티 라이브러리를 사용해서 구현했는지는 중요하지 않다.

객체를 사용하는 코드는 내부적으로 메소드, 속성이 어떻게 작동하는 알 필요가 없다.

C#, 자바와 같은 컴파일 언어에서는 일반적으로 객체의 내부 코드를 읽을 수 없다. 

그러나 자바스크립트 언어는 인터프리터 언어라서 해당 내부 코드를 읽을 수가 있다. 


그러나 캡슐화 및 정보 은닉의 개념은 동일하다.


즉, 객체의 구현이 어떻게 됐는지를 상관하지 않고 객체가 노출하는 속성과 메소드로만 작업을 할 수가 있다.


객체지향에서는 내부 구현을 숨길 수 있을 뿐더러 메소드, 속성 자체도 외부에 노출시키거나 감출 수가 있다.

이것은 정보 은닉의 또 다른 특징으로서 일반 언어에서는 public, private, protected 같은 한정자가 있어서 외부에서 속성, 메소드에 접근할 수 있는 수준을 정의할 수 있다.


예를 들어, 객체 내부에서만 접근할 수 있게 하려면 private으로 정의하면 되고 외부의 어떤 코드에서도 접근하게 하려면 public으로 정의하는 것이다.


자바스크립트에서는 모든 메소드, 속성은 공개(public)로 정의된다. 그러나 비공개(privat) 특징을 구현하는 방법이 있다.




집합(Aggregation)

몇 개의 객체를 합쳐서 하나의 객체를 만드는 것을 집합(Aggregation 또는 compositon)이라고 합니다.

이러한 집합 개념은 문제를 좀 더 작고 관리할 수 있는 부분으로 나눠서 분리할 수 있는 방법입니다.

예를 들어 컴퓨터라는 객체를 설계한다고 가정해 봅니다.

컴퓨터 전체를 동시에 한꺼번에 설계하기보다는 모니터 객체, 마우스 객체, 키보드 객체 등의 각 부분으로 나눠서 하나씩 더 깊이 있게 분석, 설계한 후 나중에 다시 하나로 합치는 것이 더 효율적일 것입니다.(divide & conquer)


객체지향 언어에서는 이런 분할/정복(divide & conquer), 그리고 종합하는 과정을 지원할 수 있어야 합니다.

다른 객체지향 언어뿐만 아니라 자바스크립트도 이런 집합 특징은 기본적으로 지원하고 있습니다.




상속(Inheritance)

객체지향 프로그래밍에서의 상속이란 이미 존재하는 코드를 재사용하거나 기존 코드를 확장하는 좋은 방법입니다.

예를 들어 사람(Person)이라는 객체(클래스)를 만들어서 속성으로 이름(name), 생년월일(birthdate)이 있고, 걷고(walk), 말하고(talk), 자고(sleep), 먹는(eat) 메서드가 있다가 해봅니다.

그런데 시간이 지나서 프로그램상에서 사람이긴 한데 좀 더 구체적인 한국사람(Korean)이 필요해졌다고 가정해 봅니다.

물론 Person이 가지고 있는 모든 속성과 메서드를 다시 Korean에서 구현하고 Korean에서 더 추가돼야 하느 속성이나 메서드(이를테면, SpeakInKorean() 같은 메서드)를 더 구현할 수도 있습니다.


그러나 Person이 가지고 있는 모든 속성과 메서드를 상속(inherit)하고 Korean에서 필요로 하는 속성과 메서드를 더 추가하는 방법을 모색하면 기존 코드의 재사용이라는 측면에서 더 효율적일 것입니다.


객체가 다른 객체를 상속할 때 보통 새로운 메서드 또는 속성이 추가됩니다.

이런 것을 표현하기 위해서 "상속(inherit)"이라는 표현 대신 "확장(extend)"이라고도 표현합니다.

부모 객체를 상속하면서 부모의 메서드와 속성을 다시 정의하는 경우도 있습니다.

즉, 메서드명, 속성명은 동일하나 자식 객체의 메서드나 속성을 호출하면 다른 방식으로 작동하게 됩니다.

이렇게 상속된 멤버를 다시 정의하는 것을 오버라이딩(overriding)이라고 합니다.


일반 객체지향 언어에서는 클래스 차원에서 상속을 지원하지만 자바스크립트에서는 클래스 상속은 없습니다.

대신 프로토타입을 이용한 객체 차원의 상속을 지원하고 있습니다.




다형성(Polymorphism)

위의 글(상속 파트) 중에 있는 Person 객체가 있습니다. Person 객체의 모든 속성과 메서드를 상속받은 Korean 객체를 만들었다고 가정해 봅니다.

즉, Person 객체나 Korean 객체 모두 "talk" 메스드를 제공하지만 Person에서 제공하는 "talk" 메서드와 Korean에서 제공하는 "talk" 메서드의 구현 내용은 다를 수 있습니다.


코드를 작성하면서 jaehee라는 변수에는 Person 객체가 할당될 수도 있고 Korean이라는 객체가 할당될 수도 있습니다.

두 객체 모두 "talk"라는 메서드를 가지고 있으므로 jaehee에게 "talk" 메서드를 호출하면 코드가 동작하게 될 것입니다.

이처럼 동일한 이름의 메서드를 호출하더라도 실제 호출 대상이 되는 객체에 따라 서로 다른 메서드가 실행되는 것을 다형성이라고 합니다.

(Person 객체인지 아니면 Korean 객체인지에 따라 서로 다른 메서드가 실행)


정리하면 다형성은 여러 객체가 동일한 메서드 호출에 반응하는 능력을 말합니다.

프로그래머 또는 프로그램은 실제 객체가 어떤 객체인지 알 필요가 없습니다.