프로그래밍 숲

자바스크립트 데코레이터와 캐싱: 함수 호출 결과 캐시 예제 분석 본문

프로그래밍_인포/Javascript

자바스크립트 데코레이터와 캐싱: 함수 호출 결과 캐시 예제 분석

jjscript 2023. 6. 23. 09:20
728x90
반응형

코어 자바스크립트 6.9 call/apply와 데코레이터, 포워딩을 공부하던 중에 데코레이터의 예시코드의 순서가 이해가 잘 가지 않아서 정리해보았습니다.

 

call/apply와 데코레이터, 포워딩

 

ko.javascript.info

 

function slow(x) {
  // CPU 집약적인 작업이 여기에 올 수 있습니다.
  console.log(`slow(${x})을/를 호출함`);
  return x;
}

function cachingDecorator(func) {
  let cache = new Map();

  return function (x) {
    if (cache.has(x)) { // cache에 해당 키가 있으면
      console.log('캐시 있으면 여기찍힘');
      return cache.get(x); // 대응하는 값을 cache에서 읽어옵니다.
    }
    console.log('캐시 없으면 여기찍힘');
    let result = func(x); // 그렇지 않은 경우엔 func를 호출하고,
    cache.set(x, result); // 그 결과를 캐싱(저장)합니다.
    return result;
  };
}

slow = cachingDecorator(slow);

console.log(slow(1)); // slow(1)이 저장되었습니다.
console.log('다시 호출: ' + slow(1)); // 동일한 결과

console.log(slow(2)); // slow(2)가 저장되었습니다.
console.log('다시 호출: ' + slow(2)); // 윗줄과 동일한 결과

처음에 두 함수를 정의하는 코드가 나옵니다.

function slow(x) {
  // CPU 집약적인 작업이 여기에 올 수 있습니다.
  console.log(`slow(${x})을/를 호출함`);
  return x;
}
function cachingDecorator(func) {
  let cache = new Map();

  return function (x) {
    if (cache.has(x)) {
      // cache에 해당 키가 있으면
      console.log('캐시 있으면 여기찍힘');
      return cache.get(x); // 대응하는 값을 cache에서 읽어옵니다.
    }
    console.log('캐시 없으면 여기찍힘');

    let result = func(x); // 그렇지 않은 경우엔 func를 호출하고,
    console.log(result);
    cache.set(x, result); // 그 결과를 캐싱(저장)합니다.
    return result;
  };
}

 

 

slow = cachingDecorator(slow);

그 다음에 이 코드가 있는데, 이 부분이 잘 이해가 안갔습니다. 함수인데 괄호 없이 재할당을 한다는 것 자체가 이해가 잘 안갔습니다. 그래서 나의 코딩 선생님 gpt로 찾아보니 다음과 같은 이유에서 함수를 참조할수 있었던 것입니다.

JavaScript에서 함수 이름만을 사용하여 함수를 참조할 수 있습니다. slow는 함수 이름이며, 변수로서의 역할을 수행합니다. 따라서 slow를 단독으로 사용하여 변수로 참조할 수 있습니다.
함수를 호출하기 위해서는 ()를 사용해야 합니다. 예를 들어, slow(1)과 같이 괄호를 사용하여 slow 함수를 호출할 수 있습니다.

결국 위의 코드는 slow라는 변수에 cachingDecorate라는 새로운 함수를 할당한 것입니다.

 

이후에 console.log를 통해 함수의 실행과 출력이 일어나게 됩니다.

console.log(slow(1)); // slow(1)이 저장되었습니다.
console.log('다시 호출: ' + slow(1)); // 동일한 결과

slow(1)이 실행되면 cachingDecorater함수가 실행되는 것이고, 캐시를 확인하는 작업이 일어나게 됩니다. 캐시가 없기 때문에 '캐시 없으면 여기찍힘' 콘솔이 가장 먼저 찍히게 됩니다.

 

그 이후에 let result = func(x); 이 실행되게 되는데 result에 func(x)의 return 값을 할당해줘야 하기 때문에, 자연스럽게 func(x)이 실행되게 됩니다.  그 과정에서   console.log(`slow(${x})을/를 호출함`); 이 실행되고, slow(1)로 함수를 실행시켰기 때문에 'slow(1)을/를 호출함'이라는 콘솔이 찍히게 됩니다.

 

그리고 result에 할당된 1이 console.log를 통해 찍히게 됩니다.

 

이제 console.log('다시 호출: ' + slow(1));이 실행되고, 이제는 캐시에 저장이 됐기 때문에  if (cache.has(x)) 이 true가 되고 console.log('캐시 있으면 여기찍힘');이 실행됩니다.

 

결국 slow(1)의 return 값으로 캐시에 저장된 1이 나오게 되고, console.log('다시 호출: ' + slow(1));의 결과가 '다시 호출: 1'로 출력되게 됩니다.

 

console.log(slow(2)); // slow(2)가 저장되었습니다.
console.log('다시 호출: ' + slow(2)); // 윗줄과 동일한 결과

위의 콘솔은 slow(1)과 같은 매커니즘으로 실행되게 됩니다.

728x90
반응형
Comments