React에서 로컬 캐싱 직접 구현하기

2023. 1. 10.·🎨 프론트엔드 공부/React & Next

📍목표

- 검색 API를 호출할 때, API 응답 데이터를 저장하기

- 같은 키워드를 두 번 검색한 경우, API를 호출하지 않고, 저장된 데이터를 활용하기

- data fetching 라이브러리 사용하지 않고 이를 구현하기

 

📍로컬 캐싱

글로벌 캐싱과 다르게, 로컬내에 캐시를 저장해야 함 (in-memory or web storage)

- local 에서 작동하기 때문에 속도가 빠름 (네트워크 필요 X)

 

캐시를 로컬 스토리지 혹은 세션 스토리지에 저장하면 새로고침 시 데이터 휘발을 막을 수 있지만, 검색 API의 응답 데이터는 중요한 데이터도 아니므로 in-memory에 저장해도 된다 (권장되는 방법)

그리고 웹 스토리지의 경우 메모리 크기에 제한이 있기도 하고, 읽기 쓰기 속도도 당연히 느리다

 

📍캐시를 어디에 저장하지? => useRef

useState와 다르게 내부 값이 변해도 리렌더링이 발생하지 않는다. 따라서 캐시를 담기에 매우 적합!

- 만약 useState를 활용하여 캐시를 저장하면, 검색에 따른 불필요한 리렌더링이 발생

 

📍캐싱 기능을 갖춘 useFetch hooks

export const useFetch = (keyword: string) => {
  // cache 객체를 useRef로 생성
  const cache = useRef<cacheType>({});

  // 예외처리
  const initialState: stateType = {
    status: "idle",
    error: null,
    data: [],
  };

  const [state, dispatch] = useReducer(
    (state: stateType, action: actionType) => {
      switch (action.type) {
        case "FETCHING":
          return { ...initialState, status: "fetching" };
        case "FETCHED":
          return { ...initialState, status: "fetched", data: action.payload };
        case "FETCH_ERROR":
          return { ...initialState, status: "error", error: action.payload };
        default:
          return state;
      }
    },
    initialState
  );

  useEffect(() => {
    let cancelRequest = false;

    if (!keyword.trim()) {
      dispatch({ type: "FETCHED", payload: [] });
      return () => {
        cancelRequest = true;
      };
    }

    const fetchData = async () => {
      dispatch({ type: "FETCHING" });
      // 이미 검색한 데이터라면 캐시에 존재하는 데이터 반환
      if (cache.current[keyword]) {
        console.info(
          "%ccached data",
          "background: radial-gradient(red, green, blue); padding: 1px;"
        );
        const data = cache.current[keyword];
        dispatch({ type: "FETCHED", payload: data });
      } else {
        // 검색 이력이 없다면 API 호출 후 캐싱
        console.info(
          "%ccalling api",
          "background: radial-gradient(grey, black, grey); padding: 1px;"
        );
        const response = await fetch(keyword);
        const data = await response.json();
        // 캐시에 저장
        cache.current[keyword] = data;
        if (cancelRequest) return;
        dispatch({ type: "FETCHED", payload: data });
      }
    };

    fetchData();
    return () => {
      cancelRequest = true;
    };
  }, [keyword]);

  return state;
};

 

검색 이력이 존재 (캐시에 데이터 존재)하면 API 미호출

검색 이력이 없으면 API 호출

 

이렇게 직접 로컬 캐싱을 구현할 수 있었다.

React Query를 사용하면 자동으로 캐싱이 적용되고, stale time이나 cache time을 지정해서 캐시된 데이터의 freshness 를 관리할 수 도 있다!

이러한 fetching 라이브러리의 유용함을 알게 됐다

 

📍참고

https://kk-programming.tistory.com/83

 

[Cache] 캐시란?, 로컬캐싱 vs 글로벌 캐싱, 캐시전략들

✅ 파레토의 법칙 사회에서 일어나는 현상의 80%는 20%의 원인으로 인해 발생된다. 인터넷 통신의 80%가 20%의 사이트에 대한 액세스로 추정되며, 이 20%의 웹사이트 데이터를 캐시해두면 효율을 극

kk-programming.tistory.com

 

'🎨 프론트엔드 공부/React & Next' 카테고리의 다른 글
  • fast refresh, code splitting
  • Next.js 을 사용하는 이유
  • React에서 드래그 앤 드랍 직접 구현하기
  • React를 사용하는 이유 3가지
지식물원
지식물원
지식이 자라는 식물원!
  • 지식물원
    지식물원
    지식물원
  • 전체
    오늘
    어제
    • 분류 전체보기 (516)
      • 🎨 프론트엔드 공부 (253)
        • JS & TS (92)
        • HTML & CSS (22)
        • React & Next (49)
        • Vue & Nuxt (22)
        • 기타 (68)
      • 🤓 기술 학습 & 공부 기록 (116)
        • Node.js (0)
        • Python (37)
        • 백엔드 (0)
        • 딥러닝 (1)
        • 컴퓨터 일반 (72)
        • 개발 인프라 (6)
      • 👨‍💻 프로젝트 경험 (6)
        • Work (0)
        • Toy (6)
      • ⚙️ 개발 팁 & 노하우 (21)
        • 프론트엔드 (6)
        • 기타 (15)
      • ☕️ 커리어 & 인터뷰 준비 (88)
        • 코딩 테스트 (88)
      • 📰 기술 트렌드 & 생각 정리 (4)
      • 📚 기타 (25)
        • 마케팅 (15)
        • 비개발서적 (10)
  • 블로그 메뉴

    • 태그
  • 링크

  • 공지사항

    • 모바일 접속 시 코드 하이라이팅 깨질 때
  • 인기 글

  • hELLO· Designed By정상우.v4.10.3
지식물원
React에서 로컬 캐싱 직접 구현하기
상단으로

티스토리툴바