AJAX의 열풍으로 많은 개발자들이 DOM 조작과 공통 함수 등을 만들며 다뤄왔던 자바스크립트를 다시 보게 되었다. 나도 그런 사람 중의 하나이다. 자바스크립트 핵심 가이드란 책이 정공법으로 자바스크립트를 잘 소개하고 있어서 그 책을 읽긴 했지만, 대개는 알고 있던 내용이라 무척이나 지루한 일이기도 했다. 그러던 중 AJAX in Action을 보면서 Appendix B에 정리된 "JavaScript for object-oriented programmers"을 접하게 되었다.  이런 내용을 미리 알았더라면 좋았을 거라는 생각에 간단히 정리해두고 넘어가고자 한다.

1.1 JavaScript != Java

LiveScript라는 넷스케이프용 스크립트 언어가 정치적인 이유로 자바스크립트로 이름을 바꿨다는 등의 얘기는 중요한 게 아니다. 중요한 건 자바에서 Object가 First-class object이듯, 자바스크립트에서는 Function, 즉 함수가 First-class object란 사실이다. 이것은 자바스크립트가 함수형 패러다임을 갖는 Scheme 등의 언어와 많은 유사성을 갖고 있다는 것을 뜻하며, 객체지향적인 접근을 시도할 때 많은 혼란이 발생할 수 있음을 알게한다. 뿐만 아니라 자바스크립트는 교묘하게 객체지향을 지원하는 듯 보이지만, 그 방식이 프로토타입 기반이다. 안영회님의 글을 참고하자. 자바스크립트에서 객체는 그저 객체처럼 보이도록 위장한 연결 배열(Associative Array)일 뿐이다. 변수의 데이터형을 지정하지 않는다거나, 인터프리터 방식의 언어라거나 하는 건 익히 알고 있는 사실일 것이다. 정리하면 자바스크립트를 이해하기 위해 개념적으로 반드시 알아둬야 할 기본 개념은 4가지이다.
  • 자바스크립트에서 First-class object는 함수(Function)이며, 함수형 패러다임을 가지는 언어에서 축적된 경험을 활용할 수 있다.
  • 자바스크립트는 객체지향 언어라기 보다, 복잡성을 제어하기 위해 객체지향을 흉내낼 수 있는 기능을 가지고 있다.
  • 자바스크립트에서 객체는 연결 배열이 객체처럼 다루어지도록 위장한 것이며, 그러한 위장의 뒷면에는 프로토타입 기반 프로그래밍 이라는 기법이 숨겨져 있다.
  • 자바스크립트는 하나의 변수에 여러 타입의 값을 받아들일 수 있으므로, 데이터형을 명확하게 지정할 필요가 없으며, 인터프리터에 의해 해석된다.

1.2 자바스크립트에서 객체 생성하기

자바스크립트에서 객체를 생성하는 방법은 크게 4가지로 분류할 수 있다. 
 
  • 자바스크립트 기본 방식 
  • JSON 방식
  • new 생성메소드 이용하기 (메소드를 함께 정의하는 방식)
  • 프로토타입 이용하기 (메소드를 별도로 정의하는 방식)

가. 자바스크립트 기본 방식

이 방식은 자바스크립트에서 기본적으로 사용되는 객체 생성 방법이다. 인스턴스를 만들어서 새로운 속성이나 함수를 해당 객체에 언제든 추가할 수 있도록 하는 것이 특징이다. 
var book = new Object();
book.title = "sample";
book.chapter1 = new Object();
book.chapter1.title = "title01";
book.chapter1.page = 24;
book.chapter2 = new Object();
book.chapter2 = {title: "title02", page: 10};
book.toString = function() {
  var message = "Outline: " + book.title + "\n" +
    "Chapter 1: " + book.chapter1.title + "\n" +
    "Chapter 2: " + book.chapter2.title + "\n";
  return message;        
}
자바스크립트의 객체가 연결 배열이라는 것을 활용하면, 
book.title = "sample";
과 같은 코드를 아래와 같이 배열처럼 정의할 수도 있다.
book['title'] = "sample";
함수도 마찬가지인데, 그때 그때 정의할 필요없이 이미 구현되어 있는 함수를 재사용하는 것도 가능하다. 이때 주의할 점은 아래와 같이 함수 객체를 할당하는 것이므로 괄호를 생략한다는 것이다.
book.func = pre_exist_func;

나. JSON 방식

