문제점
header의 설정값 (global한 값)을 바꾼 뒤 다른 페이지로 이동하면 바꾼 값이 적용되지 않는 현상이 발생했다
원인
header의 설정값은 apollo useQuery
를 이용해 불러오고 있었는데, refetch
로 변경한 뒤 다시 불러올 때는 예전 캐시 값을 읽어와서 값이 변경되지 않았다.
배경
header에서 사용하고 있던 api 쿼리문은 variable을 전달하지 않으면 가장 마지막에 읽었던 값을, variable을 주면 해당 값을 반환하는 api였다.
- () => 마지막에 읽었던 값
- (variable) => variable에 대응되는 값
이런 상황에서 사용자가 값을 변경하면 두 번째 방법으로 호출하고, 초기에 fetch할 때는 첫 번째 방법으로 호출하여 마지막에 읽었던 값이 반환되기를 기대했다. 그러나 실제로는 cache-first
정책으로 동작하고 있었기 때문에 다음과 같이 동작하고 있었다
myQuery() => data-1
[마지막 읽은 값]- 값 변경:
myQuery(3) => data-3
- 페이지 이동
myQuery() => data-3
가 나오기를 기대- 그러나 캐시에 저장된 데이터가 불러와져 실제 반환값은
data-1
- 그러나 캐시에 저장된 데이터가 불러와져 실제 반환값은
해결법
myQuery(variable)
을 수행한 뒤에 myQuery()
에 해당하는 캐시 값을 수행한 쿼리의 결과로 업데이트하였다. 코드로는 client.writeQuery()
를 사용하였다.
const client = useApolloClient();
const updateDefaultMyQueryCache = (dataToWrite: unknown) => {
client.writeQuery({
query: MY_QUERY,
data: dataToWrite,
});
};
const { loading, error, data, refetch } = useQuery<
DataType,
VariablesType
>(MY_QUERY, {
variables: { ... },
onCompleted: (responseData) => {
updateDefaultMyQueryCache(responseData);
},
});
장점
myQuery(variable)
수행 후 myQuery()
를 refetch하여 쿼리를 업데이트 하는 방법도 있으나, 이 경우에는 한번 네트워크 요청을 한 뒤에 네트워크 요청을 한번 더 하게 된다. 대신 이 경우에는 myQuery()
의 결과가 어떻게 바뀔 지 명확하고 정확도가 중요한 데이터도 아니어서 캐시를 업데이트 하면 비싼 네트워크 요청을 줄일 수 있다.
재미있는 점은 myQuery()
의 캐시 업데이트가 myQuery의 상위 집합을 요청하는 쿼리의 캐시에도 영향을 준다는 것이다. 그쪽 캐시도 수정해야 하는지 확인해 봤는데, 같은 데이터를 불러올 때 random access를 apollo가 잘 해줘서 그런지 알아서 업데이트된 값으로 반환해주고 있었다.
개선점
캐싱이 적용이 안 된 부분이 있다면 더 확대해 적용하고 싶다. (로딩이 눈에 보이는 페이지가 있어서 거기에 적용이 안 된줄 알았는데 의외로 거기는 되어 있었다) 특히 mutation 후에 refetch로 쿼리를 업데이트하는 부분이 몇 군데 있는데, 이 부분 중 몇군데는 캐시 업데이트로 바꿔도 될 지 고민해 봐야겠다. 그렇게 하면 네트워크 요청과 로딩 시간을 줄일 수 있을 것이다.
'Essay > 기술 회고' 카테고리의 다른 글
Jira의 REST API 적용 사례 - 현재 유저가 소유한 리소스 URI 명명법, expand parameter (0) | 2024.08.03 |
---|---|
FCM을 이용해서 알림 기능을 구현할 때 고려해야 하는 이슈 (0) | 2024.06.21 |
[Frontend] Troubleshooting 기록 - 회원가입 로직 (0) | 2022.01.03 |
[React] Apollo client useQuery 요청이 무한 반복됐던 이유 (0) | 2021.08.10 |