React-Query 개념과 사용방법에 대해서 알아보자 (스테픈 2km완료)

in sct-kr •  3 months ago 

image.png

React-Query 개념과 사용방법에 대해서 알아보자

목차

  1. 상태관리란 무엇일까?
  2. 리액트 쿼리를 왜 사용하는가?
  • 왜 이름이 react-query일까?
  • React-Query란?
  1. 대표적인 기능들
  2. 데이터 캐싱
  3. Query & Mutation
  4. 리액트 쿼리를 사용하지 않던 예제코드
  5. 리액트 쿼리를 사용한 코드
  6. 마치며
  1. 상태관리란?
  • 클라이언트의 상태관리란
    사용자의 인터페이스와 관련된 데이터를 말한다. 이는 애플리케이션 내부에서 직접 생성되고, 주로 사용자 상호작용에 의해 변경됩니다. 클라이언트 상태의 예를 들면 이런것들이 있겠다.

    UI 상태 (모달 열림/닫힘, 탭 선택 상태, 테마 변경상태 등등 )

    폼 입력 값
    임시 데이터 (ex. 사용자 입력 폼에 입력 중인 데이터 등등)

  • 서버의 상태관리
    서버 상태는 서버에서 가져오거나 서버에 저장해야 하는 데이터이다.
    이는 외부 데이터 소스와의 통신을 통해 얻어진 데이터를 포함하며, 일반적으로 비동기 작업을 통해 관리된다. 서버 상태의 예시로는 아래 사진과 같다.

    서버에서 가져온 데이터 목록 (ex. 블로그글, 상품 목록 등.)
    서버로부터 받아온 인증 정보 (ex. 토큰정보 등등.)

  • 서버와 클라이언트 상태를 왜 분리시켜서 생각할까?
    내가 만든 페이지를 예로 들어보자.

    위 코드는 내 블로그를 보여주는 화면의 코드이다.
    useEffect로 인해 처음 화면이 렌더링될때 fetch를 사용해 외부 api 데이터를 가져와서 mysteemdata에 저장한다.
    이렇게 저장한 데이터는

    또다른 컴포넌트에서 사용하기때문에
    스토어에 필요한 값을 저장하고 페이지를 이동해서
    이동한 페이지에서 데이터를 보여주는 로직으로 구성이 되어있다.
  • 만약 서버측의 api로직이 변경되었다고 가정해보자
    이경우 나는 최소 2개의 컴포넌트의 코드만 수정하면 된다.

    만약 컴포넌트가 이렇게 중첩적으로 내려가면서 값이 사용된다고 생각해보자
    4개가 아니라 100개의 컴포넌트를 타고 내려가면서 사용된다고 가정하자면

나는 코드를 총 100번을 수정해야한다.
서버의 상태는 수시로 변경될 수 있기 때문에 단순히 100번만 수정하면 끝이 아니다.

하지만 서버의 상태와 클라이언트의 상태를 분리시켜서 관리했다면
서버의 상태가 변경되었을때 한번의 수정만으로도 해결이 가능해진다.
이렇게 명확하게 책임을 분리하며 관리를 했을때

코드 구조의 일관성을 통해 유지보수가 매우 용이해진다.

2.리액트 쿼리를 왜 사용할까?

내가 사용해보고 느낀점을 토대로 작성하자면
리엑트 쿼리를 사용하는 이유를 총 3가지 항목으로 정리할 수 있겠다.

  1. 코드 가독성, 유지보수성 향상
    데이터 관리: 리액트 쿼리를 사용하면 api 데이터 관리 로직을 컴포넌트 밖으로 분리하여 관리한다.
    이로 인해 컴포넌트의 코드는 주로 UI에 집중하게 되어 가독성이 향상된다.

    (쿼리 관련 로직만 따로 폴더로 관리하는 사진)

각종 상태 처리의 간소화: 데이터 페칭, 캐싱, 리페칭 등의 복잡한 상태 처리가 리액트 쿼리 내부에서 자동으로 이뤄지므로, 컴포넌트의 코드가 간결해진다.