JSON은 자바스크립트 객체표기법(JavaScript Object Notation)의 약어로, 쉼표를 구분자로 해서 배열 값을 한번에 설정하는 기능을 이용한 방식이다. 자바스크립트에서 객체는 중괄호를 사용해서 콜론으로 구별된 키:값의 쌍을 쉼표를 활용해서 연속적으로 초기화할 수 있고, 할당되는 값은 다시 객체이거나 함수일 수 있다. JSON 방식을 이용하면, 복잡한 구조의 객체를 한번에 만들어 낼 수 있지만, 생성자에 익숙해진 자바 개발자들에게는 쉽게 익숙해지지 않는 방법이다.
book2 = {
  title : "sample",
  chapter1 : {
      title : "title01",
      page : 24
  },
  chapter2 : {
      title : "title02",
      page : 10
  },
  toString : function() {
      var message = "Outline: " + book2.title + "\n" +
         "Chapter 1: " + book.chapter1.title + "\n" +
          "Chapter 2: " + book.chapter2.title + "\n";
      return message;    
      }
};




다. new 생성메소드를 이용하기 (메소드를 함께 정의하는 방식)

자바 개발자에게 익숙한 생성자를 흉내낼 수 있는 것이 생성메소드를 만들어, new 키워드와 함께 이용하는 방식이다. 
function MyBook(title, chapter1, chapter2) {
  this.title = title;
  this.chapter1 = chapter1;
  this.chapter2 = chapter2;
  this.toString = function() {
        var message = "Outline: " + this.title + "\n" +
            "Chapter 1: " + book.chapter1.title + "\n" +
            "Chapter 2: " + book.chapter2.title + "\n";
        return message;    
    }
}

function Chapter(title, page) {
  this.title = title;
  this.page = page;
}

이 방식을 이용하면, 아래와 같이 자바 개발자들에게 익숙한 방식으로 객체를 생성할 수 있다.
var mybook1 = new MyBook("sample", new Chapter("title01", 24), new Chapter("title02", 10));
이 방식의 단점은 객체 인스턴스마다 함수가 매번 새로 만들어진다는 것과, 의도하지 않은 클로저(Closure)가 만들어진다는 것이다. 클로저에 대해서는 다음에 살펴보도록 한다.

라. 프로토타입 이용하기 (메소드를 별도로 정의하는 방식)

new 생성메소드 방식의 단점을 해결한 것이 프로토타입을 이용하는 방식이다. 프로토타입(prototype)은 자바스크립트 객체가 지니는 기본 속성으로, 생성 메소드를 정의한 다음에만 사용할 수 있다. 프로토타입을 이용하면, 객체를 생성했을 때 해당 함수가 생성된 객체에 자동으로 연결되도록 할 수 있다. 이런 프로토타입의 기능을 이용하면 상속의 개념을 흉내낼 수 있는데, 이를 통해 웹브라우저 등에 내장된 기본 객체의 기능을 확장할 수도 있게 된다. 
function SafeMyBook(title, chapter1, chapter2) {
    this.title = title;
    this.chapter1 = chapter1;
    this.chapter2 = chapter2;
}

SafeMyBook.prototype.toString  = function() {
    var message = "Outline: " + this.title + "\n" +
       "Chapter 1: " + book.chapter1.title + "\n" +
        "Chapter 2: " + book.chapter2.title + "\n";
    return message;    
}

function Chapter(title, page) {
    this.title = title;
    this.page = page;
}
아래의 참고자료 그림을 클릭하면, 모달 다이얼로그와 유사한 이미지 팝업이 생기는데 이것은 LightBox라는 스크립트 라이브러리이다. LightBox 스크립트를 다운받으면, 2개의 자바스크립트 파일이 존재하는데, 해당 자바스크립트 파일의 소스를 열어서 확인해보자. 모두 4번째에 소개한 프로토타입 방식을 사용해서, 객체를 생성해 조작하고 있음을 확인할 수 있을 것이다. 

자바스크립트 자체는 함수를 이용해야 한다거나, 반드시 객체를 이용해야 한다거나 하는 제약이 없다. 그러나 AJAX의 인기에 힘입어 우리가 다뤄야 하는 자바스크립트는 점점 많아지고, 복잡해지고 있다. 이러한 복잡성의 제어를 위해 자바스크립트에서도 객체 지향적인 처리가 필요해졌고, 그것을 가장 잘 표현하는 방식이 프로토타입을 이용한 객체 생성 방법이므로 잘 익혀두는 것이 좋겠다.

참고자료 1. AJAX in Action - 에이콘(Manning)
참고자료 2. 자바스크립트 핵심 가이드 (JavaScript The Definitive Guide: 4th covers JS1.5) - 한빛미디어(O'Reilly)

출처 : Tong - asamaru님의 asamaru님의 기본통통