React Query같은 라이브러리를 쓰지 않고 내장된 Service Worker API를 통해 간단히 캐싱 기능을 구현할 수 있다.
https://developer.mozilla.org/ko/docs/Web/API/Cache
Cache 인터페이스들의 메서드는 위의 DOCS에서도 확인이 가능하고, 코드로도 쉽게 확인이 가능하다.
메서드들을 쉽게 사용하기 위해 유틸 함수 몇 개를 만들어보자.
//utilities/cache.ts
/**
* 해당 이름을 가진 스토리지를 반환한다.
* 만들어져 있다면, 만들어진 스토리지를, 없다면 만들어서 반환한다.
* @param storageName
* @returns
*/
export const openCache = async (storageName: string): Promise<Cache> => {
const storage = await window.caches.open(storageName);
return storage;
};
/**
* 스토리지 안에 URL을 키로, 데이터를 저장한다.
* @param storageName
* @param url
* @param res
*/
export const putCache = async (
storageName: string,
url: string,
res: Response
) => {
const storage = await window.caches.open(storageName);
storage.put(url, res);
};
/**
* 스토리지 안에 URL를 키로 가진 캐시 데이터를 삭제한다.
* @param storageName
* @param url
*/
export const deleteCache = async (storageName: string, url: string) => {
const storage = await openCache(storageName);
storage.delete(url);
};
/**
* 스토리지 안에 요청한 URL을 키로 가진 캐시 데이터가 있는지 확인한다.
* @param storageName
* @param url
* @returns 캐시 데이터가 없다면 undefined를 반환한다.
*/
export const matchCache = async (storageName: string, url: string) => {
const storage = await openCache(storageName);
return storage.match(url);
};
/**
* 스토리지 안에 URL를 키로 가진 캐시 데이터가 있는지 확인 후,
* 있다면 캐시 데이터를 반환하고
* 없다면 API를 요청해 response를 반환한다.
* @param storageName
* @param requestUrl
* @param callback
*/
export const call = async <T>(
storageName: string,
requestUrl: string,
callback?: (res: T, resType: string) => void
) => {
const cacheData = await matchCache(storageName, requestUrl);
if (cacheData) {
cacheData.json().then((res: T) => {
callback && callback(res, "cache data");
});
} else {
fetch(requestUrl).then((res) => {
putCache(storageName, requestUrl, res);
res
.clone()
.json()
.then((res: T) => {
callback && callback(res, "api response");
});
});
}
};
이제 call 함수에 요청할 url만 잘 넘겨준다면 해당 요청에 해당하는 캐시 데이터가 있다면 캐싱된 데이터를 반환할 것이고,
없다면 api를 호출한 후 response를 캐싱할 것이다.
간단하게 버튼 2개를 만들어 테스트해보자.
//App.tsx
import { deleteCache, call } from "./utilities/cache";
const url =
"https://www.7timer.info/bin/astro.php?lon=113.2&lat=23.1&ac=0&unit=metric&output=json&tzshift=0" as const;
const storage = "testStorage" as const;
function App() {
const handleCall = () => {
call(storage, url, (res, resType) => console.log(resType, res));
};
const handleDeleteCache = () => {
deleteCache(storage, url);
};
return (
<div style={{ display: "flex", padding: 50, gap: 20 }}>
<button onClick={handleCall}>API 호출</button>
<button onClick={handleDeleteCache}>캐시 제거</button>
</div>
);
}
export default App;
api를 최초 호출한 후엔 캐싱된 데이터를 불러오는 걸 확인할 수 있다.
캐시를 제거하게 되면 다시금 api를 호출한다.
https://github.com/Lee-Minhoon/blog-examples/tree/main/web-cache
'웹 > 프론트엔드' 카테고리의 다른 글
빌드 시 에러가 나는 경우, minify 옵션을 꺼보자. (0) | 2022.12.11 |
---|---|
[Typescript] 유니온 타입 사용 시 타입 증명하기 (0) | 2022.11.23 |
Exported variable has or is using name from external module but cannot be named 에러 (0) | 2022.10.04 |
[S3] AWS S3 fetch시 cors문제 해결 (0) | 2022.09.20 |
[Next.js] Next.js에서 Toast UI Editor 사용하기 (0) | 2022.09.20 |
댓글