5.3 프락시 패턴

프락시(proxy)패턴은 자바스크립트에서 구현하기 쉬운(?) 패턴이다. 이유는 자바스크립트에서 함수도 하나의 객체처럼 정의해서 사용할수 있고, 객체의 속성을 문자열로 접근할 수 있는 특징이 있기 때문이다. 프락시 패턴은 말그대로(?) 하나의 객체가 프락시 역할을 수행하여 상황에 따라 다른 객체에 접근하게 해주거나 다른 함수를 호출하게 해주는 패턴이다.

프락시란, 클라이언트와 서버 연동에서 클라이언트가 바로 서버에 접근하는 것이 아니라 프락시를 통해서 간접적으로 접근할 수 있게 해준다. 프락시는 내부적으로 다양한 기능(여기서는 다른 객체에 접근이나 함수를 호출)을 제공하는 역할을 수행한다.

프락시의 역할 중 대표적인 것은 클라이언트가 서버에 직접 접근하지 못하도록, 한 단계 가상화 또는 캡슐화하는 것이다.

또한 클라이언트가 request를 프락시에 한번만 전달하면, 프락시는 서버로 여러번의 복잡한 real request를 보낸다.(이게 좋은거야? 많이보내는데 ㅋㅋㅋ?) 응답또한 마찬가지로 서버가 여라개의 real response 를보내면 프락시에서 취합하여 하나의 respose로 보내는 기능을 수행한다.(이건좋아보이네) 또는 반대로 클라이언트가 비슷한 request를 여러번 보낼때 서버로 그러한 request를 묶어 하나의 request로 보내는 역할을 수행하기도 한다. 부가적으로 웹에서 프락신는 캐시기능을 수행하기도 한다.

<!--생략-->
<video src="http://media.w3.org/2010/05/bunny/movie.ogv" id="videoBunny" style="width:480px;"></video>
<div id="controlpanel">
  <button id="play">Play</button>
  <button id="pause">pause</button>
  <button id="volumeUp">volumeUp</button>
  <button id="volumeDown">volumeDown</button>
</div>
<!--생략-->
(function(){
  var divControlPanel = document.getElementById('controlpanel'),
      videoBunny = document.getElementById('videoBunny'),
      proxyClickEventHandler = {
        "play": function(){
          videoBunny.play();
        },
        "pause": function(){
          videoBunny.pause();
        },
        "volumeUp": function(){
          if(videoBunny.volume <= 0.9){
            videoBunny.volume+=0.1;
          }else{
            videoBunny.volume = 1;
          }
        },
        "volumeDown": function(){
          if(videoBunny.volume >= 0.1){
            videoBunny.volume-=0.1;
          }else{
            videoBunny.volume = 0;
          }
        }
      };

  divControlPanel.addEventListener("click", function(e){
    var target = e.target||e.srcElement;
    if(proxyClickEventHandler.hasOwnProperty(target.id)){
      proxyClickEventHandler[target.id].call();
    }
  },true);
})();

위 소스를 보면 프락시변수(proxyClickEventHandler)를 하나 생성하는데, 이변수에 각 버튼의 클릭 이벤트를 처리하는 함수들을 정의하고 있다. 그리고 클릭 이벤트 핸들러에서 클릭 이벤트 발생 대상의 id를 기준으로 프락시 속성에 접근해서 함수를 호출한다. 이처럼 프락시 변수를 정의해놓으면 클릭 이벤트 핸들러들을 따라가는 것이 아니라, 로직이 포함된 프락시변수(proxyClickEventHandler.hasOwnProperty(target.id))만 보면되기 때문에 소스관리가 더 유용해진다. 위의 예제를 조금 더 프락시와 유사하게 변경한다면, 다음처럼 <video> 태그 여러개를 <select>태그로 선택해서 제어하게 할 수 있다.

<!--생략-->
<video src="http://media.w3.org/2010/05/bunny/movie.ogv" id="videoBunnySmall" style="width:240px;"></video>
<video src="http://media.w3.org/2010/05/bunny/movie.ogv" id="videoBunnyMedium" style="width:320px;"></video>
<video src="http://media.w3.org/2010/05/bunny/movie.ogv" id="videoBunnyLarge" style="width:480px;"></video>
<div id="controlpanel">
  <select id="controlVideo">
    <option>videoBunnySmall</option>
    <option>videoBunnyMedium</option>
    <option>videoBunnyLarge</option>
  </select>
  <button id="play">Play</button>
  <button id="pause">pause</button>
  <button id="volumeUp">volumeUp</button>
  <button id="volumeDown">volumeDown</button>
</div>
<!--생략-->
(function(){
  var divControlPanel = document.getElementById('controlpanel'),
      //select태그를 선택한다. 아래를 보다보면 selectControlVideo.value를 지정하는 코드가있다.
      //selectControlVideo.value는 당연히 option의 값이다.
      selectControlVideo = document.getElementById('controlVideo'),

      controlVideo = {
        "play": function(video){
          video.play();
        },
        "pause": function(video){
          video.pause();
        },
        "volumeUp": function(video){
          if(video.volume <= 0.9){
            video.volume+=0.1;
          }else{
            video.volume = 1;
          }
        },
        "volumeDown": function(video){
          if(video.volume >= 0.1){
            video.volume-=0.1;
          }else{
            video.volume = 0;
          }
        },
        "getVideoById": function(id){
          return document.getElementById(id);
        }
      },

      proxyClickEventHandler = function(command){
        var video;
        if(controlVideo.hasOwnProperty(command)){
          //option값이랑 동일한 id를 가진 video를 선택한다.
          video = controlVideo.getVideoById(selectControlVideo.value);
          //video를 선택한 command의 클로저(파라미터)로 사용한다.
          controlVideo[command].call(this, video);
        }
      }

  divControlPanel.addEventListener("click", function(e){
    var target = e.target||e.srcElement;
    proxyClickEventHandler(target.id);
    console.log(target.id);
  },true);

})();

위 소스에서는 클라이언트 - 서버 구조와 비교하여 서버의 역할을 controlVideo객체가 담당하고 있고, proxyClickEventHandler()함수가 프락시역할을 수행하고 있다고 볼 수 있다. 프락시에서는 이벤트에 대한 처리요청이 오면 <select>에 대한 정보를 수집한 다음, 해당하는 <video>를 제어 할 수 있도록 이 정보를 가공하여 controlVideo에 넘겨준다.

results matching ""

    No results matching ""