📍목표
- 검색 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