일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 해시를 사용한 집합과 맵
- 회고
- 티스토리챌린지
- Next.js
- 자료 구조
- 구현
- react-three/fiber
- 오블완
- 프론트엔드
- 수학
- 기본 문법
- 코딩일기
- js
- poiemaweb
- styled-components
- REACT
- 자바스크립트
- three.js
- JavaScript
- 토이 프로젝트
- 개발 회고
- State
- 백준
- 엔트리포인트
- 시뮬레이션
- 브루트포스
- 세그먼트 트리
- 자바
- 모던 자바스크립트 튜토리얼
- HTML5
- Today
- Total
코딩하는 고릴라
[FE] 데코레이터로 API 캐싱 로직 분리하기 본문
기존에 Map 객체를 활용해 API 응답 데이터 캐싱 로직을 구현했었습니다.
const cacheData = API_CACCHE_DATA.get('http://localhost:8080/api/team');
if (!cacheData || cacheData.exp < new Date().getTime()){
axios.get('http://localhost:8080/api/team')
.then((res) => {
// 캐시 데이터 설정 {data, exp}
API_CACHE_DATA.set('http://localhost:8080/api/team', {
data: res.data,
exp: new Date().getTime + 1000 * 60 * 10,
})
// 응답 데이터 활용
console.log(res.data);
}.catch((err) => console.log(err));
} else {
// 캐시 데이터 활용
console.log(cacheData.data);
}
해당 로직을 처음 구현했을 당시에는 썩 괜찮은 코드라고 생각했었습니다.
하지만 위 코드는 api 호출에 대한 응답값의 캐싱이 필요한 부분이 여러 군데라면 위 코드 전체를 복사해 api 호출 함수만 변경시켜 사용해야 합니다. 이는 캐싱 관련 로직에 변경이 발생했을 때, 가져다 쓴 모든 곳에서 로직을 변경해줘야 하는 불편함을 초래할 수 있습니다.

- 전체 캐싱 로직 변경 수요가 발생하면, 로직1, 로직2, 로직3 내의 캐싱 로직을 모두 일일이 수정해줘야 한다.
자바스크립트에 대해 계속해서 학습한 결과, 데코레이터를 적용시켜 로직의 분리와 보다 범용성 있는 형태로 리팩토링 할 수 있음을 알게 되었습니다.
// 데이터를 불러 올 fetch 함수를 인수로 받는 래퍼 함수
function cacheWrapper(func) {
const cacheMap = new Map(); // 캐시 데이터를 저장할 map
return async function (url) { // 래퍼 함수를 호출했을 때 반환할 중첩 함수
let cacheData = cacheMap.get(url); // 캐시 데이터
if (cacheData && cacheData.exp > new Date().getTime()) { // 캐시 데이터가 존재하며, 만료기간이 지나지 않았다면 캐시 데이터 반환
return cacheData;
}
// 캐시에 데이터가 없거나 만료기간이 지났다면 인수로 받은 fetch함수인 func를 호출, 반환값을 캐시에 저장 후 반환
let res = await func(url);
cacheMap.set(url, { data: res.data, exp: new Date().getTime() + 1000 * 60 * 10 });
return res.data;
}
}
////////
// 외부에서 위 래퍼 함수를 활용해 사용하는 방식
// 1. cacheWrapper 함수에 인수로 fetch 함수를 넣어 전달하면, cacheWrapper의 렉시컬 환경이 생성되고 내부의 중첩 함수가 반환된다.
let cachedFetch = cacheWrapper(fetchFunction);
let result = cachedFatch('http://localhost:8080/api/team'); // cacheWrapper 함수 내 중첩함수에 인수로 url을 전달해 함수를 호출한다.
// 래퍼 함수 내부의 로직에 따라, 캐시 데이터를 체크한 후 알맞은 값을 반환시킨다.
// 다른 함수에 대해 위 캐싱 로직 활용의 필요성이 있다면, 래퍼 함수에 인수로 전달할 함수만 변경하여 호출해주면 된다.
let cachedFetch2 = cacheWrapper(fetchFunction2);
let result2 = cachedFetch('other_url');
캐싱을 활용할 컴포넌트에서 let cachedFetch = cacheWrapper(fetchFunction)를 한 번 호출하면, 캐싱을 위한 Map 객체를 활용할 수 있게 된다. 그리고 그 결과로 url을 인수로 받아 api 요청을 진행하는 내부 중첩 함수를 반환받는다.
그 후 cachedFetch(url)을 호출하면, 해당 url에 대한 캐시 체크 로직을 거친 후 캐시값이나 api 요청 결괏값을 반환해 준다.
이는 여러 컴포넌트에서 서로 다른 함수에 대한 캐시 작업이 필요할 때, cachedWrapper(func)에서 인수로 전달해 줄 함수들만 달리하여 호출하면 손쉽게 캐싱 로직을 활용할 수 있다. 이를 통해 api 호출 결과 데이터를 불러오는 본 함수의 로직과 캐싱 로직을 분리할 수 있으며, 캐싱 로직 수정 시 위 래퍼함수를 가져다 쓴 모든 곳에서 수정사항이 반영되는 범용성도 확보할 수 있게 된다.
자바스크립트에 대해 학습하면 할수록, 기존 프로젝트에서의 개선점이 점점 눈에 보이는 것 같다.
'Project > Pennypal' 카테고리의 다른 글
[FE] 스타일이 적용된 CSS 가상 요소 ::after가 GPU 사용률에 미치는 영향 - 원인 파악중,, (0) | 2024.04.08 |
---|---|
[FE] FSD 아키텍처를 활용한 디렉토리 구조 구성 (0) | 2024.04.05 |
[FE] API 캐싱 (0) | 2024.04.04 |