티스토리 뷰

StaleTime, CacheTime을 보게 된 이유

운영 서버 백엔드 인스턴스 cpu 100% 초과로 다운

원인: 특정 api의 호출이 급격이 몰리는 시간대였는데, 하필 그 api에 정돈되지 않은 수많은 쿼리가 있음

백엔드에서 해당 api에서 호출되는 쿼리를 정리해서 cpu사용률을 줄임

프런트엔드의 문제는 없었을까?

 

프런트엔드의 문제점 : 불필요한 네트워크 요청 과다

1. useEffect의 의존성배열에 Next/Router에서 리턴해주는 pathname을 넣어놓고 내부에서는 useQuery가 리턴하는 refetch 함수를 실행시킴 (동일한 Link컴포넌트를 클릭해도 pathname의 변경으로 인식하는 듯.. refetch가 계속해서 발생됨)

2. 해당 페이지의 실시간성이 중요하지 않은데도 해당 쿼리가 바로 stale 한 상태로 변경되어(Default) 페이지가 Mount 될 때마다 매번 네트워크 요청

 

해결

1. useEffect refetch 제거, 애초에 강제적으로 refetch를 호출해야 한다면 뭔가 useQuery를 잘못사용하고 있는 중..

2. page가 mount될때마다 새로운 request를 보낼 필요가 없음. 혹여라도 다시 mount 된다 해도 1분에 한 번씩만 새로운 요청을 보내면 충분하다는 판단. 그전에 수시로 mount 되면 react-query의 캐시 된 데이터를 보여주기로 결정 => staletime:60000

 

헷갈렸던 부분은 cacheTime과 staleTime이다

 

cacheTime이나 staleTime을 지정해주지 않아도 리액트 쿼리로 한번 불러온 데이터는

두번째로 다시 마운트 시켰을 때 데이터 로딩 없이 바로 보이는 것을 확인할 수 있다.

하지만 네트워크 탭을 보면

여전히 pending상태에 있다..

네트워크가 pending상태라면 useQuery가 isLoading을 true로 리턴해서 나의 Loading컴포넌트가 떠야 하지만

리액트쿼리는 똑똑하게 일단 한번 요청되면 해당 '쿼리키'를 기준으로 데이터를 캐싱한다.

그리고 네트워크가 완료되기 전에는 캐시를 불러와서 이전의 데이터를 불러오고 200을 받으면 최신데이터로 업데이트를 한다.

Default로 이 캐시를 유지하는 시간이 5분이다. 5분이 지나면 다시 Loading컴포넌트가 보이겠지?

 

그렇다면 staleTime이란 무엇이냐.. 말 그대로 해당 키로 호출된 쿼리가 stale 한 상태로 변경될때까지의 시간이다.

staleTime을 1분으로 설정해두면 stale한 상태로 변경되기까지 1분이 걸린다. 즉 fresh 한 상태가 1분간 지속되므로

useQuery는 이 데이터가 어차피 fresh 하니까 네트워크 요청을 하지 않고 그냥 캐싱된 데이터만 보여줄 뿐이다.

1분이 지나면 쿼리의 상태가 stale 하게 변하게 되고 그 상태에서 바로 뒤에 mount 될 때에는 캐시도 보여주지만(아직 5분은 안됨)

실제로 네트워크 요청을 보내고 fresh 하게 만든다. 이 상태가 또 1분간 지속된다.

 

이런 식으로 프런트엔드에서도 캐시를 활용함으로써 불필요한 네트워크를 줄임으로써 서버비용 개선에 기여할 수 있다고 생각한다.

물론 캐시는 아주 섬세하게 다루지 않으면 고객에게 불편함을 느끼게 할 수 있으므로 지속적으로 개선하려는 노력이 필요하다.

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2025/04   »
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
글 보관함