본문 바로가기
Design Pattern/Structural Design

[Design Pattern] (Structural) 모듈 패턴(Module Pattern)

by song.ift 2023. 3. 27.

디자인 패턴 유형

  • Creation Design Pattern
    • 객체의 생성에 관련된 패턴
    • 객체의 생성 로직을 숨김으로써 유연성을 향상시킨다.
  • Strutural Design Pattern
    • 클래스와 객체의 구성에 관련된 패턴
  • Behavioral Design Pattern
    • 객체와 객체 간의 통신에 관련된 패턴

 

[Structural Design Pattern] 모듈 패턴(Module Pattern)

모듈 패턴은 특정 구성요소를 다른 구성요소와 독립적으로 유지하는 패턴을 말한다.

  • 장점: 재사용성을 높히기 위한 코드를 작성할 때 유용하다
  • 단점: 코드가 길어지고 파일 크기도 늘어난다

 

 

Module 패턴

JavaScript에서의 모듈은 특정 구성요소를 다른 구성요소와 독립적으로 유지하는데 가장 널리 사용되는 디자인 패턴입니다. 이는 잘 구조화된 코드를 지원하기 위해 느슨한 결합을 제공합니다.

객체지향 언어에 익숙한 사람들을 위해 설명하자면, 모듈은 JavaScript의 “클래스”입니다. 클래스의 많은 장점 중 하나는 캡슐화입니다. 상태 및 동작을 다른 클래스에서 액세스하지 못하도록 보호합니다. 모듈 패턴은 public 및 private 접근 권한 설정을 가능하게 합니다.

모듈은 변수와 메서드를 보호하는 클로저(하지만 함수 대신 객체를 반환해야 합니다) 처럼 private 범위를 허용하는 IIFE (Immediately-Invoked-Function-Expressions)이어야합니다. 다음과 같은 형태입니다.

(function() {

    // private 변수들과 함수들을 선언

    return {
        // public 변수들과 함수들을 선언
    }

})();

클로저 외부에있는 코드는 동일한 범위에 있지 않으므로 private 변수에 접근할 수 없습니다. 보다 구체적인 구현해보겠습니다.

var HTMLChanger = (function() {
  var contents = 'contents'

  var changeHTML = function() {
    var element = document.getElementById('attribute-to-change');
    element.innerHTML = contents;
  }

  return {
    callChangeHTML: function() {
      changeHTML();
      console.log(contents);
    }
  };

})();

HTMLChanger.callChangeHTML();       // Outputs: 'contents'
console.log(HTMLChanger.contents);  // undefined

callChangeHTML은 반환된 객체에 바인딩되며 HTMLChanger 네임스페이스 내부를 참조할 수 있습니다. 그러나 모듈 외부에서는 contents를 참조할 수 없습니다.

REVEALING MODULE 패턴

Revealing Module Pattern 라고 불리는 모듈 패턴의 한 변형이 있습니다. 이 패턴의 목적은 캡슐화를 유지하고 객체 리터럴에서 반환된 특정 변수와 메서드들을 잘 나타내기 위한 것입니다. 다음과 같은 형태입니다.

var Exposer = (function() {
  var privateVariable = 10;

  var privateMethod = function() {
    console.log('Inside a private method!');
    privateVariable++;
  }

  var methodToExpose = function() {
    console.log('This is a method I want to expose!');
  }

  var otherMethodIWantToExpose = function() {
    privateMethod();
  }

  return {
      first: methodToExpose,
      second: otherMethodIWantToExpose
  };
})();

Exposer.first();        // Output: This is a method I want to expose!
Exposer.second();       // Output: Inside a private method!
Exposer.methodToExpose; // undefined

훨씬 깨끗해 보이지만 private 메서드를 참조할 수 없다는 명백한 단점을 가지고 있습니다. 이는 단위 테스트 문제를 야기할 수 있고, 비슷한 문제로 모듈 외부에서 반환된 메서드들을 오버라이드를 할 수 없게 됩니다.

 

 

 

 

 모듈 패턴 (Module Pattern)

모듈은 프로젝트의 코드를 간결하고 재사용성이 좋은 구조로 작성하는 데 도움을 주며,

모듈을 구현하는 가장 쉬운 방법은 객체 리터럴을 사용하는 방법이다.

 

var obj = {
  key: 'value',
  method: function () {
    console.log('hello world');
  }
}

 

객체 리터럴은 사용하기 편하지만 위와 같이 작성했을 경우 보안에 취약하다.

 

자바스크립트에서 리터럴을 사용할땐 글로벌 공간에 변수를 선언하는 것은 되도록 피해야 한다.

 

const PlusMinus =(function () {
  let num = 0;
  
  return {
     plus: function () {
       num++;
     },
     minus: function () {
       num--;
     },
     getNum: function () {
       return num;
     }
  } 
})()

 

위와 같이 클로저나 익명 함수를 사용하여 객체를 리턴하고 변수를 함수 안에 선언하여 보호한다.

 

위 코드는 함수를 익명 함수로 감싸 변수를 보호할 수 있고, 재사용성을 높일 수 있다.

 

(function () {
  function plusMinus () {
    let num = 0;
  
    return {
       plus: function () {
         num++;
       },
       minus: function () {
         num--;
       },
       getNum: function () {
         return num;
       }
    }
  }
  
  let num1 = plusMinus();
  let num2 = plusMinus();
  
})()

 

댓글