GraphQL Client 적용하기

·2023년 2월 21일

Apollo Client는 상태관리 라이브러리다.
GraphQL api에서 데이터를 fetch 해오는 것을 가능하게 해주고
어플리케이션에서 로컬로 상태 관리할 수도 있게 해준다.
서버에 있는 데이터를 가지고 오는 것, 로컬에 있는 데이터를 관리하는 것
그리고 이 둘을 동기화 할 수 있다.

npx create-react-app movieql-client

$ yarn add @apollo/client graphql react-router-dom@6

세팅 완료 후

필요없는 파일들 지워준다.

기본 셋팅으로 2가지 파일을 만든 뒤 라우터 셋팅


const { ApolloClient, InMemoryCache } = require("@apollo/client");

const client = new ApolloClient({
  uri: "http://localhost:4000/", 
  cache: new InMemoryCache(),
});

export default client;

client. js 작성한다
uri: "http://localhost:4000/"의 의미는 GraphQL 서버는 localhost:4000에서 돌아가고 있다.

cache: new InMemoryCache(),
cache strategy인데 캐싱에 대해서 다루는 거 같다.

그다음에 client가 잘 돌아가는 지 확인하기 위해서
훅을 사용할 것이다.

client.query({
query : gql`
{ 
	allMovies {
    	title
    }
    }
`
}).then(data=> console.log(data));

이후에 index.js에 추가해주면

결과가 잘나온다 😆


import React from "react";
import ReactDOM from "react-dom/client";
import client from "./routes/client.";
import App from "./App";
import { ApolloProvider } from "@apollo/client";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <ApolloProvider client={client}>
      <App />
    </ApolloProvider>
  </React.StrictMode>
);

index.js를 아폴로 감싸주고 client를 내려준다.

export default function Movies() {
  const client = useApolloClient();
  useEffect(() => {
    client
      .query({
        query: gql`
          {
            allMovies {
              title
            }
          }
        `,
      })
      .then((res) => console.log(res));
  },[client]);
  return <div>hi</div>;
}

(모든 단계를 적는 명령형, 우리가 무엇을 원하는지 적는다.)
Provider는 애플리케이션 안의 모두가 이 client에 접근할 수 있게 해준다.

아까와 동일한 값이 나온다.
usestate를 이용하여 값을 꺼내줄 수 있지만, 매번 이렇게 쓰는건 지저분하다
매력적이고 멋지게 쓰기 위해서는 Hook을 사용해야한다.

const ALL_MOVIES = gql`
  query getMovies{
    allMovies {
      title
      id
    }
  }
`;

query getMovies <-써도 되고 안써도된다.
구분하거나 의미를 두기위해 쓴다.


바로 useQuery 이용하여 훅을 만든다.
useQuery는 여러 결과들을 전달해주는데

    client: ApolloClient<any>;
    observable: ObservableQuery<TData, TVariables>;
    data: TData | undefined;
    previousData?: TData;
    error?: ApolloError;
    loading: boolean;
    networkStatus: NetworkStatus;
    called: boolean;

이러한 내용들이 결과로 온다.
const result = useQuery(ALL_MOVIES);
result를 콘솔로그를 사용해 불러주면


결과값이 이렇게 온다.
loading이 true로 되어있는데 이는 아직 데이터를 받지 못한 상태이다.
(React Query와 유사하다)


false로 변하니 데이터값을 받아왔다.
React Query와 같은 방법으로
const {data, loading] = useQuery(ALL_MOVIES); 로 선언했다.

선언형 코드를 쓰게해주기때문에 매우 깔금했다.
(선언형 코드는 설명하기위한 코드만 적는 것을 말한다.
반면에 명령형:imperative 은 모든 단계의 코드를 적고 무엇을 원하는지 작성한다.)


export default function Movies() {
  const { data, loading, error } = useQuery(ALL_MOVIES);
  if (loading) {
    return <h1>loading</h1>;
  }
  if (error) {
    return <h1>Could not fetch :(</h1>;
  }
  return (
    <div>
      {data.allMovies.map((movie) => (
        <li key={movie.id}>{movie.title}</li>
      ))}
    </div>
  );
}

로 완성한다.

useQuery로 매우 심플하게 되었다.

const ALL_MOVIES = gql`
  query getMovies {
    allMovies {
      title
      id
    }
    allTweets {
      id
      text
      author {
        fullName
      }
    }
  }
`;

아폴로 사용한거와 동이할게 쿼리를 요청하여 받아올 수 있다.


결과도 이쁘게 잘나왔다.

코드가 매우 심플해져서 만족한다.

그다음 Link를 이용해

 return (
    <div>
      <h1>Movies</h1>
      {data.allMovies.map((movie) => (
        <li key={movie.id}>
          <Link to={`/movies/${movie.id}`}>{movie.title}</Link>
        </li>
      ))}
    </div>
  );

적용시킨다.
그러면 param에 id값이 담긴다.


위 그림처럼 Variables 을 React에서 사용하려면 useQuery 훅을 사용해야한다.

const GET_MOVIE = gql`
  query getMovie($movieId: String!) {
    movie(id: $movieId) {
      id
      title
    }
  }
`;

export default function Movie() {
  const { id } = useParams();
  const { data, loading } = useQuery(GET_MOVIE, {
    variables: {
      movieId: id,
    },
  });

  if (loading) {
    return <h1>Fetching movie...</h1>;
  }
  console.log(data, loading);
  return <div>{data.movie.title}</div>;
}

두번째 파라미터에 객체를 선언한 뒤 Variables라고 선언해준다.
$movieId와 movieId는 이름을 통일해야한다.

new InMemoryCache()에 의해 한번 들어갔던 곳을 다시 들어가면 로딩을 하지않는다.

왜냐하면 캐싱 되었기 때문에 바로 title을 보여준다.


이 확장을 사용하면 캐시를 더 쉽게 확인할 수 있다.


이를 통해 빠르게 GraphQL에 대하여 확인할 수 있다.


캐싱된 정보도 확인이 가능하다.

이렇게 아폴로의 캐싱 기능도 알아보았다.
리액트 쿼리와 비슷하다는 느낌을 받았다.

profile
잘하고 싶은 사람

0개의 댓글