현재 우리 회사는 장고에서 node.js로 백엔드를 이전🚛하는 작업 중에 있다. 그러면서 더 유연한 데이터 쿼리문 작성이 가능하고, http의 요청 횟수를 줄일 수 있는 장점을 가진 graphql을 도입하기로 했다.
백엔드를 개발하시는 CTO님이 이제 User 등 일부 서버 구축이 완료 되었다고 했다. 그래서 오늘은 React를 사용하는 프론트엔드에서 기존 RESTful 방식의 api 호출 방식과는 다른 graphql api 호출을 적용해 보았다.
참고자료: GraphQL과 RESTful API
여기 공식문서를 통해서도 알 수 있듯이, 우리는 customizable한 오픈 소스 JavaScript GraphQL 클라이언트인 Apollo-client를 사용하여 GraphQL의 query를 실행할 수 있다. (Apollo client는 타입스크립트에서도 동일하게 작동한다!)
Apollo Client은 캐싱 및 상태관리 기능 또한 지원한다. apollo client의 강력한 캐싱 기능은 클라이언트가 관심을 갖는 데이터 그래프 부분을 로컬로 복제해 놓는다. 따라서 클라이언트가 이미 캐싱된 데이터를 요청한 경우 자체적으로 데이터를 쿼리한다. 따라서 불필요한 네트워크 요청을 방지하여 성능을 크게 향상시킬 수 있다. 또한, 상태관리 기능을 지원하기 때문에 Redux도 Apollo로 대체가 가능해진다. (GraphQL과 Apollo를 쓰면, REST API와 Redux를 없애버릴 수도 있다...고 한다)
apollo-client와 비슷한 다른 선택지로는 GraphQL을 개발한 Facebook에서 직접 만든 Relay가 있지만, 이는 러닝커브가 높기도 하고, React, vue, angular 등을 동시 지원하는 apollo와 달리 react 계열만 지원한다는 단점이 있다.
(1) Get started 문서에 따라 프로젝트에 다음 패키지들을 설치해준다.
npm install @apollo/client graphql
(2) index.js 파일에서 client를 생성한다.
import { ApolloClient, InMemoryCache } from '@apollo/client';
const client = new ApolloClient({
uri: '[서버 uri]',
cache: new InMemoryCache()
});
(3) 프로젝트 최상위 컴포넌트에 ApolloProvider를 통해 client를 넘겨준다. 이러면 드디어 그 자식 컴포넌트들에서 useQuery
, useMutation
를 사용한 데이터 fetch와 update 등이 가능해진다!
import React from 'react';
import { render } from 'react-dom';
import { ApolloProvider } from '@apollo/client';
function App() {
return (
<ApolloProvider client={client}>
<div>
<h2>My first Apollo app 🚀</h2>
</div>
</ApolloProvider>
);
}
render(<App />, document.getElementById('root'));
apollo에서는 쿼리를 실행할 수 있는 useQuery훅을 제공한다. 아래 예시는 현재 로그인된 유저 정보를 가져오는 쿼리문이다.
getMe가 함수 이름이고, 넘겨 받는 파라미터가 없는 경우이다.
유저는 프로필, 몸무게, 배송지 등의 다른 여러 정보도 갖고 있지만 여기에서는 email, height, id, name 4가지 정보만 요청했다.
const GET_ME = gql`
query getMe {
me {
email
height
id
name
}
}
`;
function GHeader({ title }: GHeaderProps) {
const { data } = useQuery(GET_ME);
const handleLogout = () => {
// ...
};
return (
<Wrapper>
{//...//}
</Wrapper>
);
}
하지만, useQuery는 hook이므로 함수 내부에서 사용하는 등 조건적으로 사용될 수 었다. 그렇다면, 예를들어 '정보보기'라는 버튼을 누른 경우에만 정보를 가져오고 싶다면 어떻게 해야할까?
-> 이러한 경우 useLazyQuery를 사용해보자! (공식문서 참고)
이외에도 클라이언트에서 apollo를 더 잘 활용하기 위해 useMutation와 캐시 등 공부할 것이 많은 것 같다!! 열심히 공식문서 읽으면서 공부해야지🤓❗️