Redux 대신 Apollo Client?

Grace·2022년 6월 22일
1
post-thumbnail

2022.07.04 수정되었습니다
혹시 정정해야 할 부분이 있다면 댓글로 알려주시면 감사하겠습니다 !
추가로 학습 후 수정/보완 할 예정입니다.

데이터 통신을 통해 받아온 상태값을 관리하는 방법에 있어서 두가지를 비교해보고자 한다.
그동안 Redux에서 REST API 사용으로 인해 발생하는 over-fetching 문제에 대한 해결법을 알아보다 알게 된 apollo client에 대해 알아보자.


Redux의 상태관리

위 이미지를 기반한, 데이터를 받아와 상태를 관리할 때의 redux의 상태관리 절차를 보자면,

  1. UI(component)DOM위에 그려지기 전에 action creatorfetch 요청에 필요한 정보(url, method 등)를 액션과의 dispatch를 통해 redux에게 알려준다.
  2. REST API를 통해 미리 선언해 놓은 엔드포인트를 통해 전달 받은 데이터는 JSON형식으로 반환된다.
  3. 데이터가 준비되면 fetch작업이 완료되었다고 action을 통해 redux에게 알려준다.
  4. reducer를 통해 받은 데이터를 사용해 reduxstore에 있는 state트리를 업데이트한다.

여기서 만약 부모 컴포넌트 안에 있는 자식 컴포넌트의 state를 업데이트 해야 하는 상황이라면, 부모 컴포넌트에게서 필요한 데이터를 props로 전달받아서 업데이트 하는 과정이 추가된다 😮‍💨

자식 컴포넌트 한개를 렌더링 하기 위해서 너무나 복잡한 절차가 필요하고, 이 외에도 REST APIover-fetching이나 under-fetching의 문제까지..

Apollo Client란,

Apollo ClientGraphQl 기반의 라이브러리로,
클라이언트 어플리케이션의 GraphQl과 데이터 교환을 돕는다

우선 두괄식으로 얘기해보자면,
Apollo Client를 사용하게 되면,
Redux처럼 따로 action, reducer, type 설정 등의 부과적인 작업 없이 데이터를 불러오는 것이 가능해진다.
또한 필요한 데이터만 선택적으로 가져오는 것이 가능해진다!

간단하게 작업해볼 수 있는 자료를 찾아서, 정리해보기로 했다.

패키지 설치하기

미리 생성한 리엑트 프로젝트에 Apollo Client를 사용하기 위해선 두가지 패키지 설치가 필요하다.

npm install @apollo/client graphql
  • @apollo/client : Apllo에서 제공하는 GraphQl 클라이언트 패키지
    => GraphQl API 서버와 통신할 수 있는 React Hook 기반 함수, ApolloProvider 등을 제공한다.
  • graphql : GraphQl스펙을 javascript언어로 구현한 패키지
    => Apollo Client나 Apollo Server 모두 내부적으로 GraphQl에 의존하고 있기 때문에 함께 설치가 필요하다.

Apollo Client 생성하기

Apollo Client를 생성할 때에는 GraphQl API의 접속정보 설정이 필요하다.

import { ApolloClient } from '@apollo/client';

export const client = new ApolloClient({
  uri: "https://countries.trevorblades.com",
});

위 uri를 접속해보면, schema에 대한 정보가 있다.
그 중에 내가 사용할 continent에 대한 정보를 보면,

이렇게 세가지 필드가 들어있는데,
REST API와 다르게 GraphQl API를 사용하면 원하는 값들만 가져와서 사용할 수 있다.
(REST API를 사용하면, 모든 값을 가져와서 용도에 맞게 조작하는 과정이 필요하다)

Apollo Client 연결하기

import React from 'react';
import { ApolloProvider } from '@apollo/client';
import { client } from 'apollo/client';
import Home from 'components/home';

function App() {
  return (
    <ApolloProvider client={client}>
    	<Home />
    </ApolloProvider>
  );
}

export default App;

ApolloProvider는 Context API의 Provider처럼 최상위 컴포넌트로
위치시켜서 사용하면, 어느 위치에서든 Apollo client에 접근이 가능해진다.

GraphQl API 호출하기

import React from 'react';
import { gql, useQuery } from '@apollo/client';

const GET_CONTINENTS = gql`
	query {
		continents {
			code
			name
		}
	}
`

function Home() {
  const { loading, error, data } = useQuery(GET_CONTINTNES);
  const datas = data?.continents.length !== 0 ? data?.continents : null;
  
  if(loading) return <Loading />;
  if(error) return <Error />;
  return (
    <>
    	<h2>Continents</h2>
    	<ul>
          {datas.map((data) => (
              <li key={data.code}>{data.name}</li>
  			))}
		</ul>
	</>
   );
}

