ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JS] cachingdecorator 에서 어떻게 Map으로 저장한 데이터가 유지될까?
    문득 든 의문점 2022. 12. 15. 17:08
    반응형

    Caching Decorator

    function slow(x) {
      // CPU 집약적인 작업이 여기에 올 수 있습니다.
      alert(`slow(${x})을/를 호출함`);
      return x;
    }
    
    function cachingDecorator(func) {
      let cache = new Map();
    
      return function(x) {
        if (cache.has(x)) {    // cache에 해당 키가 있으면
          return cache.get(x); // 대응하는 값을 cache에서 읽어옵니다.
        }
    
        let result = func(x);  // 그렇지 않은 경우엔 func를 호출하고,
    
        cache.set(x, result);  // 그 결과를 캐싱(저장)합니다.
        return result;
      };
    }
    
    slow = cachingDecorator(slow);
    
    alert( slow(1) ); // slow(1)이 저장되었습니다.
    alert( "다시 호출: " + slow(1) ); // 동일한 결과
    
    alert( slow(2) ); // slow(2)가 저장되었습니다.
    alert( "다시 호출: " + slow(2) ); // 윗줄과 동일한 결과

      위 코드는 javscript.info 사이트에서 가져온 cachinDecorator의 예제이다.  위 코드에서 cachingDecorator는 function(x)을 반환한다 function(x)은 cache에 x의 결과값이 저장되어있으면 해당 결과값을 바로 반환하고 그 외의 경우 cachingDecorator가 받은 func함수에 인자로 넘긴 결과값을 반환한다.

     

    클로저

      클로저는 outer 함수의 변수나 파라메터에 접근하는 함수이다. 예를 들면 클로저에서 외부 함수의 i라는 변수에 접근한다고 가정해보자, 만약 i가 constant라면 큰 문제가 되지 않을 것이다. 하지만 만약 i가 변수이고 우리의 의도가 i가 변하는 것을 이용해 결과를 내는 것이라면 이 부분에서 문제가 발생할 수 있다. 아래 코드를 보자

     

    let arr = []
    
    for (let i = 0; i < 10; i++) {
    	arr[i] = function(i) {
        	return i * 10
        }
    }
    
    console.log(arr[1]()) //100

     

     

     만약 위 코드를 통해 [10, 20, 30, ..., 100]의 arr에 저장된 함수가 반환하기를 기대하고 작성했다면, 코드가 의도와는 다르게 동작함을 깨달을 것이다. 이는 앞서 말했듯이 arr에 저장된 함수는 outer 함수의 변수인 i를 참조하고 있으며 arr[1]() 호출되었을 때엔 i는 이미 루프를 모두 돌고 10이 됐기 때문이다. 이를 해결하기 위해 즉시실행 함수를 사용하기도 하는데 거기까진 설명하지 않겠다.

     

    정리

      다시 돌아와서, cachingdecorator 에서 어떻게 Map으로 저장한 데이터가 유지될까? 그 이유는 우리가 slow에 cashingDecorator함수의 리턴값을 저장했기 때문이다. 즉 slow는 아래 코드로 변경되었으며, 클로저로서 기능한다.

     

    function(x) {
        if (cache.has(x)) {    // if there's such key in cache
          return cache.get(x); // read the result from it
        }
    
        let result = func(x);  // otherwise call func
    
        cache.set(x, result);  // and cache (remember) the result
        return result;
      };

     

     

    이 코드는 cachingDecorator의 cache 변수를 참조하고 조건에 따라 데이터를 불러오거나 추가한다. 즉, cache는 클로저 예시코드의 i 처럼 동작한다. 클로저가 호출될때 조건에 따라 업데이트되고 가비지 컬렉션에 의해 지워지지 않는이상 유지되는 것이다.

    반응형

    댓글

Designed by Tistory.