상태, 서버 딸이에요 : TanStack Query🧃

밍갱·2025년 3월 11일
0

1. 상태 관리🧑‍💼

00. React의 상태란?

React state 관련 게시글 ▶️ 이전 정리글 참고

React 컴포넌트는 로직을 처리하기 위해 저장하는 특정한 값을 state라고 한다. state 값이 변화했을 때, 컴포넌트는 리렌더링을 한다.

상태의 종류는 크게 3가지이다.

  • 전역 상태 : 프로젝트 전체에 영향을 끼치는 상태 (예시 - 로그인 여부, 테마)
  • 컴포넌트 간 상태 : 여러 컴포넌트에서 관리되는 상태 (예시 - 데이터)
  • 지역 상태 : 특정 컴포넌트 안에서만 관리되는 상태 (예시 - 카운트)

01. 상태 관리란?

여러 컴포넌트에서 같은 데이터(상태)가 필요할 때, 부모자식 관계가 아니라면 직접적인 데이터 전달은 불가능하다. 전달을 하기 위해선 부모 컴포넌트로 데이터를 보내고, 그 데이터를 필요한 컴포넌트로 전달하는 복잡한 과정(prop drilling)이 필요하다. 프로젝트의 규모가 커져 필요한 상태가 많아지고, 어플리케이션이 복잡해질수록 props를 추적하는 것은 더 어려워진다.
이런 문제점을 해결하기 위해, 개발자는 알맞은 상태관리 툴을 선택해 상태관리를 해야한다. 즉, 상태관리는 데이터(상태)를 추적하고, 여러 컴포넌트 간의 데이터 공유를 용이하게 한다. 또한, 프로그램이 어떻게 구동 될지 예측 가능하도록 하여 유지보수 측면에서 유리해지며, 코드의 재사용성 증가와 성능 최적화에도 도움이 된다.

요약하자면...

  • 상태 추적 ▶️ 여러 컴포넌트 간의 데이터 공유를 용이하도록 만듦
  • 프로그램이 어떻게 구동 될지 예측 가능 ▶️ 유지보수 측면에서 유리
  • 코드의 재사용성 증가와 성능 최적화에도 도움

02. 클라이언트 상태란?

웹 애플리케이션의 프론트엔드 에서 관리되는 데이터로, 사용자의 브라우저나 애플리케이션 내에서 유지된다. 각 클라이언트별로 독립적인 상태를 가지며, UI 상태, 사용자 입력값, 임시 데이터 등을 포함한다. 클라이언트 상태는 서버 요청 없이도 즉시 반영되며, UX 개선을 위해 미리 가져온 데이터를 활용할 수 있다. 하지만 다른 클라이언트와 공유되지 않으며, 페이지를 새로고침하면 사라질 수 있다는 점이 특징이다.

03. 서버 상태란?

웹 애플리케이션의 백엔드 에 저장되는 데이터로, 데이터베이스, 파일 시스템, 캐시 등에 보관된다. 서버 상태는 모든 클라이언트가 동일하게 공유하는 데이터이며, 주로 사용자 정보, 게시물, 상품 정보 등 영속적인 데이터를 포함한다. 클라이언트에서 변경이 발생하면 비동기 요청을 통해 서버와 데이터를 동기화해야 하며, 응답을 기다려야 한다. 또한 보안과 데이터 무결성을 유지해야 하므로 중앙 집중식 데이터 소스에서 관리된다.

*중앙 집중식 데이터 소스란 ? : 다양한 소스의 데이터를 한 곳에 모아놓은 저장소

04. 클라이언트 상태 vs 서버 상태

특징클라이언트 상태서버 상태
관리 주체프론트엔드
(사용자 브라우저, 애플리케이션)
백엔드
(서버, 데이터베이스)
저장 위치브라우저 메모리, 상태 관리 라이브러리데이터베이스, 파일 시스템, 캐시
클라이언트 간 데이터 공유X (각 클라이언트별 개별 상태)O (동일한 데이터 제공)
주요 데이터UI 상태, 사용자 입력값 등 일시적 데이터게시물, 상품 정보 등 영속적 데이터
상태 변경 시즉시 반영, 미리 가져온 데이터 활용비동기 요청▶️ 서버데이터 요청/수정

05. 상태 관리 라이브러리

  • useState
    state를 관리하여 UI를 업데이트하는 React 내장 hook이다.

useState 관련 게시글 ▶️ 이전 정리글 참고

  • Context API
    Context API는 불필요한 prop-drilling을 하지 않아도 타겟 컴포넌트에게 필요한 데이터/상태를 쉽게 공유할 수 있게 해준다. 하지만 불필요한 리렌더링이 발생한다는 한계점이 있다.

Context API 관련 게시글 ▶️ 이전 정리글 참고

  • Redux
    Redux는 전역 상태관리를 위한 도구(라이브러리)로, 어플리케이션 전체에 대한 중앙 저장소 역할을 한다. store를 활용하여 중앙 상태 관리 방식으로 동작한다. action을 통해 store 내부의 상태 변경에 대한 이벤트를 정의하고, reducer로 액션에 대한 이벤트를 처리하여 전역 상태를 업데이트한다.

  • TanStack Query (구 React Query)
    서버상태를 관리하는 라이브러리로, 서버와 클라이언트 간 비동기 작업을 쉽게 다룰 수 있게 도와준다.

2. TanStack Query🏝️

01. TanStack Query란?

