client state vs server state

남이섬·2025년 3월 28일

영상에서 고민하고 있는 redux store 코드 예시

  • api 통신 관련 코드가 모두 Store에 있는게 맞나 ?
  • 반복되는 isFetching, isError 등 api 관련 상태
  • 반복되는 비슷한 구조의 api 통신 코드

위와 같은 것들을 모두 관리하는게 맞는 건가 ?

프론트에서 이값들이 저장되어있는 state들은 일종의 캐시

ex
만약 주문을 한다 -> 주문을 생성 -> 주문 데이터는 client 에서 관리해야하는 데이터가 아닌 서버에서 DB에 저장되어 있는 값, 서버에 관리하는 값

서버에서 관리하는 값을 가져오기 위해서는 비동기 api 가 필요하다
즉, api 패칭을 해서 가져오든, 업데이트를 할때도 api가 필요하다

다른사람과 공유되는 데이터, 내가 모르는 사이에 변경
(open order, 코인 주문 상태, 미체결 상태)

Client State vs Server State

키포인트는 데이터의 Ownerchip이 있는 곳

Client State

  • client에서 소유하며 온전히 제어가능함
  • 초기값 설정이나 조작에 제약사항 없음
  • 다른 사람들과 공유되지 않으며 Client 내에서 UI/UX 흐림이나 사용자 인터렉션에 따라 변할 수 있음
  • 항상 Client 내에서 최신 상태로 관리됨

Server State

  • Client에서 제어하거나 소유되지 않은 원격의 공간에서 관리되고 유지됨
  • Fetching/Updating에 qlehdrl API가 필요함
  • 다른 사람들과 공유되는 것으로 사용자가 모르는 사이에 변경 될 수 있음
  • 신경 쓰지 않는다면 잠재적으로 "out of date"가 될 가능성을 지님

React Query

Fetch, catch and update data in your React and React Native applications all without touching any "global state"

overview

React Query is often described as the missing data-fetching library for React, but in more technical terms, it makes fetching, caching, sychronizing and updating server state in your React applications a breeze

react querysms zero-config로 즉시 사용가능, 원하면 언제든지 config도 커스텀 가능 ?

import {
  QueryClient,
  QueryClientProvider,
  useQuery,
} from '@tanstack/react-query'

const queryClient = new QueryClient()

export default function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Example />
    </QueryClientProvider>
  )
}

function Example() {
  const { isPending, error, data } = useQuery({
    queryKey: ['repoData'],
    queryFn: () =>
      fetch('https://api.github.com/repos/TanStack/query').then((res) =>
        res.json(),
      ),
  })

  if (isPending) return 'Loading...'

  if (error) return 'An error has occurred: ' + error.message

  return (
    <div>
      <h1>{data.name}</h1>
      <p>{data.description}</p>
      <strong>👀 {data.subscribers_count}</strong>{' '}
      <strong>✨ {data.stargazers_count}</strong>{' '}
      <strong>🍴 {data.forks_count}</strong>
    </div>
  )
}

queryClient를 provider로 넣어주고 시작을 한다

  • Queries
  • Mutations
  • Query Invalidation

Queries

보통 get으로 받아올 대부분의 api에 사용할 아이, 데이터 Fetching 용이다

Query Key

key, value 맵핑구조 생각하면 된다

React Query는 Query key에 따라 query caching을 관리한다

string 형태

// a list fo todos
useQuery('todos', ...) // queryKey === ['todos']

// Something else, whatever
useQuery('somethingSpecial', ...) // queryKey === ['somethingSpecial']

array 형태

// an individual todo
useQuery(['todo', 5], ...)
//queryKey === ['todo', 5]

// an individual todo in a "preview" format
useQuery(['todo', 5, { preview: true }], ...)
// queryKey === ['todo', 5, { preview: true }]

// alist of todos that are "done"
useQuery(['todos', { tupe: 'done' }], ...)
//queryKey === ['todos', { type: 'done' }]

Query Function

DAta Fetching 할 때 promise 함수를 만든다

  • promise를 반환하는 함수 -> 데이터 resolve 하거나 error를 throw

  • use Query 반환값

useQuery Option

config 커스텀 ?

queries 파일 분리 추천

query가 여러 개일 땐 ?

Mutation

데이터 updating 시 사용하는 아이
즉, 데이터를 생성, 수정, 삭제하는 용 (create, update, delete)

useMutation

useMutation Option

optimistic update 란 ?
낙관적 업데이트는 한 마디로, 데이터를 변경하려 할 때, 응답을 기다리기 전 미리 UI를 업데이트 시키는 것이다.

Query Invalidation

Caching 하고 Synchronization은 ?

위의 컨셉을 메모리 캐시에 적용 해보자

Query 상태흐름

화면에 있다가 사라지는 query

화면에 있다가 없다가 좀 더 복잡한 query

zero-config에서도 이런 역할을 한다

알아서 하는 것들이 있어서 좋지만 주의도 해야합니다

전역상태처럼 관리되는 데이터들

어떻게 Server State들을 전역상태처럼 관리할까 ?

정답은 Context api에 있다

QueryClient 내부적으로 Context를 사용하고 있다

Provider가 필요한 이유가 여기에 있다

React Qruey etc

  • useeInfiniteQuery
  • Prefetching
  • TypeScript 지원
  • GraphQL도 대응
  • SSR & Next.js에서도 사용가능
  • devtools
  • etc.

react qeury 도입 이후

  • 서버상태 관리 용이 (redux, MobX 보다), 직관적인 api 호출
  • api 처리에 관한 각종 인터페이스 및 옵션제공
  • Client Store가 FE에서 정말로 필요한 전역상태만 남아 Sotre 답게 사용됨 (Boilerplate 코드 매우 감소)
  • devtool 제공으로 원활한 디버깅
  • Cache 전략 필요할 때 아주 좋음

보일러플레이트란?
컴퓨터 프로그래밍에서 보일러플레이트 또는 보일러플레이트 코드라고 부르는 것은 최소한의 변경으로 여러곳에서 재사용되며, 반복적으로 비슷한 형태를 띄는 코드를 말한다.

보일러플레이트 코드 제거하기
매번 프로그래밍을 할 때마다 보일러플레이트 코드를 작성하는 것은 비효율적이고 귀찮다. 리팩토링을 하게 되면 보일러플레이트 코드도 같이 수정해야하는 경우도 많다

고민 필요

  • Component가 상대적으로 비대해지는 문제 (Component 설계/분리에 대한 고민 필요)
  • 좀 더 난이도가 높아진 프로젝트 설계 (Component 유착 최소화 및 사용처 파악 필요)
  • React Query의 장점을 더 잘 활용할 방법 (단순히 API통신 이상의 가능성)

추천

  • 수많은 전역상태가 api 통신과 엮여있어 비대해진 Store를 고민하는 분
  • api 통신 관련 코드를 보다 간단히 구현하고 싶은 분
  • FE에서 데이터 Caching 전략에 대해 고민하는 분

SWR vs React-Query

profile
즐겁게 살자

0개의 댓글