Apollo GraphQL 02.

김고야·2024년 1월 24일

GQL

목록 보기
2/2

@apollo/client

ReactJS 기반의 온라인 강의 영상을 보며 Apollo Client의 보일러플레이트를 해부하려 한다. 물론 백엔드에서 GQL이 구현 되어있음을 전제로 하는 예제 코드다.

app.tsx

root 파일에 해당하는 app.tsx에 보일러플레이트와 Provider를 주입해야 한다. 이 코드가 root 파일에 있기 때문에, 그 하위 컴포넌트 어디에서든 GQL로 데이터를 조회할 수 있게 된다!

import {
  ApolloClient,
  InMemoryCache,
  ApolloProvider,
  HttpLink,
  from,
} from "@apollo/client";
import { onError } from "@apollo/client/link/error";

const errorLink = onError(({ graphqlErrors, networkError }) => {
  if (graphqlErrors) {
    graphqlErrors.map(({ message, location, path }) => {
      alert(`Graphql error ${message}`);
    });
  }
});

// 에러 관리와 엔딩포인트를 변수로 선언하여 사용한다. instance.
const link = from([
  errorLink,
  new HttpLink({ uri: "http://localhost:4000/graphql" }),
]);

/* 
* client 객체를 생성한다. InMemoryCache()로 데이터 캐싱을 기본값 두고,
* link에는 link instance를 담는다.
*/
const client = new ApolloClient({
  cache: new InMemoryCache(),
  link: link,
});

export default function App() {
  return (
    <ApolloProvider client={client}>
      <Body/>
    </ApolloProvider>
  );
}

/src/graphQL/Queries.tsx

gql객체 내부에 작성되어 있는 것이 GraphQL의 query 기본형이다.
Query 객체로 시작해, 그 내부에는 백엔드에서 만들어 준 해당 Query Handler를 주입하고, 필요한 데이터 key를 그 객체 안에 다시 작성하는 방식이다. 이제 useQuery를 통해 어디에서든 이 데이터 구조와 내용을 가져올 수 있다. 데이터 명시성이 좋아 보인다.

import { gql } from "@apollo/client";

export const LOAD_USERS = gql`
  query {
    getAllUsers {
      id
      firstName
      email
      password
    }
  }
`;

/src/graphQL/Mutation.tsx

이 부분은 createUser라는 POST 메소드를 위한 Mutation Query를 작성한 코드다. 이 Query를 호출하면, GQL로 작성된 백엔드 서버 데이터베이스에 해당 규격에 통과된 데이터를 POST할 수 있다. PUT이나 PATCH도 동일한 Query를 작성해 사용할 수 있겠다.

import { gql } from "@apollo/client";

/*
* 특징적이지만, JS 프로젝트라고 해도, 이렇게 타입을 작성해야 한다.
* mutaition createUser() 라는 객체 내부에, 다시 creatUser라는 
* 백엔드 핸들러 객체를 중첩하여 작성해야만 구동된다.
*/
export const CREATE_USER_MUTATION = gql`
  mutation createUser(
    $firstName: String!
    $lastName: String!
    $email: String!
    $password: String
  ) {
    createUser(
      firstName: $firstName
      lastName: $lastName
      email: $email
      password: $password
    ) {
      id
    }
  }
`;

/src/pages/Body.tsx

apollo의 useQuery()를 사용해, 데이터를 조회하는 페이지 컴포넌트의 코드.

import { useEffect, useState } from "react";
import { useQuery, gql } from "@apollo/client";
import { LOAD_USERS } from "../GraphQL/Queries";


export default function Body() {
  /*
  * useQuery()는 인자로 LOAD_USERS라는 Query를 받는다.
  * custom hooks처럼 필요한 item을 가져와 사용하면 된다.
  * setUsers에 data의 getAllUsers 엔티티를 넣어주고 있다.
  */
  const { error, loading, data } = useQuery(LOAD_USERS);
  const [users, setUsers] = useState([]);
  
  useEffect(() => {
    if (data) {
      setUsers(data.getAllUsers);
    }
  }, [data]);

  return (
    <div>
      {/* 
      {users.map((val) => {
        return <h1> {val.firstName}</h1>;
      })} */}
    </div>
  );
}

/src/Create.tsx

Mutation 쪽의 코드는 약간 복잡한데, 기본적으로는 State에 event value를 삽입하여, 데이터 요청하는 구조는 익숙한 그 자체이다. 다만 CREATE_USER_MUTATION이라는 Query를 담보로 하는 createUser 핸들러를 직접 이용해, event handler를 사용해야 한다.

import { useState } from "react";
import { useMutation } from "@apollo/client";
import { CREATE_USER_MUTATION } from "../GraphQL/Mutations";

export default function Create() {
  // state 4개와 input jsx 4개는 생략한다.
  const [firstName, setFirstName] = useState("");
  ...
 /* 
  * createUser GQL 서버 핸들러와 CREATE_USER_MUTATION 클라이언트 
  * Query를 기본으로 createUser 메소드를 활성시킨다.
 */
  const [createUser] = useMutation(CREATE_USER_MUTATION);

  const addUser = () => {
    createUser({
      /* 
      * 일종의 컨벤션으로 지켜야하는 부분이다. State로 담겨진 데이터를 
      * variables 객체로 감싸야 한다. 
      */
      variables: {
        firstName: firstName,
        lastName: lastName,
        email: email,
        password: password,
        },
      });
    };
  return (
    <div>
      <input
        type="text"
        placeholder="First Name"
        onChange={(e) => {
          setFirstName(e.target.value);
        }}
      />
      ...
      <button onClick={addUser}>Create!</button>
    </div>
  );
}
profile
Frontend Engineer

0개의 댓글