GRAMMAR

Editing
  • account_tree
  • bug_report

Class는 무엇인가?

클래스(class)는 객체(object) DNA를 가지고 있는 객체지향(기반)언어에서 다루는 개념이다. 사실 자바스크립트는 객체기반 언어이지만 Class라는 개념은 없었다. 이 점은 다른 객체지향 언어를 다루었던 개발자들에게는 톡특함 또는 난해함과 미숙함으로 비추어질 수도 있었다. 그러나 이 부분은 타언어와 비교해 단점이거나 모난 돌멩이가 아니라 언어적 특성으로 봐야할 것이다.

그렇지만 언어적 특성으로만 이해해 달라고 하기에는 다양한 언어를 다루는 개발자들에게는 느끼기에 따라 크고 작은 진입 장벽이 될 수도 있었던 것은 분명하다. 그래서 자바스크립트가 업데이트되면서 Class라는 개념을 도입했다.

시작하면서

나는 이 글을 다음과 같은 순으로 쓰고자 한다.

  1. 객체의 간단한 개념
  2. Class 이전의 객체를 다루는 방법
  3. Class를 이용한 객체를 다루는 방법

우리가 자바스크립트의 Class에 대해 이해를 하기 위해서는 다음 사항을 먼저 알고 가자.

CSS의 class와는 전혀 무관하다.

웹 개발의 한 축인 CSS에서도 class라는 개념을 사용한다. 그렇다보니 자칫 CSS의 class와 연관지어 생각할 수도 있다. 하지만 전혀 관계가 없는 확실한 다른 개념이다.

새로운 객체 상속 매커니즘을 다루는 것이 아니다.

자바스크립트는 이미 객체기반 개발을 지원한다. 이 말은 객체 모델이 존재하고 이 객체 모델을 사용해서 필요한 객체를 생성해 낼 수 있다는 뜻이다. 필요한 객체라는 것은 데이터를 의미하며 자바스크립트 코드에서 데이터는 모두 객체라는 것이다. 또한 다른 객체지향 언어처럼 객체간 상속이 가능하다. 그리고 이 상속에 대한 구현 방식이 톡특하다고만 보기에는 불편한 것도 사실이다. 오해하지 말자. 불편하다고 해서 성능이 떨어지는 언어라는 것은 절대 아니다.

Class 개념은 바로 이러한 불편함에서 비롯된 새로운 문법적 개념이다. 이것을 외국 인터넷 자료를 찾다보면 문법설탕(syntax sugar)이라는 표현으로 쓰기도 한다. 그리고 다른 객체지향 언어와의 러닝커브(learning curve)를 맞추기 위한 고도의 전략으로 보면 될 듯 하다.

객체의 간단한 개념

이미 자바스크립트의 기초를 제대로 배웠다면 객체의 개념에 대해 새삼스레 이야기를 들을 필요는 없을 것이다. 하지만 대부분의 입문자들에게는 여전히 객체는 골치아픈 존재일 것이라고 생각한다. 이 글의 주제가 객체의 개념을 심도있게 다루는 것이 아니므로 간단하지만 임팩트(?)있게 써보려고 한다.

자바스크립트를 교육하고 있는 선생님들이나 선배들은 객체를 설명할 때 나름대로의 방법과 노하우를 가지고 있을 것이다. 경험상 그 어떤 방법과 노하우도 모든 입문자들을 만족시키기는 어려웠다. 그럼에도 이번에는 간단하게라는 미션과 함께 이해를 시키고자 도전하고자 한다.

인간 세계는 하나의 커대한 객체 프로그램 덩어리이다.

설마 이게 사실일 것이라고 믿는 것은 아니겠지만 객체를 설명할 때 이 만한 접근법이 또 있을까 싶기도 하다. 인간 세계에는 수많은 사람들을 비롯해서 다양한 생물체가 이야기를 만들어가면서 존재하고 있다. 우리는 한명 한명의 사람들을 객체로 보기로 하자. 사실 실제 객체이기도 하다. 그런데 이 사람들이 모두 똑같은가? 외모뿐만 아니라 성격, 능력도 모두 정말 제각각이다. 하지만 키가 작다고 해서 인간이 아닌가? 운동을 못한다고 해서 인간이 아닌가? 사람을 하나의 객체로 본다면 사람이라는 데이터는 키가 크거나 운동을 잘 하는 차이가 있는 것이라 볼 수 있다. 이러한 다양한 차이가 있는 사람들이 모여 인간 세계에서 이야기를 만들고 있는 것이 아닐까?

아마도 자바스크립트에 입문하면서 맨 먼저 다루는 데이터의 종류는 String이라 불리는 문자열 데이터일 것이다. 키 큰 사람, 운동 잘하는 사람이 있듯이 같은 문자열 데이터들 중에서도 글자수가 열자(10) 이거나 그 이상인 것들이 분명히 존재한다. 바로 이것이 객체의 개념을 잡는 기초적인 이해이다.

객체지향(기반) 소프트웨어 개발은 데이터를 객체의 관점으로 다루는 것이라고 할 수 있고 인간이니 문자열이니 하는 것은 소프트웨어 개발에서는 데이터 타입(data type)이라고 이야기한다.

객체는 객체 모델이 있다.

오래전에 TV에 방영되었던 '인간의 조건'이라는 예능 프로그램이 있었다. '인간이라면 이래야 돼!' 뭐 이런 의미가 아닐까? 그 조건이 어떤 것인지 정의하기에는 나의 학문적인 한계가 있지만 적어도 영희, 철수를 인간으로 보는 추상적인 조건들이 있을 것이다. 이것을 모델이라고 하는 것이고 영희, 철수의 모델은 추상적인 개념의 인간인 것이다.