서버 상태와 클라이언트 상태의 분리: 서버 상태를 리액트 쿼리로 관리하면 클라이언트 상태와 서버 상태가 명확하게 분리되어 코드의 유지보수성을 높여준다.

  1. 중복 코드 제거
    재사용 가능한 로직: 외부 api 데이터를 가져오는 코드를 여러 컴포넌트에서 작성할 필요가 없다. 리액트 쿼리 훅을 사용하여 중복 코드를 최소화할 수 있다.

  2. 성능 최적화
    캐싱: 리액트 쿼리는 데이터를 자동으로 캐싱하여 성능을 최적화한다.
    캐싱된 데이터를 활용하면 서버에 반복적인 요청을 보내지 않고도 빠르게 데이터를 가져올 수 있다.
    리페칭: 데이터가 변경되면 자동으로 리페칭되어 최신 데이터를 유지할 수 있다.

이러한 3가지 이유를 토대로 서버와 클라이언트간의 상태를 분리시켜 관리해야하고 리엑트 쿼리를 사용하면 손쉽게 서버 상태관리가 가능하기 때문에
리엑트 쿼리를 사용하는것이라고 정리할 수 있겠다.

왜 이름이 react-query일까?

쿼리는 사전적으로 질문, 질의하다 등으로 볼 수 있다.

컴퓨터 언어에서의 쿼리는 데이터베이스 및 API 요청과 같은 데이터 검색 작업을 나타낸다.
리엑트 쿼리는 클라이언트와 서버 간의 데이터 통신, 특히 데이터를 가져오는(read) 작업을 관리하는 데 중점을 두고 있고
이러한 데이터 가져오기 작업이 일반적으로 "쿼리"라고 불리기 때문에 기능과 용도를 통해 React Query라는 이름이 붙었을거라고 추론할 수 있다.

서버 상태관리를 위한 라이브러리는 어떤게 더 있을까?
SWR (Stale-While-Revalidate),Apollo Client,RTK Query (Redux Toolkit Query)
,Relay 등등 다양한 라이브러리가 존재한다.
각 라이브러리의 특징과 리엑트 쿼리와의 차이점에 대해서는 글의 밑에서 추가로 다루기로 하고

현업에서 많이 사용하는 리엑트 쿼리에 대해서 알아도록 하자.

일단 내가 작성중인 리엑트 쿼리는 v5버전으로 공부를 했기 때문에

v5버전을 기준을 작성한다.

1.쿼리 키
리엑트 쿼리를 사용하기 위해서는
쿼리 키의 특징 및 역할에 대해 알아두는것이 좋다.
리엑트 쿼리에서 쿼리 키의 역할이 정말 중요하다.

쿼리키의 큰 특징으로는 4가지 정도의 기능이 있다.

1.캐싱 및 데이터 동기화:
쿼리 키는 React Query가 데이터를 캐시하고, 동일한 데이터를 여러 컴포넌트에서 재사용할 수 있도록 한다.
동일한 쿼리 키를 사용하는 쿼리들은 동일한 데이터를 공유하며, 이를 통해 네트워크 요청을 최소화하고 성능을 최적화한다.

코드로 설명을 하자면

붉은 줄을 그어 표시해둔 부분이 쿼리키이다.
배열로 blogdata라고 표시해둔 상태인데 해당 쿼리키에 blogfetch의 결과값이
캐싱된다고 생각하면 된다.

이를 다른 컴포넌트에서 동일한 키값으로 불러오게되면
캐싱된 데이터를 제공하게된다.

2.자동 리페칭(Refetching):
쿼리 키를 사용하여 데이터를 자동으로 다시 가져올 수 있다.
예를 들어, 데이터가 변경되거나, 특정 이벤트가 발생할 때 쿼리 키를 기준으로 자동으로 데이터를 다시 가져오도록 설정할 수 있다.


이렇게 쿼리 키에 변수를 등록해서 사용하는경우
해당 변수의 값이 변경되면 자동으로 리페칭을 하게된다.

