Overview

필자는 WEB UI 개발 및 간단한 서버, 내부 개발테스트 등을 할때는 자바스크립트(JavaScript)를 사용합니다.
기본적으로 자바스크립트는 정적 웹페이지에서 다양한 동적 이벤트나 UI 변경 등 정적 리소스에서 제공하지 못한 많은 것들을 가능하게 해줍니다.

예) A 태그에 시스템 알럿창으로 띄우는 코드

<a href="#" onclick="alert('Hello World.'); return false;">Click Me.</a>


Javascript 모듈화가 왜 필요하지 ?

하지만 자바스크립트에서 단순 기능만 작성하지 않기 때문에 모듈화가 필요합니다.
각 페이지에 필요한 기능들을 모은 자바스크립트 파일들이 존재 하는데, 페이지별로 로드하여 사용하기에는 전역변수, 클래스 변수 등 스코프(scope) 처리가 까다로워 코드 작성이 용이하지 않았습니다.
다른 파일로 작성을 하여도 지역 변수가 아닌 변수에 대해서 관리하기가 힘들었습니다.

// common.js
var pageName = '페이지이름';
...

// main.js
var pageName = '메인페이지';
...

// 파일을 달리 작성하여도 `pageName`의 scope를 보장하지 못한다.

파일별 scope를 관리하기 위해서 익명함수단위로 모듈화를 적용하였습니다.


예) 익명함수 모듈화

// product.js
(function() {
  var productId = null;
  function loadData() {
    ...
  }
})();

// product_info.js
(function() {
  function loadData() {
    ...
    // product.js 의 productId 값을 참조
  }
})();


하지만 함수내 변수를 scope로 관리하기 때문에 product_info.js에서 product.js 에 있는
productId 변수를 참조하기 위해서는 전역변수 혹은 다른 방식으로 데이터값을 전달해야 하는 이슈가 발생합니다.

또한 코드 혹은 개발단계에서 해당 파일에 어떠한 함수와 변수들이 있는지 확인을 위해 여러 소스파일들을 확인하고 이해해야 했습니다.

물론 json 타입으로 생성하여 oop 처럼 사용은 가능합니다만, 일반적인 oop와는 달리 생성자를 통해 클래스 인스턴스를 생성을 하게 되면 아래와 같은 기본 클래스의 정보들을 그대로 사용 할수가 없게됩니다.


아래와 같은 json object를 선언한 상태를 가정합니다.

var BaseObject = {
  testFunction : function () {
    alert('test');
  }
};


예) new 키워드를 사용하여 클래스 인스턴스 생성시 오류

oop


예) constructor 메소드를 사용하여 변수에 할당, 상위 속성을 가져오지 못함

var aObject = BaseObject.constructor();
console.log(aObject);
oop


예) Object.assign 으로 변수에 할당

var aObject = Object.assign(BaseObject, {});
console.log(aObject);
oop


정상적으로 가져오는 것을 확인할 수가 있습니다.
하지만 이 방법은 객체를 생성하는 것이 아닌, 병합하여 사용하는 것이기 때문에 상위 오브젝트 및 같은 상위 오브젝트를 사용 한다면 아래와 같은 scope 문제가 발생합니다.

var aObject = Object.assign(BaseObject, {});
console.log(aObject); // {testFunction: f}

// 변수 값 변경
aObject.testFunction = 'test';
console.log(aObject); // {testFunction: "test"}
console.log(BaseObject); // {testFunction: "test"}

// 다른 변수에 할당
var bObject = Object.assign(BaseObject, {});
console.log(bObject); // {testFunction: "test"}


Javascript OOP 모듈화

위와 같은 문제로 모듈화를 OOP로 모듈화 하기로 하였습니다.
자바스크립트의 프로토타입(Prototype)을 사용하여 클래스를 작성합니다.

// base.js

var BaseObject = function (name) {
  this._name = name;
};
// 간단한 이름조회
BaseObject.prototype.getName = function () {
  return this._name;
};

// BaseObject 인스턴스 생성
var aObject = new BaseObject("홍길동");
console.log(aObject);
/*
  BaseObject {_name: "홍길동"}
  _name: "홍길동"
  __proto__:
  getName: ƒ ()
  constructor: ƒ (name)
  arguments: null
  caller: null
  length: 1
  name: "BaseObject"
  prototype: {getName: ƒ, constructor: ƒ}
  __proto__: ƒ ()
  [[FunctionLocation]]: VM14190:1
  [[Scopes]]: Scopes[2]
  __proto__: Object
*/


// 새로운 인스턴스 생성
var bObject = new BaseObject("길동이");
console.log(bObject);
/*
  BaseObject {_name: "길동이"}
  _name: "길동이"
  __proto__:
  getName: ƒ ()
  constructor: ƒ (name)
  arguments: null
  caller: null
  length: 1
  name: "BaseObject"
  prototype: {getName: ƒ, constructor: ƒ}
  __proto__: ƒ ()
  [[FunctionLocation]]: VM14190:1
  [[Scopes]]: Scopes[2]
  __proto__: Object
*/

// 이름 출력
console.log(aObject.getName()); // 홍길동
console.log(bObject.getName()); // 길동이


위 코드에 나오듯이 aObject, bObject의 생성자(constructor)에는 동일한 클래스 정보가 들어가있습니다.
json을 사용하면 클래스가 아니기 때문에 instanceof 를 통한 인스턴스 비교를 할 수가 없지만, 프로토타입(Prototype)를 사용하여 만든 오브젝트는 동일 인스턴스 유무를 확인 할 수가 있습니다.

// json object
var jsonBaseObject = { name : "홍길동"; };
var jsonObject = Object.assign(jsonBaseObject, {});
jsonObject instanceof jsonBaseObject // error

// prototype 클래스
aObject instanceof BaseObject // true
bObject instanceof BaseObject // true


이제 위 확인한 내용을 토대로 자바스크립트에서 클래스 단위로 모듈화를 설계할 수 있습니다.

// base.js
var BaseObject = function (name) {
  this._name = name;
  this._clickCount = 0;
};
// 간단한 이름조회
BaseObject.prototype.getName = function () {
  return this._name;
};
// 클릭 카운트 세기
BaseObject.prototype.click = function () {
  this._clickCount += 1;
};
// 클릭 카운트 조회
BaseObject.prototype.getClickCount = function () {
  return this._clickCount;
};

// index.js
var aObject = new BaseObject("메인페이지");
var bObject = new BaseObject("상세페이지");

// 메인페이지 클릭 3번
aObject.click();
aObject.click();
aObject.click();

// 상세페이지 클릭 5번
bObject.click();
bObject.click();
bObject.click();
bObject.click();
bObject.click();

// 클릭 횟수 확인
console.log(aObject.getClickCount());  // 3
console.log(bObject.getClickCount());  // 5


Conclusion

최근 개발흐름을 보니 react, vuejs 등 많은 자바스크립트 프레임워크나 타입스크립트(TypeScript) 가 있어 프로토타입(Prototype)을 이용한 클래스 설계는 잘 하지 않는 것 같습니다.
하지만 순수 자바스크립트로만 구현을 해야 할 상황이라면? 또는 자바스크립트에서 가벼운 클래스 설계가 필요할때는 프로토타입(Prototype)을 이용한 클래스 단위별 모듈화를 설계 하는게 좋은 작업이라고 생각됩니다.


참고

https://ko.wikipedia.org/wiki/객체_지향_프로그래밍
https://developer.mozilla.org/ko/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript


장현준 팀장 | R&D 개발3팀
janghj@brandi.co.kr
브랜디, 오직 예쁜 옷만