TanStack Query는 서버로부터 데이터를 가져오고(fetching), 캐싱(caching)하고, 캐시를 제어하는 등 서버 상태를 쉽고 효율적으로 관리할 수 있는 라이브러리이다. 즉, 웹 애플리케이션에서 서버 상태의 페칭, 캐싱, 동기화, 업데이트 작업을 간편하게 수행할 수 있도록 도와준다.
TanStack Query를 사용하면 데이터 관련 코드의 양을 줄이고, 항상 최신 데이터를 유지할 수 있다. 네트워크가 재연결되거나 요청이 실패할 경우 자동으로 데이터를 갱신하여 애플리케이션의 안정성을 높인다. 또한, 낙관적 업데이트(Optimistic Updates), 무한 스크롤(Infinite Scroll), 페이지네이션(Pagination) 등의 기능을 손쉽게 구현할 수 있으며, 이를 통해 메모리 사용과 성능을 최적화할 수 있다.

02. TanStack Query의 주요 개념

  • Queries : 쿼리는 비동기 데이터 소스에 대한 선언적 의존성을 가지며, 고유한 키를 통해 식별되며, 서버에서 데이터를 가져올 때 활용된다. new QueryClient로 QueryClient를 생성하고 useQueryClient로 QueryClient를 호출한다. 그리고, useQuery로 데이터를 캐싱한다.

  • Mutations : Mutation은 데이터를 생성(Create), 수정(Update), 삭제(Delete)하거나 서버에 부수적인 영향을 주는 작업에 사용된다. useMutation을 사용한다.

  • Query Invalidation : 쿼리의 stale(오래됨) 상태나 사용자 행동으로 인해 데이터가 변경되는 경우 새로운 데이터를 가져와야한다. 이럴 때, QueryClient의 invalidateQueries를 사용하여 특정 쿼리의 상태를 변경하고 데이터를 다시 가져올 수 있다.

03. QueryClient : 쿼리 생성 및 호출

  • new QueryClient : 쿼리 생성
// 쿼리 생성
const queryClient = new QueryClient()

export default function App() {
  return (
  	//Provider로 래핑
    <QueryClientProvider client={queryClient}>
      <TodoList />
    </QueryClientProvider>
  )
}
  • useQueryClient : 쿼리 인스턴스 연결
export default function TodoList(){
	//쿼리 인스턴스 연결
    const queryClient = useQueryClient()
    
    ...생략
}
  • invalidateQueries() : 쿼리 무효화
queryClient.invalidateQueries() // 모든 쿼리 무효화
queryClient.invalidateQueries(["queryKey"]) // 특정 쿼리 무효화

04. useQuery : 데이터 fetch

  • useQuery : 컴포넌트에서 데이터를 가져올 때 사용
//jsx
const { 반환값 구조 분해 } = useQuery(옵션)

//tsx
const { 반환값 구조 분해 } = useQuery<데이터타입>(옵션)
  • useQuery의 옵션

    • queryKey : 필수 ! 해당 쿼리를 식별하는 고유한 키(TanStack Query는 쿼리 키에 따라 쿼리 캐싱을 관리) 배열 형태로 설정한다.
    • queryFn : 필수 ! 데이터를 가져오는 비동기 함수
    • select : 가져온 데이터를 변형(선택)하는 로직
      기타 옵션들은 TanStack Query useQuery 문서 확인하기
  • useQuery의 반환값

    • data : 성공적으로 가져온 데이터
    • isPending : 쿼리가 실행 중이며, 아직 데이터가 로딩되지 않은 상태 (첫 데이터 fetch 시 사용)
      (isLoading과 비슷하지만 isLoading은 v5 이후부터 잘 사용하지 않음)
    • isFetching : 쿼리 함수가 실행 중인 상태 (첫 fetch + refetch 모두 포함)
    • isError : 쿼리 함수에서의 오류 발생 여부
    • error : 오류가 발생했을 때의 오류 객체, 오류가 없으면 null
      기타 반환값들은 TanStack Query useQuery 문서 확인하기
  • 예시

//sample in jsx

const { data, isPending, isError } = useQuery({
	queryKey: ["todos"],
    queryFn: fetchTodoData,
    select: data => data.map(user => user.name)
})

05. useMutation : 데이터 변경 작업

  • useMutation : 데이터 변경 작업(생성, 수정, 삭제 등)을 처리
const 반환 = useMutation(옵션)
  • useMutation의 옵션

    • mutationFn : 실행할 비동기 변이 함수
    • onSuccess : 변이가 성공할 때 호출되는 함수
    • onMutate : 변이 함수가 실행되기 전에 호출되는 함수
    • onSettled : 변이가 성공하거나 실패해도 항상 호출되는 함수
    • onError : 변이 중 오류가 발생할 때 호출되는 함수
      기타 옵션들은 TanStack Query useMutation 문서 확인하기
  • useMutation의 반환값

    • mutate : 변이 실행 함수
    • data : 성공적으로 가져온 데이터
    • isPending : 변이가 실행 중인지 여부 (이전 버전에서는 isLoading)
      기타 반환값들은 TanStack Query useMutation 문서 확인하기
  • 예시

//sample in jsx

const { mutate : addMutation } = useMutation({
    mutationFn: addTodo,
    onSuccess: () => {
      alert("새로운 할일이 추가되었습니다.");
      //쿼리 무효화
      queryClient.invalidateQueries(["todos"]);
    }
  });

TanStack Query 공식 문서
상태관리 참고 사이트 1
상태관리 참고 사이트 2
서버상태/클라이언트상태 참고 사이트
TanStack Query 참고 사이트

profile
미술 전공에서 프론트엔드 개발까지

0개의 댓글