3.데이터 무효화(Invalidation):
특정 쿼리 키를 기준으로 데이터를 무효화할 수 있다.
데이터를 무효화하면, 다음 번 쿼리 시 새로운 데이터를 가져오게 된다.
이는 데이터가 변경되었을 때 최신 상태를 유지하는 데 유용하다.

invalidateQueries 기능을 사용해 기존의 쿼리를 무효화할 수있다.

4.의존성 관리:
여러 쿼리가 동일한 데이터를 참조할 때, 쿼리 키를 사용하여 의존성을 관리할 수 있다.
이를 통해 데이터의 일관성을 유지할 수 있다.


이렇게 쿼리키에 사용하는 변수가 쿼리함수에 사용되는 형태로 의존성 관리가 가능하지만
이런경우 옵션의
enabled 옵션을 사용해 해당 변수의 값이 true인 경우에만
해당 쿼리가 동작하도록 사용하는게 효율적이다.

리엑트 쿼리에서 쿼리키의 특징을 정리해보면
키값은 유니크해야하고
키로 사용한 배열의 값에 변동사항이 있는경우
리페칭이 발생하게된다.
이러한 특징을 활용해 키값에 회원 아이디나 회원정보등을 변수로 활용해

이런 형태로도 쿼리를 사용할 수 도 있다.
유저의 데이터를 받아와서 데이터 페칭시 사용하는 방식으로
동적으로도 가능하다.
사용자가 다른아이디로 로그인을 한 경우
쿼리 키의 값에 다른 아이디가 들어오기 때문에
리페칭이 일어나게되며
리페칭시 쿼리키에 사용된 변수의 값을 참조하여 데이터 페칭이 발생하게된다.

그럼 쿼리는 언제 자동으로 데이터를 최신화 할까?

공식문서를 읽어보면 기본적으로 캐시된 데이터가 오래되었다 판단하여

쿼리를 호출할때마다 리페칭을 하게된다.

공식문서의 설명에서 처럼
데이터 최신화를 막기위해서는
리엑트 쿼리의 옵션중에 stale Time이 있다.
이 시간이 설정되어있는 시간동안은 데이터가 최신화 상태라고 간주하고
이 시간이 종료되면 데이터가 오래되었다고 판단해서 리페칭을 하게된다.

staleTime의 초기값은 0이기 때문에
기본적으로 캐싱된 데이터가 오래되었다고 판단하게 되는것이다.
따라서 이러한 리페칭을 줄이기 위해서는 해당 옵션의 값을 적절히 조절하는게 중요하다.
staleTime과 꼭 함께 알아두면 좋은것이 바로
gcTime옵션이다.
staleTime의 값만큼의 시간이 끝나기 전까지는 데이터가 최신화 된 상태로 간주하는데
리엑트 쿼리는 캐시에 저장한 데이터를 일정 시간 이상 사용하지 않는경우
삭제해버린다.

이를 관리하는 옵션이 gctime이다.

공식문서에도 5분이 기본값이라고 쓰여있다
데이터를 캐싱하고 5분동안 사용하지 않으면 데이터를 삭제시켜버린다.
만약 fetch로 가져온 api데이터가 최신화도 잘 되지 않는 자료이고
사이트에 접속한 동안에 그냥 최신화 없이 사용하고 싶은경우 이 두옵션을 반드시 조절해서 사용하는게 최적화에 좋을 것이다.

Query & Mutation

일반적으로 데이터를 가져오기만 하는 Get방식에는 useQuery가 사용되고
Post, Put, Delete와 같이 데이터를 업데이트 하는경우 useMutation를 사용한다.

데이터를 가져오는 부분인 쿼리 함수에 대해서 알아보자

쿼리 함수의 역할:
데이터를 가져오는 비동기 함수를 정의한다.
주로 API 호출을 수행하며, 데이터를 반환하는 Promise를 반환한다.

두가지 형태로 쿼리펑션을 작성해봤다.

하나는 외부에 fetch로 데이터를 가져오는 함수를 만들어 불러와서 사용하는 방법과

쿼리펑션 내부에서 직접 선언해서 사용하는 방법