마찬가지로 자바스크립트의 문자열 데이터도 모델이 존재한다. 컴퓨팅 사고의 기반으로 '문자열 데이터는 이래야 돼!' 식으로 추상적인 개념이 분명 존재하는 것이다.

그렇다면 객체 모델을 기반으로 어떻게 영희, 철수, 어떤 문자열 처럼 어떻게 데이터가 만들어 지는가? 영희, 철수는 부모님이 생물학적으로 만들어낸 데이터이고 그 방법을 이야기하는 것은 영희, 철수를 데이터라고 취급하는 것 만큼이나 우스운 일일 것이다. 사람을 이용한 설명은 여기까지만 하기로 한다.

Class 이전의 객체를 다루는 방법

자바스크립트에서 다루는 데이터들은 모두 모델들이 존재한다. 즉 타입이라고 할 수 있겠다. string, number, array 등등은 매우 중요한 타입들 중의 하나이며 이러한 타입의 데이터를 생성하기 위해서는 각각의 모델들이 존재한다. 입문 단계에서는 이 모델들을 일일이 파헤쳐 이해할 필요는 없겠지만 필요한 데이터를 타입에 따라 만들어내는 방법은 알고 있어야 할 것이다.

예를 들어서 우리는 문자열 데이터를 만들어 낼 때 다음과 같이 코드를 작성할 것이다.

var str = "Hello";

사실 이 방법은 가장 대중적이면서 권장하는 방법이기는 하지만 객체 모델과 그 기반의 데이터를 생산해 내는 개념을 설명하기에는 또 따른 배경 설명을 듣고 이해해야만 한다. 그래서 나는 다음과 같이 문자열 데이터를 생성하는 것을 예를 들기로 한다. 분명 이 방법이 틀린 것은 아니다. 단지 추천하지 않는 방법일 뿐이다.

var str = new String("Hello");

사실 이 차이가 자바스크립트를 이해하는데 있어서 어려운 것 중의 하나이기도 하다. new String()에서 'String()' 을 생성자 함수라고 부른다. 즉 새로운 문자열 데이터를 만들어 내는 공장인 셈이다.

어쩌다 보니 이 이야기를 먼저 시작했지만 사실 Class의 개념을 잡는데 생성 방법에 대한 설명은 크게 의미가 없다. 무슨 말인가 하면 새로운 문법설탕인 Class이든 과거의 방식이든 데이터를 생성하는 방식은 다르지 않다. Class는 생성된 데이터가 아닌 그 데이터의 객체 모델을 이야기하는 것이다. 다시 말해서 객체 모델을 만들어 내는 것을 Class라는 새로운 문법으로 가능해 졌다는 것이다. 설마 객체 모델을 개발자가 만들 수 있다는 것을 모르는 입문자가 있지는 않을 것이다.

그렇다면 Class 이전은 어떻게 개발자가 객체 모델을 만들었을까?

// 부모 객체 모델을 만든다.
function Parent(name) {
	this.parentName = name;
}
// 만들어진 부모 객체 모델에 새로운 메소드를 추가한다.
Parent.prototype.getParentName = function() {
	return this.parentName;
};

// 자식 객체 모델을 만든다.
function Child(parentName, childName) {
	Parent.apply(this, arguments);
	this.childName = childName;
}

// 부모 객체 모델을 상속받는다.
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child; // 생성자 지정
Child.prototype.getChildName = function() {
	return this.childName;
};

// 이제 자식 객체 모델의 생성자 함수를 이용해서 새로운 객체(인스턴스 데이터)를 생성한다.
var obj = new Child("울부모", "나자식");

// 상속된 부모 객체 모델의 메소드를 호출한다.
console.log(obj.getParentName()); // '울부모' 출력
console.log(obj.getChildName()); // '나자식' 출력

어떤가? 코드들이 한 눈에 들어오는가? 객체 모델들을 만들고 이것을 상속 관계로 두어 사용하는 패턴은 사실 입문자에게는 버거운 것이다. 그래도 주석을 달아 두었으니 이해하려고 애써주기를 바란다. 나는 코드의 이해보다는 전체적인 작성 패턴을 들여다보기를 더 바라며 아래의 새로운 문법인 'Class를 이용한 객체를 다루는 방법'에 소개하는 예시 코드 패턴과 비교해 보기를 권한다.

Class를 이용한 객체를 다루는 방법

분명 Class 문법은 설탕처럼 달콤하다고 했다. 사람들은 달콤함에 더 끌리지 않겠나? 위에 소개한 Class를 이용하지 않는 전통적인 방식의 경우보다는 덜 복잡하고 간결해야 할 것이다.

// 부모 클래스를 만든다.
class Parent {
  // 생성자
  constructor(name) {
  	this.parentName = name;
  }
  // 메소드
  getParentName() {
  	return this.parentName;
  }
}

// 부모 클래스를 상속받아 자식 클래스를 만든다.
class Child extends Parent {
  // 생성자
  constructor(parentName, childName) {
    // 부모 생성자 실행
    super(parentName);
    this.childName = childName
  }
  // 메소드
  getChildName() {
  	return this.childName;
  }
}

// 이제 자식 객체 모델인 클래스의 생성자를 이용해서 새로운 객체(인스턴스 데이터)를 생성한다.
var obj = new Child("울부모", "나자식");

// 상속된 부모 객체 모델의 메소드를 호출한다.
console.log(obj.getParentName()); // '울부모' 출력
console.log(obj.getChildName()); // '나자식' 출력

어떤가? 간결함이 느껴지는가? 사실 다른 언어의 Class 개념을 먼저 알았더라면 간결함을 논하기보다는 따로 러닝커브를 걱정하지 않아도 될 편안함을 느꼈을 것이다. Class 이전의 방식을 다뤄본 개발자라면 단지 간결함에 놀라울 뿐이다.