캐시 데이터 활용

설명
Tags

캐시 이해

case1. network-only / cache-only

동일한 쿼리를 다음과 같이 구성하여 호출한다.
  • 메인 로직에서는 network-only로 호출
  • 서브 로직에서는 cache-only로 호출
 
가정
network-only 호출은 cache를 업데이트 시키므로, network-only 쿼리를 쏴서 기존과 달라진 데이터가 있어서 새로운 데이터로 갱신되었다면, 알아서 cache-only로 호출하던 쿼리 쪽도 다시 동작할 것이라고 예상하였음.
const A = () => { const [checkFirmwareUpdate, { data }] = useGetLatestFirmwareLazyQuery({ variables: { tabletImei: '1' }, fetchPolicy: 'network-only', }); useEffect(() => { const interval = setInterval(() => { checkFirmwareUpdate(); console.log('A'); }, 10 * 1000); return (): void => { clearInterval(interval); }; }, [checkFirmwareUpdate]); useEffect(() => { console.log('A data', data); }, [data]); return <></>; }; const B = () => { const [checkFirmwareUpdate, { data }] = useGetLatestFirmwareLazyQuery({ variables: { tabletImei: '1' }, fetchPolicy: 'cache-only', }); useEffect(() => { checkFirmwareUpdate(); console.log('B'); }, [checkFirmwareUpdate]); useEffect(() => { console.log('B data', data); }, [data]); return <></>; };
결과
network-only 쿼리를 호출하고 업데이트가 있는 새로운 데이터를 받았다 할 지라도, cache-only로 호출하고 있던 쿼리가 다시 호출되지 않는다.
따라서 cache-only를 사용하던 컴포넌트가 리렌더링 되지 않는다.
// 최초 호출 LOG A data undefined LOG B LOG B data undefined LOG A LOG A data {"latestFirmware": {"__typename": "FirmwareType", "file": "https://application.algocare.link/test", "fileSize": 10000, "id": "1", "majorVersion": 0, "minorVersion": 0, "patchVersion": 0}} LOG B data {"latestFirmware": {"__typename": "FirmwareType", "file": "https://application.algocare.link/test", "fileSize": 10000, "id": "1", "majorVersion": 0, "minorVersion": 0, "patchVersion": 0}} // network-only 쿼리 결과에 변화가 없기까지는, cache-only쪽 로직은 다시 돌지 않는다. LOG A LOG A data {"latestFirmware": {"__typename": "FirmwareType", "file": "https://application.algocare.link/test", "fileSize": 10000, "id": "1", "majorVersion": 0, "minorVersion": 0, "patchVersion": 0}} LOG A data {"latestFirmware": {"__typename": "FirmwareType", "file": "https://application.algocare.link/test", "fileSize": 10000, "id": "1", "majorVersion": 0, "minorVersion": 0, "patchVersion": 0}} LOG A LOG A data {"latestFirmware": {"__typename": "FirmwareType", "file": "https://application.algocare.link/test", "fileSize": 10000, "id": "1", "majorVersion": 0, "minorVersion": 0, "patchVersion": 0}} LOG A data {"latestFirmware": {"__typename": "FirmwareType", "file": "https://application.algocare.link/test", "fileSize": 10000, "id": "1", "majorVersion": 0, "minorVersion": 0, "patchVersion": 0}} LOG A LOG A data {"latestFirmware": {"__typename": "FirmwareType", "file": "https://application.algocare.link/test", "fileSize": 10000, "id": "1", "majorVersion": 0, "minorVersion": 0, "patchVersion": 0}} LOG A data {"latestFirmware": {"__typename": "FirmwareType", "file": "https://application.algocare.link/test", "fileSize": 10000, "id": "1", "majorVersion": 0, "minorVersion": 0, "patchVersion": 0}} // network-only 쿼리 결과에 변화가 생긴 경우에는, cache-only쪽의 data도 영향을 받는다. LOG A LOG A data {"latestFirmware": {"__typename": "FirmwareType", "file": "https://application.algocare.link/test", "fileSize": 10000, "id": "1", "majorVersion": 0, "minorVersion": 0, "patchVersion": 0}} LOG A data {"latestFirmware": {"__typename": "FirmwareType", "file": "https://application.algocare.link/Firmware/STG/V1.1.2_no_headers.bin", "fileSize": 25956, "id": "23", "majorVersion": 1, "minorVersion": 1, "patchVersion": 2}} LOG B data {"latestFirmware": {"__typename": "FirmwareType", "file": "https://application.algocare.link/Firmware/STG/V1.1.2_no_headers.bin", "fileSize": 25956, "id": "23", "majorVersion": 1, "minorVersion": 1, "patchVersion": 2}} // 이후 다시 network-only 결과에 변화가 없다면, cache-only쪽 로직은 다시 돌지 않는다. LOG A LOG A data {"latestFirmware": {"__typename": "FirmwareType", "file": "https://application.algocare.link/Firmware/STG/V1.1.2_no_headers.bin", "fileSize": 25956, "id": "23", "majorVersion": 1, "minorVersion": 1, "patchVersion": 2}} LOG A data {"latestFirmware": {"__typename": "FirmwareType", "file": "https://application.algocare.link/Firmware/STG/V1.1.2_no_headers.bin", "fileSize": 25956, "id": "23", "majorVersion": 1, "minorVersion": 1, "patchVersion": 2}} LOG A LOG A data {"latestFirmware": {"__typename": "FirmwareType", "file": "https://application.algocare.link/Firmware/STG/V1.1.2_no_headers.bin", "fileSize": 25956, "id": "23", "majorVersion": 1, "minorVersion": 1, "patchVersion": 2}} LOG A data {"latestFirmware": {"__typename": "FirmwareType", "file": "https://application.algocare.link/Firmware/STG/V1.1.2_no_headers.bin", "fileSize": 25956, "id": "23", "majorVersion": 1, "minorVersion": 1, "patchVersion": 2}}
 