결과적으로 둘다 동일한데

유지보수 측면에서나 재사용성 측면에서도

외부에 만들어서 불러와 사용하는걸 추천한다.

동일한 쿼리키로 서로다른 데이터 페칭을 하는경우

마지막으로 호출했던 쿼리펑션의 데이터가 캐싱되기 때문이다.

쿼리 키와 쿼리 평선은 리엑트 쿼리에서 직접적으로 데이터 페칭과 캐싱에 관여하기 때문에 매우 중요하다.

그외에 다양한 옵션이 존재한다.

앞서 staletime과 gctime등으로 데이터가 최신화 상태를 관리했다면

렌더링에 관여하는 부분도 존재한다.

notifyonChangeprops 옵션이다.
리엑트 쿼리는 기본적으로 서버 상태값이 변경되면 리렌더링이 되는데
해당 옵션을 통해 선택적으로 렌더링을 하는것도 가능하다.

일단 notifyonChangeprops 옵션으로 지정된 옵션은 해당 옵션이 변경사항이 생길경우에만 렌더링을 임의로 시킬 수 있다.


이러한 옵션들을 지정해서 효과적으로 렌더링을 처리가 가능한데
기본 적으로 속성이 변경되면 추적되도록 되어있어서
해당 옵션을 통해 원하는 속성만 지정해두면 그외에 속성이 변경되는경우
렌더링이 되지 않아 최적화 하는데 사용이 가능하다.


위 사진처럼

임의로 data와 error 시에만 렌더링을 하도록 하여 최적화 하는데 사용도 가능하다.

기본적으로 데이터 페칭이 발생하면 캐싱을 하게되는데
우리가 기존에 데이터를 받아와서 원하는대로 가공하여 저장하고 사용하던 방식에서 벗어나
서버의 상태값을 통채로 저장하기 때문에

원하는 데이터가 있는경우 해당 데이터만 선택적으로도 활용이 가능한데
이를 가능하게 해주는 옵션이

select옵션이다
원하는 데이터를 선택하게되면 useQuery를 호출했을때
선택한 데이터만 제공된다.
쿼리를 사용하지 않았을대라면 fetch로 가져온 데이터를 재가공하고 사용하는 경우가 많은데 재가공하지 않고 통으로 저장하기때문에 사용성이 더욱 좋아진다.
위 사진에서 보는것과 같이 filter와 사용방법이 거의 동일하다.

5.리엑트쿼리를 사용하기 전의 코드

내가 방명록을 만들기위해 작성한 코드이다.
해당 코드에서는 데이터를 가져오는 getdata가 존재하고
데이터를 추가하는 addboard라는 함수도 존재한다.
addboard 함수를 동작시키면
useEffect에 의해 getdata라는 함수를 다시 실행시키게 되고
서버에서 해당 데이터를 받아오게된다.

만약 리엑트 쿼리를 사용하게된다면 이렇게 데이터가 변경될때마다
업데이트 시키는 함수와 useEffect를 사용해서 데이터를 최신화 하는 과정이 필요하지 않고 자동으로 데이터를 다시 가져와서 보여주게 된다는 이야기이다.

  1. 쿼리를 사용한 코드

데이터를 패칭을 하는 로직을 분리시키고

쿼리 펑션에 해당 로직을 가져와서 사용했다.
코드가 훨씬 보기 편해졌다

  1. 마치며

오늘은 리엑트 쿼리에 대해서 알아보았다.

React-Query는 상태 관리에서 서버 상태와 클라이언트 상태를 분리하여 코드 가독성 및 유지보수성을 높여준다는걸
알수 있었고

데이터 페칭, 캐싱, 리페칭 등의 복잡한 작업을 간소화해 성능을 최적화하며,

중복 코드를 제거해 효율적인 개발이 가능하도록 했다.

React-Query를 사용하면 상태 관리가 쉬워지고, 코드의 일관성을 유지할 수 있어 더 나은 개발 환경을 제공한다는 점이 포인트였다고 생각한다.


스테픈2km완료

image.png

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE BLURT!