Closure 를 이용한 중복 호출 캐싱 구현

houndhollis·6일 전
0

간만에 글을 적는다.

소소한 근황

그 간 많은 일들이 있었다 내가 가보고 싶은 곳의 면접도 보고 결과가 어찌 되었든 최선을 다했다고 생각한다.


한번씩 면접에 엄청난 에너지를 쏟아 채용과정을 진행하고, 불합격 한 경우 조금 맥이 빠지는 경우가 있지만 해볼만 하다고 항상 생각하는거 같다.

본론으로 들어가서

클로져 이용한 중복호출 개선 (값 캐싱 해보기)

꼭 이런 경우가 있는건 아니지만, 테스트를 하기위해,

const fetchTodos = () =>
  axios.get<Todos[]>("https://jsonplaceholder.typicode.com/todos");
const fetchTodoItem = () =>
  axios.get<TodoItem[]>("https://jsonplaceholder.typicode.com/todos/1");

const fetchAllTodo = () =>
  Promise.all([
   	fetchTodos(),
    fetchTodoItem(),
    fetchTodos(),
    fetchTodoItem(),
  ]);

이렇게 중복으로 호출 하는 값이 있다고 보자
그러면 네트워크에 정확하게 4번의 값이 찍힐 것이다.
나의 예상은 적중했다 👍

하지만 우리는 알고 있다 중복 호출에 대해서는 값을 캐싱하고 반환해주면 된다는 것을 그리하여 작업을 시작했다.

클로져 구현

const createJsFetchCache = () => {
  const cache = new Map();

  return (url: string): Promise<AxiosResponse<Todo[] | TodoItem[]>> => {
    if (cache.has(url)) {
      return cache.get(url);
    }

    const request = axios.get<Todo[] | TodoItem[]>(url);

    cache.set(url, request);
    request
      .catch(() => {
        cache.delete(url);
      });

    return request;
  };
};

const jsFetchCache = createJsFetchCache();

const fetchTodos = () =>
  jsFetchCache("https://jsonplaceholder.typicode.com/todos");
const fetchTodoItem = () =>
  jsFetchCache("https://jsonplaceholder.typicode.com/todos/1");

처음에는, 클로져를 이용할려 하지 않고, cache를 전역으로 관리하는 코드로 작성을 해보기도 했다 물론 그렇다고 해서 결과값이나 동작이 달라지진 않았다 하지만 주제가 클로져인 관계로 클로져로 작성을 했다

네트워크 에서도 2번만 찍히는 모습을 볼 수 있다.

동작 방식을 보면

처음 if문에서는 캐싱된 값이 없어 넘어갈 것이다, 여기서 중요한것은 Promise 자체를 바로 cache에 저장함으로서, Promise.all 을 사용한 병렬에도 중복 호출을 하지 않게 한다, 그 결과 이행 상태가 되면 값을 반환을 한다. 추가로 request에서 에러가 날 경우, 먼저 set을 해준 부분을 삭제 처리하는 로직까지 넣어두긴 했다.

TTL, Size 등을 생각해서 추가로 작성 한다면 더 좋은 캐싱 전략이 될꺼 같기도 하다

const jsFetchCache = createJsFetchCache();

// 해당 부분이 귀찮다고 생각이 들면,
const createJsFetchCache = (() => {
  const cache = new Map();
  
	// 내용 생략...
  
  };
})();

즉시실행 함수로 변경하여,

const fetchTodos = () => createJsFetchCache("/schedules-majors.json");
const fetchTodoItem = () =>
  createJsFetchCache("/schedules-liberal-arts.json");

하는 것도 가능하다

그럼 왜 클로져?

cache 값을 클로져의 경우 내부에서 관리해서 외부 접근이 불가능 하지만, 클로져 활용 ❌ 에서는 외부 접근이 가능하여 잘못된 접근이나 의도치 않은 수정으로 인해 문제가 발생할 수 있으며, 모듈화 에서도 차이가 발생

(클로져를 사용한 경우는 독립적인 캐싱 인스턴스를 활용할 수 있지만, 하지 않은 예시에서는 불가능 하다)

개인적이지만, 사용하지 않은 쪽이 조금 더 직관적이고 간결해 보이기도 하다.(지극히 개인적)

profile
한 줄 소개

0개의 댓글