자바스크립트 모듈패턴이란? (1)

danmin20·2021년 2월 23일
0

Javascript

목록 보기
7/9

namespace?

네임스페이스란 수많은 함수, 객체, 변수들로 이루어진 코드가 전역 유효범위를 어지럽히지 않고, 애플리케이션이나 라이브러리를 위한 하나의 전역 객체를 만들고 모든 기능을 이 객체에 추가하는 것을 말한다.
즉, 코드에 네임스페이스를 지정해주면, 코드 내의 이름 충돌뿐만 아니라 이 코드와 같은 페이지에 존재하는 또 다른 자바스크립트 라이브러리나 위젯 등 서드파티 코드와의 이름 충돌도 미연에 방지할 수 있다.
이러한 네임스페이스를 자바스크립트에서는 모듈패턴으로 흉내낼 수 있다.

module?

모듈이란 전체 애플리케이션 중 일부를 독립된 코드로 분리해서 만들어 놓은 것이다. 유용한 기능을 모아둔 것으로 볼 수 있다.
자바스크립트에서는 모듈을 구현하는 가장 쉬운 방법은 객체 리터럴을 사용하는 방법이다.

var module = { 
  key : 'value', 
  pulicMethod : function () { } 
}

즉, 객체 리터럴은 하나의 객체라는 점에서 싱글톤 패턴으로 볼 수도 있고, 독립된 모듈이라는 점에서 모듈패턴으로 볼 수도 있다.

독립된 모듈은 자체적으로 필요한 내부 변수 및 내부 함수를 모두 갖고 있어야 하므로 클로저를 이용하여 구현해야 한다.

var Module = (function () { 
  // 은닉될 멤버
  var privateKey = 0; 
  function privateMethod() { 
    return ++privateKey; 
  } 
  // 공개될 멤버 (특권 메소드) 정의 
  return { 
    publickey : privateKey, 
    publicMethod : function () { 
      return privateMethod(); 
    } 
  } 
})(); 

console.log(Module.publicMethod()); // 1
console.log(Module.publicMethod()); // 2 (클로저로 인한 결과)

위의 코드를 실행하면 익명함수가 자동으로 호출되어 익명함수가 반환하는 객체가 Module 변수에 할당된다.

아래와 같이 자동으로 호출(self-invoking)되는 구조를 없애면, 여러 개의 인스턴스를 생성할 수 있다.

var Module = function () { 
  // 은닉될 멤버 정의 
  var privateKey = 0; 
  function privateMethod() { 
    return ++privateKey; 
  } 
  // 공개될 멤버 (특권 메소드) 정의 
  return { 
    publickey : privateKey, 
    publicMethod : function () { 
      return privateMethod(); 
    } 
  } 
}; 

var obj1 = Module(); 
obj1.publicMethod(); // 1 출력 
obj1.publicMethod(); // 2 출력 

var obj2 = Module(); 
obj2.publicMethod(); // 1 출력 
obj2.publicMethod(); // 2 출력

내부의 익명함수에서 함수가 아니라 객체를 반환한다는 점에서 클로저와 차이점이 있다.

장단점

단점

  • 전체적으로 코드량이 약간 더 많아져서 파일크기도 증가한다.
  • 전역 인스턴스가 하나이기 때문에 코드의 어느 한 부분이 수정되면 전역 인스턴스도 수정된다.

장점

  • 코드를 정리하는 방법으로 널리 사용되며, 자바스크립트 코딩패턴에서 권장하는 방법이다.

기본 모듈패턴

// 1. 네임스페이스를 설정하고 모듈을 정의
var MyApp = {} // 전역 객체
MyApp.modules = {}

/*
 2. 공개범위(특권메소드 등..)와 비공개 유효범위를 만든다
 -> 즉시 실행함수로 모듈이 될 객체를 반환하고, 공개 인터페이스가 담기게 된다.
 */
MyApp.modules.libs = (function() {

    // 비공개 프로퍼티 (private 멤버)

    // 공개 프로퍼티  (public, previlege 멤버)
    return {

    };
}());