💡
const { data } = use@@Query() cosnt [ @@Query, { data } ] = use@@LazyQuery() data 객체는 캐시가 업데이트가 될 시 영향을 받는다. 따라서 data 객체는 state로 간주된다.
notion image
 

case2. cache-only / writeQuery / readQuery

  • main 로직에선 cache-only로 쿼리를 호출한다.
  • 인터벌로 client.writeQuery를 통해 결과 데이터를 직접 쓴다.
 
가정
writeQuery로 인해 캐시가 업데이트 되어서, 쿼리의 data 오브젝트가 영향을 받아서 관련 로직이 다시 동작할 것으로 예상함.
const B = () => { const client = useApolloClient(); const [checkFirmwareUpdate, { data }] = useGetLatestFirmwareLazyQuery({ variables: { tabletImei: '1' }, fetchPolicy: 'cache-only', }); useEffect(() => { checkFirmwareUpdate(); console.log('B'); }, [checkFirmwareUpdate]); useEffect(() => { console.log('B data', data); }, [data]); useEffect(() => { let count = 0; const interval = setInterval(() => { console.log('B writeQuery'); client.writeQuery({ query: GetLatestFirmwareDocument, data: { latestFirmware: { __typename: 'FirmwareType', file: 'https://application.algocare.link/Firmware/STG/V1.1.2_no_headers.bin', fileSize: 25956, id: '23', majorVersion: 1, minorVersion: 1, patchVersion: 2 + count, }, }, }); count++; }, 5 * 1000); return (): void => { clearInterval(interval); }; }, [client]); return <></>; };
결과
writeQuery를 호출하면 실제 해당 쿼리에 대한 캐시 데이터는 업데이트 되지만, 쿼리의 data 오브젝트는 갱신되지 않는다. 따라서 data와 관련된 로직도 다시 동작하지 않는다.
캐시 데이터가 업데이트 되었는지 여부는 readQuery를 하면 알 수 있는데, 계속 변하는 것을 보면 writeQuery 시 캐시데이터 자체는 업데이트가 잘 반영되었다는 것을 알 수 있다.
// 초기 데이터 LOG B LOG B data undefined // writeQuery를 호출했고 캐시 데이터는 업데이트 하지만, 쿼리의 data 오브젝트는 업데이트 하지 않는다. LOG B writeQuery LOG cache read {"latestFirmware": {"__typename": "FirmwareType", "file": "https://AAAA.BBBB.bin", "fileSize": 12345, "id": "23", "majorVersion": 1, "minorVersion": 1, "patchVersion": 2}} LOG B writeQuery LOG cache read {"latestFirmware": {"__typename": "FirmwareType", "file": "https://AAAA.BBBB.bin", "fileSize": 12345, "id": "23", "majorVersion": 1, "minorVersion": 1, "patchVersion": 3}} LOG B writeQuery LOG cache read {"latestFirmware": {"__typename": "FirmwareType", "file": "https://AAAA.BBBB.bin", "fileSize": 12345, "id": "23", "majorVersion": 1, "minorVersion": 1, "patchVersion": 4}} LOG B writeQuery LOG cache read {"latestFirmware": {"__typename": "FirmwareType", "file": "https://AAAA.BBBB.bin", "fileSize": 12345, "id": "23", "majorVersion": 1, "minorVersion": 1, "patchVersion": 5}} LOG B writeQuery LOG cache read {"latestFirmware": {"__typename": "FirmwareType", "file": "https://AAAA.BBBB.bin", "fileSize": 12345, "id": "23", "majorVersion": 1, "minorVersion": 1, "patchVersion": 6}}
notion image
 

broadcast 원리