refetchOnWindowFocus를 무작정 끄시나요?

정우시·2023년 9월 14일
5

우아한테크코스

목록 보기
11/14

서론

요즘카페 팀은 웹 애플리케이션 개발에서 데이터 상태 관리의 중요성을 인식하고, 이를 위해 리액트 쿼리와 같은 라이브러리를 적극 활용하고 있습니다. 그러나 이 데이터 관리 과정에서 useQuery를 사용할 때 의도치 않은 refetch 현상에 직면하게 되었습니다. 이 글에서는 이 문제를 다루며, 우리가 어떻게 이를 해결하려고 노력했는지에 대해 소개하겠습니다.

본론

문제 상황

'요즘카페' 서비스는 GET /cafes를 호출하면 매번 새로운 카페 목록을 응답해주고 있습니다. 따라서 해당 API는 멱등하지 않는 API라고 볼 수 있습니다. 저희는 GET /cafes API를 사용하는 메인 페이지의 화면 창을 나갔다 들어왔을 때 목록이 완전히 바뀌는 문제가 있었습니다.

refetchOnWindowFocus

물론 refetchOnWindowFocus를 false로 바꿔서 해결했을 수도 있을 것입니다. 하지만 그것이 근본적인 해결책일까요? 먼저, useQuery의 'refetchOnWindowFocus'옵션에 대해 알아보겠습니다.

'refetchOnWindowFocus'는 웹 애플리케이션에서 데이터를 관리하는 과정에서 사용되는 옵션입니다. 이 옵션은 기본적으로 활성화되어 있으며, 브라우저 창이 다시 활성화될 때마다(예: 사용자가 웹 페이지 탭을 전환하거나 다른 탭에서 돌아왔을 때) 데이터를 자동으로 다시 불러오는 동작을 수행하도록 설정됩니다.

그렇다면 왜 리액트 쿼리는 'refetchOnWindowFocus'를 기본적으로 활성화를 했을까요? 그것은 리액트 쿼리가 Stale-While-Revalidate (SWR)의 caching mechanism을 따르기 때문입니다.

Stale-While-Revalidate (SWR)

Stale-While-Revalidate이란 무엇인가요?

Stale-While-Revalidate은 웹 애플리케이션에서 데이터를 효율적으로 관리하기 위한 캐싱 전략 중 하나입니다.

이 전략은 데이터의 최신 버전을 서버에서 가져오는 동시에 캐시된(과거의) 데이터를 사용자에게 제공하는 방식을 기반으로 합니다. 이를 통해 사용자는 즉시 데이터를 볼 수 있으며, 동시에 최신 정보를 기다리지 않아도 됩니다.

Stale-While-Revalidate 작동 방식

1. HTTP 요청과 캐시

  • 사용자가 웹 페이지를 열면, 애플리케이션은 데이터를 가져와서 캐시에 저장합니다.
  • 이 데이터는 사용자에게 표시되고, 동시에 서버에서 최신 데이터를 요청합니다.

2. 캐시된 데이터 사용

  • 서버로부터 최신 데이터를 받을 때까지 기다리지 않고, 캐시된 데이터를 사용자에게 표시합니다.
  • 이로써 사용자는 빠르게 페이지를 로드하고 데이터를 볼 수 있습니다.

3. 최신 데이터 업데이트

  • 서버에서 최신 데이터를 가져온 후, 캐시의 데이터와 비교합니다.
  • 새로운 데이터가 캐시의 데이터와 다를 경우, 캐시를 업데이트합니다.

이렇게 SWR은 데이터를 캐싱하고, 캐시된 데이터가 낡아도 일시적으로 사용자에게 반환하며 동시에 백그라운드에서 최신 데이터를 가져오는 방식으로 최적의 성능을 제공합니다.

refetchOnWindowFocus와 Stale-While-Revalidate와의 관계

'refetchOnWindowFocus'를 활성화하면 브라우저 창이 다시 활성화될 때마다 데이터를 다시 불러오기 때문에 이는 'Stale-While-Revalidate' 캐싱 전략과 유사한 동작을 합니다. 사용자가 다른 탭으로 이동한 후 다시 해당 탭으로 돌아오면, 캐시된 데이터가 stale한 상태일 수 있습니다.

그럴 때 'refetchOnWindowFocus'를 활성화하면 브라우저 창의 포커스 이벤트에 의해 데이터를 리프레시 하려고 시도합니다. 이것은 사용자에게 최신 정보를 제공하려는 의도와 일치합니다.

따라서 'refetchOnWindowFocus'를 활성화하면 사용자가 다시 해당 탭을 활성화할 때마다 'Stale-While-Revalidate'와 유사한 방식으로 데이터를 업데이트하고 최신 정보를 유지할 수 있게 됩니다.

문제 해결

요즘카페 팀에서는 'Stale-While-Revalidate' 캐싱 전략을 고려하지 않고, 무작정 'refetchOnWindowFocus'를 끄는 것은 올바른 선택이 아니라고 판단했습니다. 이런 결정을 내리게 된 이유는 GET /cafes API 자체가 멱등하지 않는 비멱등(non-idempotent) API라는 점 때문입니다. 멱등하지 않은 API는 동일한 요청을 여러 번 보내면 다른 결과가 나올 수 있으므로, 무작정 refetch를 비활성화하는 것은 문제의 근본적인 원인을 해결하지 않습니다.

상태의 제어권이 서버가 아니라 클라이언트에 있다고 할 수 있기 때문에, 이 문제를 해결하기 위해 클라이언트 측에서 적절한 조치를 취하는 것이 중요합니다. 이를 위해 'staleTime'과 'cacheTime' 옵션을 사용하여 데이터 캐싱을 관리하고, 클라이언트에서 데이터의 유효성을 더욱 효과적으로 조절할 수 있습니다.

'staleTime' 옵션은 데이터가 "낡아도 좋다"라고 허용하는 시간을 나타내며, 'cacheTime'은 데이터를 캐시에 저장하는 시간을 나타냅니다. 이 두 옵션을 'Infinity'로 설정하면 데이터가 캐시에 영원히 남아 있고, 'refetchOnWindowFocus' 옵션을 활성화해도 브라우저 창이 활성화될 때마다 데이터를 불러오지 않습니다. 이렇게 하면 refetch의 무작위 발생을 방지하면서도 데이터를 캐시에 영구적으로 저장하여 사용자 경험을 개선할 수 있습니다.

따라서 요즘카페 팀은 'refetchOnWindowFocus: false' 대신 'staleTime: Infinity'와 'cacheTime: Infinity'를 설정하여 데이터 캐시를 영구화하고, 의도치 않은 refetch를 방지할 수 있었습니다. 또한 이러한 조치를 통해 클라이언트가 데이터 관리의 주도권을 가지며 서버와의 효율적인 통신을 유지할 수 있게 되었습니다.

결론

데이터 상태 관리와 캐싱 전략은 웹 애플리케이션의 성능과 사용자 경험을 결정하는 핵심적인 요소입니다. 'refetchOnWindowFocus'와 같은 옵션을 사용할 때는 데이터의 특성과 업데이트 빈도를 고려해야 합니다. 요즘카페 팀은 'Stale-While-Revalidate'와 같은 캐싱 전략을 활용하여 데이터 무효화 문제를 해결하였으며, 이를 통해 사용자에게 최신 정보를 제공하고 성능을 개선하였습니다.


참고 자료

profile
프론트엔드 공부하고 있는 정우시입니다.

0개의 댓글