export default Home;
  • @apollo/client에서 제공하는 gql이라는 template literal tag를 사용해서 일반 자바스크립트 문자열을 GraphQL 구문으로 바꿔준다.
  • 위 작업 후 useQuery에 넘겨주면, apollo client가 graphql 서버로 graphql 쿼리를 요청하고 응답을 반환한다.
  • 반환된 data는 optional chaining을 사용하여 값이 null이 아닐 경우에만 조회하여 오류를 방지한다.

이번엔 간단하게 데이터를 가져와서 나열하는 작업을 해보았다.

fetch작업을 통해 가져온 데이터의 상태관리에 있어서는,
그 데이터의 상태 관리를 위해 액션, 리듀서 등의 작성이 없이
바로 쿼리문을 통해 데이터를 받아오고 관리가 가능하다는 것이 흥미로웠다.

🚩 정정한 부분
이번 포스팅을 작성하게 된 계기는 apollo client를 접하게 되고, redux를 대체해서 사용할 수 있다는 글을 읽게 되어 공부를 하게 되었다.
그래서 처음엔 apollo client상태관리로서의 역할을 한다고 생각을 했는데, 어떤 번역문을 읽으면서 제대로 된 이해를 하게 되었다.

내가 직접 redux를 통해 상태관리를 했던 경험을 떠올리다보니, 대부분이
서버에서 가져온 데이터를 관리하는 것이었다.
그러다보니 이번 포스팅에서 말했던 것 처럼, graphQl로 서버와 통신할 경우에 apollo client를 사용하면 redux를 사용하던 것 처럼 복잡한 작업(액션, 리듀서, 사가 등의 작성)이 많이 줄어들 수 있다는 것을 알게 되었다.
또한 서버에서 가져온 데이터를 apollo client로 관리하면, UI를 위한 클라이언트의 상태관리 대부분은 react의 상태관리 만으로도 가능해진다는 말을 이해하게 되었다.

물론 graphQl API로 통신하기 위한 작업들이 필요하겠지만,
이번 포스팅을 작성하면서 apollo client에 대한 개념을 이해하는 시간이었다 :)


참고하였습니다 :)

profile
쉽게 사는건 재미가 없더군요, 새로 시작합니다🤓

4개의 댓글

comment-user-thumbnail
2022년 6월 28일

graphql 은 fetching 을 하기 위한 query 이고
이 부분을 서버에서 받아주기 위해서 서버를 띄워야 하는데 그 부분을 연결해 주는 것이 apollo 인데
(서버에서 데이터를 가져오기위한 작업)

상태관리를 하는 redux와 비교가 될까요?

1개의 답글
comment-user-thumbnail
2022년 7월 4일

좋은 글 감사합니다.

약간의 사견을 덧붙이자면, 제가 번역한 "GraphQL은 어떻게 Redux를 대체하는가"는 서로 다른 레이어에서 동작하는 두개의 기술을 한 층위에서 "대체가능하다"고 다루는 부분이 다소 논쟁적인 글이라고 생각합니다. 다만 GraphQL(보다 정확히는 Apollo Client)의 Batch Call과 Client Cache를 사용하는 경우 대부분의 일반적인 어플리케이션 단위에서 사용되는 상태 관리가 대부분 대체될 수 있다는 점에 인사이트가 있다고 생각해요.

그래서 GraphQL이 Redux를 직접 대체한다- 보다는, Fetching + Client Cache를 동시에 사용하는 방식을 통해 서버 상태에 의존하는 영역의 React 상태관리를 대체할 수 있다가 더 정확한 표현이라고 생각합니다. 이러한 맥락에서 그 이후에 등장한 Fetching/Client Cache 솔루션들(SWR, React Query 등)과 비교해보시는 것도 좋은 스터디 주제가 되지 않을까 싶네요.

참고로, 개인적으로 저는 팀내에서 자체 개발한 E2E Type-safety 솔루션(a.k.a TypeFrame) 에 SWR(https://swr.vercel.app/ko)을 결합하는 방식으로 사용하고 있습니다. 여전히 모든 상태관리 솔루션들을 대체할 수는 없지만(클라이언트에만 필요한 데이터의 경우 Atom-based 방식의 Jotai를 사용합니다) 여기서 얻은 인사이트가 현재까지도 꽤 의미있는 기술 선택-활용의 주제가 되고 있네요.

1개의 답글