자바스크립트의 객체 프로퍼티

자바스크립트의 경우, private, protected, public 속성을 나타내는 별도의 문법이 없다.
자바스크립트 객체의 프로퍼티는 모두 public하다.

하지만 private member의 개념이 존재하긴 하는데,
예를 들어 함수 안에서 정의한 변수는 함수 밖에서 접근할 수 없으므로 private member로 여겨진다. (함수의 매개변수, 지역 변수, 내부 함수 등)

네임스페이스 패턴

프로그램의 복잡도가 증가하고 코드의 각 부분들이 별개의 파일로 분리되어 선택적으로 문서에 포함하게 되면, 어떤 코드가 특정 네임스페이스나 그 내부의 프로퍼티를 처음으로 정의한다고 가정하는 것은 위험하다. 네임스페이스에 추가하려는 프로퍼티가 이미 존재한다면 내용을 덮어쓰게 될 수도 있다.
따라서 네임스페이스를 생성하거나 프로퍼티를 추가하기 전에 존재 여부를 확인해야 한다.

// 위험
var MYAPP = {}; 

// 개선안 1
if (typeof MYAPP === 'undefined') {
  MYAPP = {}; 
} 

// 개선안 2
var MYAPP = MYAPP || {};

이렇게 추가되는 확인 작업 때문에 상당량의 중복 코드가 생겨날 수 있다.
따라서 네임스페이스 생성의 실제 작업을 맡아 줄 재사용 가능한 함수를 만들어두면 편리하다.

다음은 네임스페이스 함수를 구현한 예제이다.
해당 네임스페이스가 존재하면 덮어쓰지 않기 때문에 기존 코드를 망가뜨리지 않는다.

var MYAPP = MYAPP || {}; 
MYAPP.namespace = function (ns_string) { 
  var parts = ns_string.split('.'), 
      parent = MYAPP, 
      i; 
  
  // 처음에 중복되는 전역 객체명은 제거한다. 
  if (parts[0] === 'MYAPP') { 
    parts = parts.slice(1); 
  } 
  for (i = 0; i < parts.length; i += 1) { 
    if (typeof parent[parts[i]] === 'undefined') { 
      parent[parts[i]] = {}; 
    } 
    parent = parent[parts[i]]; 
  } 
  return parent; 
};

의존 관계 선언

자바스크립트 라이브러리들은 대개 네임스페이스를 지정하여 모듈화되어 있기 때문에, 필요한 모듈만 골라서 사용할 수 있다. 이때 함수나 모듈 최상단에, 의존 관계에 있는 모듈을 선언하는 것이 좋다.
즉, 지역변수를 만들어 모듈을 가리키도록 선언하는 것이다.

var myFunction = function () { 
  // 의존 관계에 있는 모듈들 
  var event = YAHOO.util.Event, 
      dom = YAHOO.util.Dom; 
  
  // event 와 dom 변수 사용 가능 
};

간단하지만 상당히 많은 장점을 가진다.

  • 의존 관계가 명시적으로 선언되어 있기 때문에, 페이지 내에서 반드시 포함시켜야 하는 스크립트 파일이 무엇인지 알 수 있다.
  • 함수의 첫머리에 의존 관계가 선언되기 때문에 의존 관계를 찾아내고 이해하기 쉽다.
  • dom 과 같은 지역 변수는 YAHOO 와 같은 전역 변수보다 더 빠르며, YAHOO.util.Dom 처럼 전역 변수의 중첩 프로퍼티와 비교하면 더욱 빠르다.
    의존 관계 선언 패턴을 잘 지키면 함수 안에서 전역 객체 판별을 단 한번만 수행하고 이 다음부터는 지역 변수를 사용하기 때문에 훨씬 빠르다.

Reference

  • https://webclub.tistory.com/5?category=501048
  • https://webclub.tistory.com/78?category=501048
  • https://webclub.tistory.com/521?category=501048
profile
FE developer 😉

0개의 댓글